BALL
1.4.1
|
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.4. Before that, they were always recursive. 00112 #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 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