00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00053 #ifndef UNIXSTL_INCL_UNIXSTL_SYNCH_HPP_SPIN_MUTEX
00054 #define UNIXSTL_INCL_UNIXSTL_SYNCH_HPP_SPIN_MUTEX
00055 
00056 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00057 # define UNIXSTL_VER_UNIXSTL_SYNCH_HPP_SPIN_MUTEX_MAJOR     5
00058 # define UNIXSTL_VER_UNIXSTL_SYNCH_HPP_SPIN_MUTEX_MINOR     0
00059 # define UNIXSTL_VER_UNIXSTL_SYNCH_HPP_SPIN_MUTEX_REVISION  3
00060 # define UNIXSTL_VER_UNIXSTL_SYNCH_HPP_SPIN_MUTEX_EDIT      60
00061 #endif 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 #ifndef UNIXSTL_INCL_UNIXSTL_H_UNIXSTL
00078 # include <unixstl/unixstl.h>
00079 #endif 
00080 #ifndef UNIXSTL_INCL_UNIXSTL_SYNCH_UTIL_H_FEATURES
00081 # include <unixstl/synch/util/features.h>
00082 #endif 
00083 #ifndef UNIXSTL_HAS_ATOMIC_INTEGER_OPERATIONS
00084 # error unixstl/synch/spin_mutex.hpp requires support for atomic integer operations. Consult unixstl/synch/util/features.h for details
00085 #endif 
00086 #ifndef UNIXSTL_INCL_UNIXSTL_SYNCH_H_ATOMIC_FUNCTIONS
00087 # include <unixstl/synch/atomic_functions.h>
00088 #endif 
00089 #ifndef STLSOFT_INCL_STLSOFT_SYNCH_HPP_CONCEPTS
00090 # include <stlsoft/synch/concepts.hpp>
00091 #endif 
00092 #ifndef STLSOFT_INCL_STLSOFT_SYNCH_HPP_SPIN_POLICIES
00093 # include <stlsoft/synch/spin_policies.hpp>
00094 #endif 
00095 
00096 #ifndef STLSOFT_INCL_H_SCHED
00097 # define STLSOFT_INCL_H_SCHED
00098 # include <sched.h>
00099 #endif 
00100 
00101 #ifdef STLSOFT_UNITTEST
00102 # include <stlsoft/synch/lock_scope.hpp>
00103 #endif 
00104 
00105 #if defined(_DEBUG)
00106 # define    STLSOFT_SPINMUTEX_COUNT_LOCKS
00107 #endif 
00108 
00109 
00110 
00111 
00112 
00113 #ifndef _UNIXSTL_NO_NAMESPACE
00114 # if defined(_STLSOFT_NO_NAMESPACE) || \
00115      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00116 
00117 namespace unixstl
00118 {
00119 # else
00120 
00121 
00122 namespace stlsoft
00123 {
00124 
00125 namespace unixstl_project
00126 {
00127 
00128 # endif 
00129 #endif 
00130 
00131 
00132 
00133 
00134 
00135 
00144 template <ss_typename_param_k SP>
00145 class spin_mutex_base
00146     : public stlsoft_ns_qual(critical_section)< STLSOFT_CRITICAL_SECTION_ISNOT_RECURSIVE
00147                                             ,   STLSOFT_CRITICAL_SECTION_ISNOT_TRYABLE
00148                                             >
00149 {
00152 private:
00154     typedef SP                              spin_policy_class;
00155 public:
00157     typedef spin_mutex_base<SP>             class_type;
00159     typedef unixstl_ns_qual(atomic_int_t)   atomic_int_type;
00161     typedef us_sint32_t                     count_type;
00163     typedef us_bool_t                       bool_type;
00165 
00168 public:
00169 #ifdef __SYNSOFT_DBS_COMPILER_SUPPORTS_PRAGMA_MESSAGE
00170 # pragma message(_sscomp_fileline_message("Create stlsoft/synch/spin_mutex_base.hpp, and factor out"))
00171 #endif 
00172 
00179     ss_explicit_k spin_mutex_base(atomic_int_type *p = NULL) stlsoft_throw_0()
00180         : m_spinCount((NULL != p) ? p : &m_internalCount)
00181         , m_internalCount(0)
00182 #ifdef STLSOFT_SPINMUTEX_COUNT_LOCKS
00183         , m_cLocks(0)
00184 #endif // STLSOFT_SPINMUTEX_COUNT_LOCKS
00185         , m_spunCount(0)
00186         , m_bYieldOnSpin(spin_policy_class::value)
00187     {}
00193     spin_mutex_base(atomic_int_type *p, bool_type bYieldOnSpin) stlsoft_throw_0()
00194         : m_spinCount((NULL != p) ? p : &m_internalCount)
00195         , m_internalCount(0)
00196 #ifdef STLSOFT_SPINMUTEX_COUNT_LOCKS
00197         , m_cLocks(0)
00198 #endif 
00199         , m_spunCount(0)
00200         , m_bYieldOnSpin(bYieldOnSpin)
00201     {}
00203     ~spin_mutex_base() stlsoft_throw_0()
00204     {
00205 #ifdef STLSOFT_SPINMUTEX_COUNT_LOCKS
00206         UNIXSTL_ASSERT(0 == m_cLocks);
00207 #endif // STLSOFT_SPINMUTEX_COUNT_LOCKS
00208     }
00210 
00213 public:
00215     void lock() stlsoft_throw_0()
00216     {
00217 #ifdef UNIXSTL_SPINMUTEX_CHECK_INIT
00218         
00219         
00220         
00221         
00222         if(NULL == m_spinCount)
00223         {
00224             m_spinCount = &m_internalCount;
00225         }
00226 #endif 
00227 
00228         UNIXSTL_MESSAGE_ASSERT("A global instance of spin_mutex has skipped dynamic initialisation. You must #define UNIXSTL_SPINMUTEX_CHECK_INIT if your compilation causes dynamic initialisation to be skipped.", NULL != m_spinCount);
00229 
00230 #if defined(UNIXSTL_OS_IS_LINUX) && \
00231     !defined(UNIXSTL_ARCH_IS_INTEL)
00232         for(m_spunCount = 1; 0 != ::atomic_inc_and_test(m_spinCount); ++m_spunCount)
00233 #elif defined(UNIXSTL_OS_IS_MACOSX)
00234         for(m_spunCount = 1; !::OSAtomicCompareAndSwap32Barrier(0, 1, m_spinCount); ++m_spunCount)
00235 #elif defined(UNIXSTL_HAS_ATOMIC_WRITE)
00236         for(m_spunCount = 1; 0 != atomic_write(m_spinCount, 1); ++m_spunCount)
00237 #else 
00238 # error Your platform does not support atomic_write(), or has provides it in a manner unknown to the authors of UNIXSTL. If you know of the correct implementation, please send a patch.
00239 #endif 
00240         {
00241             if(m_bYieldOnSpin)
00242             {
00243                 ::sched_yield();
00244             }
00245         }
00246 
00247 #ifdef STLSOFT_SPINMUTEX_COUNT_LOCKS
00248         UNIXSTL_ASSERT(0 != ++m_cLocks);
00249 #endif // STLSOFT_SPINMUTEX_COUNT_LOCKS
00250     }
00252     void unlock() stlsoft_throw_0()
00253     {
00254 #ifdef STLSOFT_SPINMUTEX_COUNT_LOCKS
00255         UNIXSTL_ASSERT(m_cLocks-- != 0);
00256 #endif // STLSOFT_SPINMUTEX_COUNT_LOCKS
00257 
00258         m_spunCount = 0;
00259 
00260 #if defined(UNIXSTL_OS_IS_LINUX) && \
00261     !defined(UNIXSTL_ARCH_IS_INTEL)
00262         ::atomic_dec(m_spinCount);
00263 #elif defined(UNIXSTL_OS_IS_MACOSX)
00264         ::OSAtomicDecrement32Barrier(m_spinCount);
00265 #else 
00266         atomic_write(m_spinCount, 0);
00267 #endif 
00268     }
00270 
00273 public:
00285     count_type  spun_count() const
00286     {
00287         return m_spunCount;
00288     }
00290 
00293 private:
00294     atomic_int_type *m_spinCount;
00295     atomic_int_type m_internalCount;
00296 #ifdef STLSOFT_SPINMUTEX_COUNT_LOCKS
00297     count_type      m_cLocks;       
00298 #endif // STLSOFT_SPINMUTEX_COUNT_LOCKS
00299     count_type      m_spunCount;
00300     const bool_type m_bYieldOnSpin;
00302 
00305 private:
00306     spin_mutex_base(class_type const& rhs);
00307     class_type& operator =(class_type const& rhs);
00309 };
00310 
00311 typedef spin_mutex_base<stlsoft_ns_qual(spin_yield)>        spin_mutex_yield;
00312 typedef spin_mutex_base<stlsoft_ns_qual(spin_no_yield)>     spin_mutex_no_yield;
00313 
00314 #ifdef STLSOFT_OLD_SPIN_MUTEX_BEHAVIOUR
00315 typedef spin_mutex_no_yield                                 spin_mutex;
00316 #else 
00317 typedef spin_mutex_yield                                    spin_mutex;
00318 #endif 
00319 
00320 
00321 
00322 
00323 
00324 #ifndef _UNIXSTL_NO_NAMESPACE
00325 # if defined(_STLSOFT_NO_NAMESPACE) || \
00326      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00327 } 
00328 # else
00329 } 
00330 # endif 
00331 #endif 
00332 
00339 template <ss_typename_param_k SP>
00340 inline void lock_instance(unixstl_ns_qual(spin_mutex_base)<SP> &mx)
00341 {
00342     mx.lock();
00343 }
00344 
00351 template <ss_typename_param_k SP>
00352 inline void unlock_instance(unixstl_ns_qual(spin_mutex_base)<SP> &mx)
00353 {
00354     mx.unlock();
00355 }
00356 
00357 
00358 #ifndef _UNIXSTL_NO_NAMESPACE
00359 # if defined(_STLSOFT_NO_NAMESPACE) || \
00360      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00361 namespace unixstl
00362 {
00363 # else
00364 namespace unixstl_project
00365 {
00366 #  if defined(STLSOFT_COMPILER_IS_BORLAND)
00367 using ::stlsoft::lock_instance;
00368 using ::stlsoft::unlock_instance;
00369 #  endif 
00370 # endif 
00371 #endif 
00372 
00373 
00374 
00375 
00376 
00377 
00382 struct spin_mutex_lock_traits
00383 {
00384 public:
00386     typedef spin_mutex                lock_type;
00387     typedef spin_mutex_lock_traits    class_type;
00388 
00389 
00390 public:
00392     static void lock(spin_mutex &c)
00393     {
00394         lock_instance(c);
00395     }
00396 
00398     static void unlock(spin_mutex &c)
00399     {
00400         unlock_instance(c);
00401     }
00402 };
00403 
00405 
00406 
00407 #ifdef STLSOFT_UNITTEST
00408 # include "./unittest/spin_mutex_unittest_.h"
00409 #endif 
00410 
00411 
00412 
00413 #ifndef _UNIXSTL_NO_NAMESPACE
00414 # if defined(_STLSOFT_NO_NAMESPACE) || \
00415      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00416 } 
00417 # else
00418 } 
00419 } 
00420 # endif 
00421 #endif 
00422 
00423 
00424 
00425 #endif 
00426 
00427