annotate DEPENDENCIES/generic/include/boost/container/detail/mutex.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents f46d142149f5
children
rev   line source
Chris@102 1 // Copyright (C) 2000 Stephen Cleary
Chris@102 2 //
Chris@102 3 // Distributed under the Boost Software License, Version 1.0. (See
Chris@102 4 // accompanying file LICENSE_1_0.txt or copy at
Chris@102 5 // http://www.boost.org/LICENSE_1_0.txt)
Chris@102 6 //
Chris@102 7 // See http://www.boost.org for updates, documentation, and revision history.
Chris@102 8
Chris@102 9 //////////////////////////////////////////////////////////////////////////////
Chris@102 10 //
Chris@102 11 // (C) Copyright Ion Gaztanaga 2007-2013. Distributed under the Boost
Chris@102 12 // Software License, Version 1.0. (See accompanying file
Chris@102 13 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@102 14 //
Chris@102 15 // See http://www.boost.org/libs/container for documentation.
Chris@102 16 //
Chris@102 17 //////////////////////////////////////////////////////////////////////////////
Chris@102 18
Chris@102 19 #ifndef BOOST_CONTAINER_MUTEX_HPP
Chris@102 20 #define BOOST_CONTAINER_MUTEX_HPP
Chris@102 21
Chris@102 22 #ifndef BOOST_CONFIG_HPP
Chris@102 23 # include <boost/config.hpp>
Chris@102 24 #endif
Chris@102 25
Chris@102 26 #if defined(BOOST_HAS_PRAGMA_ONCE)
Chris@102 27 # pragma once
Chris@102 28 #endif
Chris@102 29
Chris@102 30 //#define BOOST_CONTAINER_NO_MT
Chris@102 31 //#define BOOST_CONTAINER_NO_SPINLOCKS
Chris@102 32
Chris@102 33 #include <boost/container/detail/config_begin.hpp>
Chris@102 34 #include <boost/container/detail/workaround.hpp>
Chris@102 35
Chris@102 36 // Extremely Light-Weight wrapper classes for OS thread synchronization
Chris@102 37
Chris@102 38 #define BOOST_MUTEX_HELPER_NONE 0
Chris@102 39 #define BOOST_MUTEX_HELPER_WIN32 1
Chris@102 40 #define BOOST_MUTEX_HELPER_PTHREAD 2
Chris@102 41 #define BOOST_MUTEX_HELPER_SPINLOCKS 3
Chris@102 42
Chris@102 43 #if !defined(BOOST_HAS_THREADS) && !defined(BOOST_NO_MT)
Chris@102 44 # define BOOST_NO_MT
Chris@102 45 #endif
Chris@102 46
Chris@102 47 #if defined(BOOST_NO_MT) || defined(BOOST_CONTAINER_NO_MT)
Chris@102 48 // No multithreading -> make locks into no-ops
Chris@102 49 #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_NONE
Chris@102 50 #else
Chris@102 51 //Taken from dlmalloc
Chris@102 52 #if !defined(BOOST_CONTAINER_NO_SPINLOCKS) && \
Chris@102 53 ((defined(__GNUC__) && \
Chris@102 54 ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \
Chris@102 55 defined(__i386__) || defined(__x86_64__))) || \
Chris@102 56 (defined(_MSC_VER) && _MSC_VER>=1310))
Chris@102 57 #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_SPINLOCKS
Chris@102 58 #endif
Chris@102 59
Chris@102 60 #if defined(BOOST_WINDOWS)
Chris@102 61 #include <windows.h>
Chris@102 62 #ifndef BOOST_MUTEX_HELPER
Chris@102 63 #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_WIN32
Chris@102 64 #endif
Chris@102 65 #elif defined(BOOST_HAS_UNISTD_H)
Chris@102 66 #include <unistd.h>
Chris@102 67 #if !defined(BOOST_MUTEX_HELPER) && (defined(_POSIX_THREADS) || defined(BOOST_HAS_PTHREADS))
Chris@102 68 #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_PTHREAD
Chris@102 69 #endif
Chris@102 70 #endif
Chris@102 71 #endif
Chris@102 72
Chris@102 73 #ifndef BOOST_MUTEX_HELPER
Chris@102 74 #error Unable to determine platform mutex type; #define BOOST_NO_MT to assume single-threaded
Chris@102 75 #endif
Chris@102 76
Chris@102 77 #if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
Chris@102 78 //...
Chris@102 79 #elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
Chris@102 80 #if defined(_MSC_VER)
Chris@102 81 #ifndef _M_AMD64
Chris@102 82 /* These are already defined on AMD64 builds */
Chris@102 83 #ifdef __cplusplus
Chris@102 84 extern "C" {
Chris@102 85 #endif /* __cplusplus */
Chris@102 86 long __cdecl _InterlockedCompareExchange(long volatile *Dest, long Exchange, long Comp);
Chris@102 87 long __cdecl _InterlockedExchange(long volatile *Target, long Value);
Chris@102 88 #ifdef __cplusplus
Chris@102 89 }
Chris@102 90 #endif /* __cplusplus */
Chris@102 91 #endif /* _M_AMD64 */
Chris@102 92 #pragma intrinsic (_InterlockedCompareExchange)
Chris@102 93 #pragma intrinsic (_InterlockedExchange)
Chris@102 94 #define interlockedcompareexchange _InterlockedCompareExchange
Chris@102 95 #define interlockedexchange _InterlockedExchange
Chris@102 96 #elif defined(WIN32) && defined(__GNUC__)
Chris@102 97 #define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b)
Chris@102 98 #define interlockedexchange __sync_lock_test_and_set
Chris@102 99 #endif /* Win32 */
Chris@102 100
Chris@102 101 /* First, define CAS_LOCK and CLEAR_LOCK on ints */
Chris@102 102 /* Note CAS_LOCK defined to return 0 on success */
Chris@102 103
Chris@102 104 #if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
Chris@102 105 #define BOOST_CONTAINER_CAS_LOCK(sl) __sync_lock_test_and_set(sl, 1)
Chris@102 106 #define BOOST_CONTAINER_CLEAR_LOCK(sl) __sync_lock_release(sl)
Chris@102 107
Chris@102 108 #elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
Chris@102 109 /* Custom spin locks for older gcc on x86 */
Chris@102 110 static FORCEINLINE int boost_container_x86_cas_lock(int *sl) {
Chris@102 111 int ret;
Chris@102 112 int val = 1;
Chris@102 113 int cmp = 0;
Chris@102 114 __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
Chris@102 115 : "=a" (ret)
Chris@102 116 : "r" (val), "m" (*(sl)), "0"(cmp)
Chris@102 117 : "memory", "cc");
Chris@102 118 return ret;
Chris@102 119 }
Chris@102 120
Chris@102 121 static FORCEINLINE void boost_container_x86_clear_lock(int* sl) {
Chris@102 122 assert(*sl != 0);
Chris@102 123 int prev = 0;
Chris@102 124 int ret;
Chris@102 125 __asm__ __volatile__ ("lock; xchgl %0, %1"
Chris@102 126 : "=r" (ret)
Chris@102 127 : "m" (*(sl)), "0"(prev)
Chris@102 128 : "memory");
Chris@102 129 }
Chris@102 130
Chris@102 131 #define BOOST_CONTAINER_CAS_LOCK(sl) boost_container_x86_cas_lock(sl)
Chris@102 132 #define BOOST_CONTAINER_CLEAR_LOCK(sl) boost_container_x86_clear_lock(sl)
Chris@102 133
Chris@102 134 #else /* Win32 MSC */
Chris@102 135 #define BOOST_CONTAINER_CAS_LOCK(sl) interlockedexchange((long volatile*)sl, (long)1)
Chris@102 136 #define BOOST_CONTAINER_CLEAR_LOCK(sl) interlockedexchange((long volatile*)sl, (long)0)
Chris@102 137 #endif
Chris@102 138
Chris@102 139 /* How to yield for a spin lock */
Chris@102 140 #define SPINS_PER_YIELD 63
Chris@102 141 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
Chris@102 142 #define SLEEP_EX_DURATION 50 /* delay for yield/sleep */
Chris@102 143 #define SPIN_LOCK_YIELD SleepEx(SLEEP_EX_DURATION, FALSE)
Chris@102 144 #elif defined (__SVR4) && defined (__sun) /* solaris */
Chris@102 145 #include <thread.h>
Chris@102 146 #define SPIN_LOCK_YIELD thr_yield();
Chris@102 147 #elif !defined(LACKS_SCHED_H)
Chris@102 148 #include <sched.h>
Chris@102 149 #define SPIN_LOCK_YIELD sched_yield();
Chris@102 150 #else
Chris@102 151 #define SPIN_LOCK_YIELD
Chris@102 152 #endif /* ... yield ... */
Chris@102 153
Chris@102 154 #define BOOST_CONTAINER_SPINS_PER_YIELD 63
Chris@102 155 inline int boost_interprocess_spin_acquire_lock(int *sl) {
Chris@102 156 int spins = 0;
Chris@102 157 while (*(volatile int *)sl != 0 ||
Chris@102 158 BOOST_CONTAINER_CAS_LOCK(sl)) {
Chris@102 159 if ((++spins & BOOST_CONTAINER_SPINS_PER_YIELD) == 0) {
Chris@102 160 SPIN_LOCK_YIELD;
Chris@102 161 }
Chris@102 162 }
Chris@102 163 return 0;
Chris@102 164 }
Chris@102 165 #define BOOST_CONTAINER_MLOCK_T int
Chris@102 166 #define BOOST_CONTAINER_TRY_LOCK(sl) !BOOST_CONTAINER_CAS_LOCK(sl)
Chris@102 167 #define BOOST_CONTAINER_RELEASE_LOCK(sl) BOOST_CONTAINER_CLEAR_LOCK(sl)
Chris@102 168 #define BOOST_CONTAINER_ACQUIRE_LOCK(sl) (BOOST_CONTAINER_CAS_LOCK(sl)? boost_interprocess_spin_acquire_lock(sl) : 0)
Chris@102 169 #define BOOST_MOVE_INITIAL_LOCK(sl) (*sl = 0)
Chris@102 170 #define BOOST_CONTAINER_DESTROY_LOCK(sl) (0)
Chris@102 171 #elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
Chris@102 172 //
Chris@102 173 #elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
Chris@102 174 #include <pthread.h>
Chris@102 175 #endif
Chris@102 176
Chris@102 177 namespace boost {
Chris@102 178 namespace container {
Chris@102 179 namespace container_detail {
Chris@102 180
Chris@102 181 #if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
Chris@102 182 class null_mutex
Chris@102 183 {
Chris@102 184 private:
Chris@102 185 null_mutex(const null_mutex &);
Chris@102 186 void operator=(const null_mutex &);
Chris@102 187
Chris@102 188 public:
Chris@102 189 null_mutex() { }
Chris@102 190
Chris@102 191 static void lock() { }
Chris@102 192 static void unlock() { }
Chris@102 193 };
Chris@102 194
Chris@102 195 typedef null_mutex default_mutex;
Chris@102 196 #elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
Chris@102 197
Chris@102 198 class spin_mutex
Chris@102 199 {
Chris@102 200 private:
Chris@102 201 BOOST_CONTAINER_MLOCK_T sl;
Chris@102 202 spin_mutex(const spin_mutex &);
Chris@102 203 void operator=(const spin_mutex &);
Chris@102 204
Chris@102 205 public:
Chris@102 206 spin_mutex() { BOOST_MOVE_INITIAL_LOCK(&sl); }
Chris@102 207
Chris@102 208 void lock() { BOOST_CONTAINER_ACQUIRE_LOCK(&sl); }
Chris@102 209 void unlock() { BOOST_CONTAINER_RELEASE_LOCK(&sl); }
Chris@102 210 };
Chris@102 211 typedef spin_mutex default_mutex;
Chris@102 212 #elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
Chris@102 213 class mutex
Chris@102 214 {
Chris@102 215 private:
Chris@102 216 CRITICAL_SECTION mtx;
Chris@102 217
Chris@102 218 mutex(const mutex &);
Chris@102 219 void operator=(const mutex &);
Chris@102 220
Chris@102 221 public:
Chris@102 222 mutex()
Chris@102 223 { InitializeCriticalSection(&mtx); }
Chris@102 224
Chris@102 225 ~mutex()
Chris@102 226 { DeleteCriticalSection(&mtx); }
Chris@102 227
Chris@102 228 void lock()
Chris@102 229 { EnterCriticalSection(&mtx); }
Chris@102 230
Chris@102 231 void unlock()
Chris@102 232 { LeaveCriticalSection(&mtx); }
Chris@102 233 };
Chris@102 234
Chris@102 235 typedef mutex default_mutex;
Chris@102 236 #elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
Chris@102 237 class mutex
Chris@102 238 {
Chris@102 239 private:
Chris@102 240 pthread_mutex_t mtx;
Chris@102 241
Chris@102 242 mutex(const mutex &);
Chris@102 243 void operator=(const mutex &);
Chris@102 244
Chris@102 245 public:
Chris@102 246 mutex()
Chris@102 247 { pthread_mutex_init(&mtx, 0); }
Chris@102 248
Chris@102 249 ~mutex()
Chris@102 250 { pthread_mutex_destroy(&mtx); }
Chris@102 251
Chris@102 252 void lock()
Chris@102 253 { pthread_mutex_lock(&mtx); }
Chris@102 254
Chris@102 255 void unlock()
Chris@102 256 { pthread_mutex_unlock(&mtx); }
Chris@102 257 };
Chris@102 258
Chris@102 259 typedef mutex default_mutex;
Chris@102 260 #endif
Chris@102 261
Chris@102 262 template<class Mutex>
Chris@102 263 class scoped_lock
Chris@102 264 {
Chris@102 265 public:
Chris@102 266 scoped_lock(Mutex &m)
Chris@102 267 : m_(m)
Chris@102 268 { m_.lock(); }
Chris@102 269 ~scoped_lock()
Chris@102 270 { m_.unlock(); }
Chris@102 271
Chris@102 272 private:
Chris@102 273 Mutex &m_;
Chris@102 274 };
Chris@102 275
Chris@102 276 } // namespace container_detail
Chris@102 277 } // namespace container
Chris@102 278 } // namespace boost
Chris@102 279
Chris@102 280 #undef BOOST_MUTEX_HELPER_WIN32
Chris@102 281 #undef BOOST_MUTEX_HELPER_PTHREAD
Chris@102 282 #undef BOOST_MUTEX_HELPER_NONE
Chris@102 283 #undef BOOST_MUTEX_HELPER
Chris@102 284 #undef BOOST_MUTEX_HELPER_SPINLOCKS
Chris@102 285
Chris@102 286 #include <boost/container/detail/config_end.hpp>
Chris@102 287
Chris@102 288 #endif