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 
00050 #ifndef WINSTL_INCL_WINSTL_SYNCH_HPP_SPIN_MUTEX
00051 #define WINSTL_INCL_WINSTL_SYNCH_HPP_SPIN_MUTEX
00052 
00053 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00054 # define WINSTL_VER_WINSTL_SYNCH_HPP_SPIN_MUTEX_MAJOR       4
00055 # define WINSTL_VER_WINSTL_SYNCH_HPP_SPIN_MUTEX_MINOR       1
00056 # define WINSTL_VER_WINSTL_SYNCH_HPP_SPIN_MUTEX_REVISION    3
00057 # define WINSTL_VER_WINSTL_SYNCH_HPP_SPIN_MUTEX_EDIT        56
00058 #endif 
00059 
00060 
00061 
00062 
00063 
00064 #ifndef WINSTL_INCL_WINSTL_H_WINSTL
00065 # include <winstl/winstl.h>
00066 #endif 
00067 #ifndef STLSOFT_INCL_STLSOFT_SYNCH_HPP_CONCEPTS
00068 # include <stlsoft/synch/concepts.hpp>
00069 #endif 
00070 #ifndef STLSOFT_INCL_STLSOFT_SYNCH_HPP_SPIN_POLICIES
00071 # include <stlsoft/synch/spin_policies.hpp>
00072 #endif 
00073 #ifndef WINSTL_INCL_WINSTL_SYNCH_H_ATOMIC_TYPES
00074 # include <winstl/synch/atomic_types.h>
00075 #endif 
00076 
00077 #ifdef STLSOFT_UNITTEST
00078 # include <stlsoft/synch/lock_scope.hpp>
00079 #endif 
00080 
00081 #if defined(_DEBUG)
00082 # define    STLSOFT_SPINMUTEX_COUNT_LOCKS
00083 #endif 
00084 
00085 #if defined(_ATL_MIN_CRT)
00086 # define    WINSTL_SPINMUTEX_CHECK_INIT
00087 #endif 
00088 
00089 
00090 
00091 
00092 
00093 #ifndef _WINSTL_NO_NAMESPACE
00094 # if defined(_STLSOFT_NO_NAMESPACE) || \
00095      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00096 
00097 namespace winstl
00098 {
00099 # else
00100 
00101 
00102 namespace stlsoft
00103 {
00104 
00105 namespace winstl_project
00106 {
00107 
00108 # endif 
00109 #endif 
00110 
00111 
00112 
00113 
00114 
00115 
00124 template <typename SP>
00125 class spin_mutex_base
00126     : public stlsoft_ns_qual(critical_section)< STLSOFT_CRITICAL_SECTION_ISNOT_RECURSIVE
00127                                             ,   STLSOFT_CRITICAL_SECTION_ISNOT_TRYABLE
00128                                             >
00129 {
00132 private:
00134     typedef SP                            spin_policy_class;
00135 public:
00137     typedef spin_mutex_base<SP>           class_type;
00139     typedef winstl_ns_qual(atomic_int_t)  atomic_int_type;
00141     typedef ws_sint32_t                   count_type;
00143     typedef ws_bool_t                     bool_type;
00145 
00148 public:
00149 #ifdef __SYNSOFT_DBS_COMPILER_SUPPORTS_PRAGMA_MESSAGE
00150 # pragma message(_sscomp_fileline_message("Create stlsoft/synch/spin_mutex_base.hpp, and factor out"))
00151 #endif 
00152 
00159     ss_explicit_k spin_mutex_base(atomic_int_type *p = NULL) stlsoft_throw_0()
00160         : m_spinCount((NULL != p) ? p : &m_internalCount)
00161         , m_internalCount(0)
00162 #ifdef STLSOFT_SPINMUTEX_COUNT_LOCKS
00163         , m_cLocks(0)
00164 #endif // STLSOFT_SPINMUTEX_COUNT_LOCKS
00165         , m_spunCount(0)
00166         , m_bYieldOnSpin(spin_policy_class::value)
00167     {}
00173     spin_mutex_base(atomic_int_type *p, bool_type bYieldOnSpin) stlsoft_throw_0()
00174         : m_spinCount((NULL != p) ? p : &m_internalCount)
00175         , m_internalCount(0)
00176 #ifdef STLSOFT_SPINMUTEX_COUNT_LOCKS
00177         , m_cLocks(0)
00178 #endif 
00179         , m_spunCount(0)
00180         , m_bYieldOnSpin(bYieldOnSpin)
00181     {}
00183     ~spin_mutex_base() stlsoft_throw_0()
00184     {
00185 #ifdef STLSOFT_SPINMUTEX_COUNT_LOCKS
00186         WINSTL_ASSERT(0 == m_cLocks);
00187 #endif // STLSOFT_SPINMUTEX_COUNT_LOCKS
00188     }
00190 
00193 public:
00195     void lock() stlsoft_throw_0()
00196     {
00197 #ifdef WINSTL_SPINMUTEX_CHECK_INIT
00198         
00199         
00200         
00201         
00202         if(NULL == m_spinCount)
00203         {
00204             m_spinCount = &m_internalCount;
00205         }
00206 #endif 
00207 
00208         WINSTL_MESSAGE_ASSERT("A global instance of spin_mutex has skipped dynamic initialisation. You must #define WINSTL_SPINMUTEX_CHECK_INIT if your compilation causes dynamic initialisation to be skipped.", NULL != m_spinCount);
00209 
00210 
00211 
00212         for(m_spunCount = 1; 0 != ::InterlockedExchange(reinterpret_cast<LPLONG>(m_spinCount), 1); ++m_spunCount)
00213         {
00214             if(m_bYieldOnSpin)
00215             {
00216                 ::Sleep(1);
00217             }
00218         }
00219 
00220 #ifdef STLSOFT_SPINMUTEX_COUNT_LOCKS
00221         WINSTL_ASSERT(0 != ++m_cLocks);
00222 #endif // STLSOFT_SPINMUTEX_COUNT_LOCKS
00223     }
00225     void unlock() stlsoft_throw_0()
00226     {
00227 #ifdef STLSOFT_SPINMUTEX_COUNT_LOCKS
00228         WINSTL_ASSERT(0 != m_cLocks--);
00229 #endif // STLSOFT_SPINMUTEX_COUNT_LOCKS
00230 
00231         m_spunCount = 0;
00232 
00233         static_cast<void>(::InterlockedExchange(reinterpret_cast<LPLONG>(m_spinCount), 0));
00234     }
00236 
00239 public:
00251     count_type  spun_count() const
00252     {
00253         return m_spunCount;
00254     }
00256 
00259 private:
00260     atomic_int_type *m_spinCount;
00261     atomic_int_type m_internalCount;
00262 #ifdef STLSOFT_SPINMUTEX_COUNT_LOCKS
00263     count_type      m_cLocks;       
00264 #endif // STLSOFT_SPINMUTEX_COUNT_LOCKS
00265     count_type      m_spunCount;
00266     const bool_type m_bYieldOnSpin;
00268 
00271 private:
00272     spin_mutex_base(class_type const& rhs);
00273     class_type& operator =(class_type const& rhs);
00275 };
00276 
00277 typedef spin_mutex_base<stlsoft_ns_qual(spin_yield)>        spin_mutex_yield;
00278 typedef spin_mutex_base<stlsoft_ns_qual(spin_no_yield)>     spin_mutex_no_yield;
00279 
00280 #ifdef STLSOFT_OLD_SPIN_MUTEX_BEHAVIOUR
00281 typedef spin_mutex_no_yield                                 spin_mutex;
00282 #else 
00283 typedef spin_mutex_yield                                    spin_mutex;
00284 #endif 
00285 
00286 
00287 
00288 
00289 
00290 #ifndef _WINSTL_NO_NAMESPACE
00291 # if defined(_STLSOFT_NO_NAMESPACE) || \
00292      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00293 } 
00294 # else
00295 } 
00296 # endif 
00297 #endif 
00298 
00305 template <ss_typename_param_k SP>
00306 inline void lock_instance(winstl_ns_qual(spin_mutex_base)<SP> &mx)
00307 {
00308     mx.lock();
00309 }
00310 
00317 template <ss_typename_param_k SP>
00318 inline void unlock_instance(winstl_ns_qual(spin_mutex_base)<SP> &mx)
00319 {
00320     mx.unlock();
00321 }
00322 
00323 
00324 #ifndef _WINSTL_NO_NAMESPACE
00325 # if defined(_STLSOFT_NO_NAMESPACE) || \
00326      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00327 namespace winstl {
00328 # else
00329 namespace winstl_project {
00330 #  if defined(STLSOFT_COMPILER_IS_BORLAND)
00331 using ::stlsoft::lock_instance;
00332 using ::stlsoft::unlock_instance;
00333 #  endif 
00334 # endif 
00335 #endif 
00336 
00337 
00338 
00339 
00340 
00341 
00346 struct spin_mutex_lock_traits
00347 {
00348 public:
00350     typedef spin_mutex                lock_type;
00352     typedef spin_mutex_lock_traits    class_type;
00353 
00354 
00355 public:
00357     static void lock(spin_mutex &c)
00358     {
00359         lock_instance(c);
00360     }
00361 
00363     static void unlock(spin_mutex &c)
00364     {
00365         unlock_instance(c);
00366     }
00367 };
00368 
00370 
00371 
00372 #ifdef STLSOFT_UNITTEST
00373 # include "./unittest/spin_mutex_unittest_.h"
00374 #endif 
00375 
00376 
00377 
00378 #ifndef _WINSTL_NO_NAMESPACE
00379 # if defined(_STLSOFT_NO_NAMESPACE) || \
00380      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00381 } 
00382 # else
00383 } 
00384 } 
00385 # endif 
00386 #endif 
00387 
00388 
00389 
00390 #endif 
00391 
00392