File indexing completed on 2025-01-18 09:30:12
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_CONTAINER_MUTEX_HPP
0015 #define BOOST_CONTAINER_MUTEX_HPP
0016
0017 #ifndef BOOST_CONFIG_HPP
0018 # include <boost/config.hpp>
0019 #endif
0020
0021 #if defined(BOOST_HAS_PRAGMA_ONCE)
0022 # pragma once
0023 #endif
0024
0025
0026
0027
0028 #include <boost/container/detail/config_begin.hpp>
0029 #include <boost/container/detail/workaround.hpp>
0030
0031
0032
0033
0034
0035 #define BOOST_MUTEX_HELPER_NONE 0
0036 #define BOOST_MUTEX_HELPER_WIN32 1
0037 #define BOOST_MUTEX_HELPER_PTHREAD 2
0038 #define BOOST_MUTEX_HELPER_SPINLOCKS 3
0039
0040 #if !defined(BOOST_HAS_THREADS) && !defined(BOOST_NO_MT)
0041 # define BOOST_NO_MT
0042 #endif
0043
0044 #if defined(BOOST_NO_MT) || defined(BOOST_CONTAINER_NO_MT)
0045
0046 #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_NONE
0047 #else
0048
0049 #if !defined(BOOST_CONTAINER_NO_SPINLOCKS) && \
0050 ((defined(__GNUC__) && \
0051 ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \
0052 defined(__i386__) || defined(__x86_64__))) || \
0053 (defined(_MSC_VER) && _MSC_VER>=1310))
0054 #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_SPINLOCKS
0055 #elif defined(BOOST_HAS_UNISTD_H)
0056 #include <unistd.h>
0057 #if !defined(BOOST_MUTEX_HELPER) && (defined(_POSIX_THREADS) || defined(BOOST_HAS_PTHREADS))
0058 #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_PTHREAD
0059 #endif
0060 #endif
0061 #endif
0062
0063 #ifndef BOOST_MUTEX_HELPER
0064 #error Unable to determine platform mutex type; #define BOOST_NO_MT to assume single-threaded
0065 #endif
0066
0067 #if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
0068
0069 #elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
0070 #if defined(_MSC_VER)
0071 #include <intrin.h>
0072 #define interlockedexchange _InterlockedExchange
0073 #elif defined(WIN32) && defined(__GNUC__)
0074 #define interlockedexchange __sync_lock_test_and_set
0075 #endif
0076
0077
0078
0079
0080 #if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
0081 #define BOOST_CONTAINER_CAS_LOCK(sl) __sync_lock_test_and_set(sl, 1)
0082 #define BOOST_CONTAINER_CLEAR_LOCK(sl) __sync_lock_release(sl)
0083
0084 #elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
0085
0086 static inline int boost_container_x86_cas_lock(int *sl) {
0087 int ret;
0088 int val = 1;
0089 int cmp = 0;
0090 __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
0091 : "=a" (ret)
0092 : "r" (val), "m" (*(sl)), "0"(cmp)
0093 : "memory", "cc");
0094 return ret;
0095 }
0096
0097 static inline void boost_container_x86_clear_lock(int* sl) {
0098 assert(*sl != 0);
0099 int prev = 0;
0100 int ret;
0101 __asm__ __volatile__ ("lock; xchgl %0, %1"
0102 : "=r" (ret)
0103 : "m" (*(sl)), "0"(prev)
0104 : "memory");
0105 }
0106
0107 #define BOOST_CONTAINER_CAS_LOCK(sl) boost_container_x86_cas_lock(sl)
0108 #define BOOST_CONTAINER_CLEAR_LOCK(sl) boost_container_x86_clear_lock(sl)
0109
0110 #else
0111 #define BOOST_CONTAINER_CAS_LOCK(sl) interlockedexchange((long volatile*)sl, (long)1)
0112 #define BOOST_CONTAINER_CLEAR_LOCK(sl) interlockedexchange((long volatile*)sl, (long)0)
0113 #endif
0114
0115
0116 #define SPINS_PER_YIELD 63
0117 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
0118 #if !defined( BOOST_USE_WINDOWS_H )
0119 #if defined (WIN32_PLATFORM_PSPC)
0120 #define BOOST_CONTAINERWINAPI_IMPORT BOOST_SYMBOL_IMPORT
0121 #elif defined (_WIN32_WCE)
0122 #define BOOST_CONTAINERWINAPI_IMPORT
0123 #else
0124 #define BOOST_CONTAINERWINAPI_IMPORT BOOST_SYMBOL_IMPORT
0125 #endif
0126
0127 #if defined(WINAPI)
0128 #define BOOST_CONTAINERWINAPI_WINAPI_CC WINAPI
0129 #else
0130 #if defined(_M_IX86) || defined(__i386__)
0131 #define BOOST_CONTAINERWINAPI_DETAIL_STDCALL __stdcall
0132 #else
0133 #define BOOST_CONTAINERWINAPI_DETAIL_STDCALL
0134 #endif
0135 #define BOOST_CONTAINERWINAPI_WINAPI_CC BOOST_CONTAINERWINAPI_DETAIL_STDCALL
0136 #endif
0137
0138 #if !defined(__LP64__)
0139 namespace boost {
0140 namespace container_winapi {
0141 typedef unsigned long DWORD_;
0142 #else
0143 typedef unsigned int DWORD_;
0144 #endif
0145 typedef int BOOL_;
0146 }}
0147
0148 extern "C" {
0149 BOOST_CONTAINERWINAPI_IMPORT boost::container_winapi::DWORD_ BOOST_CONTAINERWINAPI_WINAPI_CC
0150 SleepEx(
0151 boost::container_winapi::DWORD_ dwMilliseconds,
0152 boost::container_winapi::BOOL_ bAlertable);
0153 }
0154 #endif
0155
0156 namespace boost {
0157 namespace container_winapi {
0158 using ::SleepEx;
0159 }
0160 }
0161
0162 #define SLEEP_EX_DURATION 50
0163 #define SPIN_LOCK_YIELD boost::container_winapi::SleepEx(SLEEP_EX_DURATION, 0)
0164 #elif defined (__SVR4) && defined (__sun)
0165 #include <thread.h>
0166 #define SPIN_LOCK_YIELD thr_yield();
0167 #elif !defined(LACKS_SCHED_H)
0168 #include <sched.h>
0169 #define SPIN_LOCK_YIELD sched_yield();
0170 #else
0171 #define SPIN_LOCK_YIELD
0172 #endif
0173
0174 #define BOOST_CONTAINER_SPINS_PER_YIELD 63
0175 inline int boost_interprocess_spin_acquire_lock(int *sl) {
0176 int spins = 0;
0177 while (*(volatile int *)sl != 0 ||
0178 BOOST_CONTAINER_CAS_LOCK(sl)) {
0179 if ((++spins & BOOST_CONTAINER_SPINS_PER_YIELD) == 0) {
0180 SPIN_LOCK_YIELD;
0181 }
0182 }
0183 return 0;
0184 }
0185 #define BOOST_CONTAINER_MLOCK_T int
0186 #define BOOST_CONTAINER_TRY_LOCK(sl) !BOOST_CONTAINER_CAS_LOCK(sl)
0187 #define BOOST_CONTAINER_RELEASE_LOCK(sl) BOOST_CONTAINER_CLEAR_LOCK(sl)
0188 #define BOOST_CONTAINER_ACQUIRE_LOCK(sl) (BOOST_CONTAINER_CAS_LOCK(sl)? boost_interprocess_spin_acquire_lock(sl) : 0)
0189 #define BOOST_MOVE_INITIAL_LOCK(sl) (*sl = 0)
0190 #define BOOST_CONTAINER_DESTROY_LOCK(sl) (0)
0191 #elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
0192
0193 #elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
0194 #include <pthread.h>
0195 #endif
0196
0197 namespace boost {
0198 namespace container {
0199 namespace dtl {
0200
0201 #if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
0202 class null_mutex
0203 {
0204 private:
0205 null_mutex(const null_mutex &);
0206 void operator=(const null_mutex &);
0207
0208 public:
0209 null_mutex() { }
0210
0211 static void lock() { }
0212 static void unlock() { }
0213 };
0214
0215 typedef null_mutex default_mutex;
0216 #elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
0217
0218 class spin_mutex
0219 {
0220 private:
0221 BOOST_CONTAINER_MLOCK_T sl;
0222 spin_mutex(const spin_mutex &);
0223 void operator=(const spin_mutex &);
0224
0225 public:
0226 spin_mutex() { BOOST_MOVE_INITIAL_LOCK(&sl); }
0227
0228 void lock() { BOOST_CONTAINER_ACQUIRE_LOCK(&sl); }
0229 void unlock() { BOOST_CONTAINER_RELEASE_LOCK(&sl); }
0230 };
0231 typedef spin_mutex default_mutex;
0232 #elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
0233 class mutex
0234 {
0235 private:
0236 CRITICAL_SECTION mtx;
0237
0238 mutex(const mutex &);
0239 void operator=(const mutex &);
0240
0241 public:
0242 mutex()
0243 { InitializeCriticalSection(&mtx); }
0244
0245 ~mutex()
0246 { DeleteCriticalSection(&mtx); }
0247
0248 void lock()
0249 { EnterCriticalSection(&mtx); }
0250
0251 void unlock()
0252 { LeaveCriticalSection(&mtx); }
0253 };
0254
0255 typedef mutex default_mutex;
0256 #elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
0257 class mutex
0258 {
0259 private:
0260 pthread_mutex_t mtx;
0261
0262 mutex(const mutex &);
0263 void operator=(const mutex &);
0264
0265 public:
0266 mutex()
0267 { pthread_mutex_init(&mtx, 0); }
0268
0269 ~mutex()
0270 { pthread_mutex_destroy(&mtx); }
0271
0272 void lock()
0273 { pthread_mutex_lock(&mtx); }
0274
0275 void unlock()
0276 { pthread_mutex_unlock(&mtx); }
0277 };
0278
0279 typedef mutex default_mutex;
0280 #endif
0281
0282 template<class Mutex>
0283 class scoped_lock
0284 {
0285 public:
0286 scoped_lock(Mutex &m)
0287 : m_(m)
0288 { m_.lock(); }
0289 ~scoped_lock()
0290 { m_.unlock(); }
0291
0292 private:
0293 Mutex &m_;
0294 };
0295
0296 }
0297 }
0298 }
0299
0300 #undef BOOST_MUTEX_HELPER_WIN32
0301 #undef BOOST_MUTEX_HELPER_PTHREAD
0302 #undef BOOST_MUTEX_HELPER_NONE
0303 #undef BOOST_MUTEX_HELPER
0304 #undef BOOST_MUTEX_HELPER_SPINLOCKS
0305
0306 #include <boost/container/detail/config_end.hpp>
0307
0308 #endif