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