Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:12

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Stephen Cleary 2000 
0004 // (C) Copyright Ion Gaztanaga  2015-2017.
0005 //
0006 // Distributed under the Boost
0007 // Software License, Version 1.0. (See accompanying file
0008 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 // See http://www.boost.org/libs/container for documentation.
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 //#define BOOST_CONTAINER_NO_MT
0026 //#define BOOST_CONTAINER_NO_SPINLOCKS
0027 
0028 #include <boost/container/detail/config_begin.hpp>
0029 #include <boost/container/detail/workaround.hpp>
0030 
0031 // Extremely Light-Weight wrapper classes for OS thread synchronization
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   // No multithreading -> make locks into no-ops
0046   #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_NONE
0047 #else
0048    //Taken from dlmalloc
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 /* Win32 */
0076 
0077    /* First, define CAS_LOCK and CLEAR_LOCK on ints */
0078    /* Note CAS_LOCK defined to return 0 on success */
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       /* Custom spin locks for older gcc on x86 */
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 /* Win32 MSC */
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    /* How to yield for a spin lock */
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       } // extern "C"
0154       #endif
0155 
0156       namespace boost {
0157          namespace container_winapi {
0158             using ::SleepEx;
0159          }
0160       }
0161 
0162       #define SLEEP_EX_DURATION     50 /* delay for yield/sleep */
0163       #define SPIN_LOCK_YIELD  boost::container_winapi::SleepEx(SLEEP_EX_DURATION, 0)
0164    #elif defined (__SVR4) && defined (__sun) /* solaris */
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 /* ... yield ... */
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 } // namespace dtl
0297 } // namespace container
0298 } // namespace boost
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