mutex.h

Go to the documentation of this file.
00001 // -*- Mode: C++; tab-width: 2; -*-
00002 // vi: set ts=2:
00003 //
00004 
00005 #ifndef BALL_SYSTEM_MUTEX_H
00006 #define BALL_SYSTEM_MUTEX_H
00007 
00008 #ifndef BALL_COMMON_GLOBAL_H
00009 # include <BALL/COMMON/global.h>
00010 #endif
00011 
00012 #include <QtCore/QMutex>
00013 #include <QtCore/QReadWriteLock>
00014 #include <QtCore/QMutexLocker>
00015 #include <QtCore/QReadLocker>
00016 #include <QtCore/QWriteLocker>
00017 
00018 #ifdef BALL_HAS_BOOST_THREAD
00019 # include <boost/version.hpp>
00020 # if BOOST_VERSION >= 103500
00021 # include <boost/thread/mutex.hpp>
00022 # define BALL_HAS_BOOST_MUTEX
00023 # endif
00024 #endif
00025 
00026 #undef BALL_USE_THREAD_CHECKER_API
00027 #ifdef BALL_USE_THREAD_CHECKER_API
00028 # include <libittnotify.h>
00029 #endif
00030 
00031 #define BALL_DEFAULT_MUTEX_TYPE QMutex
00032 #define BALL_DEFAULT_MUTEXLOCKER_TYPE QMutexLocker
00033 #define BALL_DEFAULT_READWRITELOCK_TYPE QReadWriteLock
00034 #define BALL_DEFAULT_READLOCKER_TYPE QReadLocker
00035 #define BALL_DEFAULT_WRITELOCKER_TYPE QWriteLocker
00036 
00037 namespace BALL
00038 {
00046   template <class MutexType>
00047   class TMutex
00048     : public MutexType
00049   {
00050     public:
00051       TMutex(bool is_recursive = false)
00052         : MutexType()
00053       {}
00054   };
00055 
00056   template <>
00057   class TMutex<QMutex>
00058     : public QMutex
00059   {
00060     public:
00061       TMutex(bool is_recursive = false)
00062         : QMutex( is_recursive ? Recursive : NonRecursive )
00063       {
00064       }
00065   };
00066 
00077   template <class MutexLockerType, class MutexType>
00078   class TMutexLocker
00079     : public MutexLockerType
00080   {
00081     public:
00082       TMutexLocker(MutexType* mutex)
00083         : MutexLockerType(mutex)
00084       {}
00085   };
00086 
00095   template <class ReadWriteLockType>
00096   class TReadWriteLock
00097     : public ReadWriteLockType
00098   {
00099     public:
00100       TReadWriteLock(bool is_recursive = false)
00101         : ReadWriteLockType()
00102       {}
00103   };
00104 
00105   template <>
00106   class TReadWriteLock<QReadWriteLock>
00107     : public QReadWriteLock
00108   {
00109     public:
00110       TReadWriteLock(bool is_recursive = false)
00111 // NOTE: Qt only supports non-recursive read write locks since version 4.3. Before that, they were always recursive.
00112 #if (QT_VERSION >= QT_VERSION_CHECK(4, 3, 0))
00113         : QReadWriteLock( is_recursive ? Recursive : NonRecursive )
00114 #else
00115         : QReadWriteLock()
00116 #endif
00117       {
00118       }
00119   };
00120 
00131   template <class ReadLockerType, class ReadWriteLockType>
00132   class TReadLocker
00133     : public ReadLockerType
00134   {
00135     public:
00136       TReadLocker(ReadWriteLockType* lock)
00137         : ReadLockerType(lock)
00138       {}
00139   };
00140 
00151   template <class WriteLockerType, class ReadWriteLockType>
00152   class TWriteLocker
00153     : public WriteLockerType
00154   {
00155     public:
00156       TWriteLocker(ReadWriteLockType* lock)
00157         : WriteLockerType(lock)
00158       {}
00159   };
00160 
00161 
00162 
00163 #ifdef BALL_HAS_BOOST_MUTEX
00164   // Boost-based mutexes only require a mapping of tryLock to try_lock.
00165   template <>
00166   class TMutex<boost::mutex>
00167     : public boost::mutex
00168   {
00169     public:
00170       TMutex()
00171         : boost::mutex()
00172       {}
00173 
00174       void lock()
00175       {
00176         return boost::mutex::lock();
00177       }
00178 
00179       bool tryLock()
00180       {
00181         return try_lock();
00182       }
00183   };
00184 
00185 #endif
00186 
00187 
00188 #ifdef BALL_USE_THREAD_CHECKER_API
00189   template <>
00190   class TMutex<QMutex>
00191     : public QMutex
00192   {
00193     public:
00194       TMutex()
00195         : QMutex()
00196       {
00197       }
00198 
00199       void lock()
00200       {
00201         __itt_notify_sync_prepare((void *)this);
00202         QMutex::lock();
00203         __itt_notify_sync_acquired((void*)this);
00204       }
00205 
00206       void unlock()
00207       {
00208         __itt_notify_sync_releasing((void *)this);
00209         QMutex::unlock();
00210       }
00211 
00212       bool tryLock()
00213       {
00214         __itt_notify_sync_prepare((void*)this);
00215         bool result = QMutex::tryLock();
00216 
00217         if (result)
00218           __itt_notify_sync_acquired((void*)this);
00219         else
00220           __itt_notify_sync_cancel((void*)this);
00221 
00222         return result;
00223       }
00224   };
00225 
00226   // TODO: similar instantiation for TReadWriteLock
00227 
00228 #else
00229 // required for visual studio
00230 #ifdef BALL_COMPILER_MSVC
00231   //template class BALL_EXPORT TMutex<BALL_DEFAULT_MUTEX_TYPE>;
00232   //template class BALL_EXPORT TReadWriteLock<BALL_DEFAULT_READWRITELOCK_TYPE>;
00233   template class BALL_EXPORT TMutexLocker<BALL_DEFAULT_MUTEXLOCKER_TYPE, BALL_DEFAULT_MUTEX_TYPE>;
00234   template class BALL_EXPORT TReadLocker<BALL_DEFAULT_READLOCKER_TYPE, BALL_DEFAULT_READWRITELOCK_TYPE>;
00235   template class BALL_EXPORT TWriteLocker<BALL_DEFAULT_WRITELOCKER_TYPE, BALL_DEFAULT_READWRITELOCK_TYPE>;
00236 #endif
00237 #endif
00238 
00239   // the standard mutex to use
00240   typedef TMutex<BALL_DEFAULT_MUTEX_TYPE> Mutex;
00241   typedef TReadWriteLock<BALL_DEFAULT_READWRITELOCK_TYPE> ReadWriteLock;
00242   typedef TMutexLocker<BALL_DEFAULT_MUTEXLOCKER_TYPE, BALL_DEFAULT_MUTEX_TYPE> MutexLocker;
00243   typedef TReadLocker<BALL_DEFAULT_READLOCKER_TYPE, BALL_DEFAULT_READWRITELOCK_TYPE> ReadLocker;
00244   typedef TWriteLocker<BALL_DEFAULT_WRITELOCKER_TYPE, BALL_DEFAULT_READWRITELOCK_TYPE> WriteLocker;
00245 }
00246 
00247 #endif // BALL_SYSTEM_MUTEX_H
00248