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
00047 #ifndef WINSTL_INCL_WINSTL_SYNCH_HPP_SEMAPHORE
00048 #define WINSTL_INCL_WINSTL_SYNCH_HPP_SEMAPHORE
00049
00050 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00051 # define WINSTL_VER_WINSTL_SYNCH_HPP_SEMAPHORE_MAJOR 1
00052 # define WINSTL_VER_WINSTL_SYNCH_HPP_SEMAPHORE_MINOR 3
00053 # define WINSTL_VER_WINSTL_SYNCH_HPP_SEMAPHORE_REVISION 1
00054 # define WINSTL_VER_WINSTL_SYNCH_HPP_SEMAPHORE_EDIT 21
00055 #endif
00056
00057
00058
00059
00060
00061 #ifndef WINSTL_INCL_WINSTL_H_WINSTL
00062 # include <winstl/winstl.h>
00063 #endif
00064 #ifndef STLSOFT_INCL_STLSOFT_SYNCH_HPP_CONCEPTS
00065 # include <stlsoft/synch/concepts.hpp>
00066 #endif
00067 #ifndef WINSTL_INCL_WINSTL_SYNCH_ERROR_HPP_EXCEPTIONS
00068 # include <winstl/synch/error/exceptions.hpp>
00069 #endif
00070
00071
00072
00073
00074
00075 #ifndef _WINSTL_NO_NAMESPACE
00076 # if defined(_STLSOFT_NO_NAMESPACE) || \
00077 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00078
00079 namespace winstl
00080 {
00081 # else
00082
00083
00084 namespace stlsoft
00085 {
00086
00087 namespace winstl_project
00088 {
00089
00090 # endif
00091 #endif
00092
00093
00094
00095
00096
00097
00103 class semaphore
00104 : public stlsoft_ns_qual(critical_section)< STLSOFT_CRITICAL_SECTION_ISNOT_RECURSIVE
00105 , STLSOFT_CRITICAL_SECTION_IS_TRYABLE
00106 >
00107 , public stlsoft_ns_qual(synchronisable_object_tag)
00108 {
00109 public:
00111 typedef semaphore class_type;
00113 typedef HANDLE synch_handle_type;
00115 typedef ws_bool_t bool_type;
00117 typedef ws_size_t count_type;
00119 typedef HANDLE resource_type;
00120
00121 public:
00122 enum
00123 {
00124 maxCountValue = 0x7fffffff
00125 };
00126
00129 public:
00131 semaphore(synch_handle_type sem, bool_type bTakeOwnership)
00132 : m_sem(sem)
00133 , m_maxCount(0)
00134 , m_bOwnHandle(bTakeOwnership)
00135 {
00136 WINSTL_ASSERT(NULL != sem);
00137 }
00139 ss_explicit_k semaphore(count_type initialCount, count_type maxCount = maxCountValue)
00140 : m_sem(create_semaphore_(NULL, initialCount, maxCount, static_cast<ws_char_a_t const*>(NULL)))
00141 , m_maxCount(maxCount)
00142 , m_bOwnHandle(true)
00143 {}
00144 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00145
00146 ss_explicit_k semaphore(int initialCount, count_type maxCount = maxCountValue)
00147 : m_sem(create_semaphore_(NULL, static_cast<count_type>(initialCount), maxCount, static_cast<ws_char_a_t const*>(NULL)))
00148 , m_maxCount(maxCount)
00149 , m_bOwnHandle(true)
00150 {}
00151 #endif
00153 ss_explicit_k semaphore(ws_char_a_t const* name, count_type initialCount, count_type maxCount = maxCountValue)
00154 : m_sem(create_semaphore_(NULL, initialCount, maxCount, name))
00155 , m_maxCount(maxCount)
00156 , m_bOwnHandle(true)
00157 {}
00159 ss_explicit_k semaphore(ws_char_w_t const* name, count_type initialCount, count_type maxCount = maxCountValue)
00160 : m_sem(create_semaphore_(NULL, initialCount, maxCount, name))
00161 , m_maxCount(maxCount)
00162 , m_bOwnHandle(true)
00163 {}
00165 ss_explicit_k semaphore(ws_char_a_t const* name, LPSECURITY_ATTRIBUTES psa, count_type initialCount, count_type maxCount = maxCountValue)
00166 : m_sem(create_semaphore_(psa, initialCount, maxCount, name))
00167 , m_maxCount(maxCount)
00168 , m_bOwnHandle(true)
00169 {}
00171 ss_explicit_k semaphore(ws_char_w_t const* name, LPSECURITY_ATTRIBUTES psa, count_type initialCount, count_type maxCount = maxCountValue)
00172 : m_sem(create_semaphore_(psa, initialCount, maxCount, name))
00173 , m_maxCount(maxCount)
00174 , m_bOwnHandle(true)
00175 {}
00176
00178 ~semaphore() stlsoft_throw_0()
00179 {
00180 if( NULL != m_sem &&
00181 m_bOwnHandle)
00182 {
00183 ::CloseHandle(m_sem);
00184 }
00185 }
00187
00190 public:
00192 void lock()
00193 {
00194 WINSTL_ASSERT(NULL != m_sem);
00195
00196 DWORD dwRes = ::WaitForSingleObject(m_sem, INFINITE);
00197
00198 if(WAIT_OBJECT_0 != dwRes)
00199 {
00200 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00201 STLSOFT_THROW_X(synchronisation_exception("semaphore wait failed", ::GetLastError()));
00202 #endif
00203 }
00204 }
00206 bool_type lock(ws_dword_t wait)
00207 {
00208 WINSTL_ASSERT(NULL != m_sem);
00209
00210 DWORD dwRes = ::WaitForSingleObject(m_sem, wait);
00211
00212 if( WAIT_OBJECT_0 != dwRes &&
00213 WAIT_TIMEOUT != dwRes)
00214 {
00215 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00216 STLSOFT_THROW_X(synchronisation_exception("semaphore wait failed", ::GetLastError()));
00217 #endif
00218 }
00219
00220 return (dwRes == WAIT_OBJECT_0);
00221 }
00225 bool_type try_lock()
00226 {
00227 return lock(0);
00228 }
00233 void unlock()
00234 {
00235 WINSTL_ASSERT(NULL != m_sem);
00236
00237 if(!::ReleaseSemaphore(m_sem, 1, NULL))
00238 {
00239 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00240 STLSOFT_THROW_X(synchronisation_exception("semaphore release failed", ::GetLastError()));
00241 #endif
00242 }
00243 }
00256 ws_long_t unlock(count_type numLocksToRelease)
00257 {
00258 WINSTL_ASSERT(NULL != m_sem);
00259 WINSTL_ASSERT(numLocksToRelease > 0);
00260 WINSTL_ASSERT(static_cast<LONG>(numLocksToRelease) > 0);
00261
00262 LONG previousCount = 0;
00263
00264 if(!::ReleaseSemaphore(m_sem, static_cast<LONG>(numLocksToRelease), &previousCount))
00265 {
00266 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00267 STLSOFT_THROW_X(synchronisation_exception("semaphore release failed", ::GetLastError()));
00268 #else
00269 return -1;
00270 #endif
00271 }
00272
00273 return static_cast<ws_long_t>(previousCount);
00274 }
00276
00279 public:
00281 synch_handle_type handle()
00282 {
00283 return m_sem;
00284 }
00286 synch_handle_type get()
00287 {
00288 return m_sem;
00289 }
00291
00292
00293 private:
00294 static synch_handle_type create_semaphore_(LPSECURITY_ATTRIBUTES psa, count_type initialCount, count_type maxCount, ws_char_a_t const* name)
00295 {
00296 WINSTL_MESSAGE_ASSERT("Maximum semaphore count must be > 0", maxCount > 0);
00297 WINSTL_ASSERT(initialCount <= maxCount);
00298
00299 synch_handle_type sem = ::CreateSemaphoreA(psa, static_cast<LONG>(initialCount), static_cast<LONG>(maxCount), name);
00300
00301 if(NULL == sem)
00302 {
00303 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00304 STLSOFT_THROW_X(synchronisation_exception("Failed to create kernel semaphore object", ::GetLastError()));
00305 #endif
00306 }
00307
00308 return sem;
00309 }
00310 static synch_handle_type create_semaphore_(LPSECURITY_ATTRIBUTES psa, count_type initialCount, count_type maxCount, ws_char_w_t const* name)
00311 {
00312 synch_handle_type sem = ::CreateSemaphoreW(psa, static_cast<LONG>(initialCount), static_cast<LONG>(maxCount), name);
00313
00314 if(NULL == sem)
00315 {
00316 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00317 STLSOFT_THROW_X(synchronisation_exception("Failed to create kernel semaphore object", ::GetLastError()));
00318 #endif
00319 }
00320
00321 return sem;
00322 }
00323
00324
00325 private:
00326 synch_handle_type m_sem;
00327 const count_type m_maxCount;
00328 const bool_type m_bOwnHandle;
00329
00330
00331 private:
00332 semaphore(class_type const& rhs);
00333 semaphore& operator =(class_type const& rhs);
00334 };
00335
00336
00337
00338
00339
00347 inline HANDLE get_synch_handle(semaphore &sem)
00348 {
00349 return sem.get();
00350 }
00351
00361 inline HANDLE get_kernel_handle(semaphore &sem)
00362 {
00363 return sem.get();
00364 }
00365
00366
00367 #ifndef _WINSTL_NO_NAMESPACE
00368 # if defined(_STLSOFT_NO_NAMESPACE) || \
00369 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00370 }
00371 # else
00372 }
00373 # endif
00374 #endif
00375
00382 inline void lock_instance(winstl_ns_qual(semaphore) &sem)
00383 {
00384 sem.lock();
00385 }
00386
00393 inline void unlock_instance(winstl_ns_qual(semaphore) &sem)
00394 {
00395 sem.unlock();
00396 }
00397
00398 #ifndef _WINSTL_NO_NAMESPACE
00399 # if defined(_STLSOFT_NO_NAMESPACE) || \
00400 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00401 namespace winstl {
00402 # else
00403 namespace winstl_project {
00404 # if defined(STLSOFT_COMPILER_IS_BORLAND)
00405 using ::stlsoft::lock_instance;
00406 using ::stlsoft::unlock_instance;
00407 # endif
00408 # endif
00409 #endif
00410
00411
00412
00413
00414
00415
00420 struct semaphore_lock_traits
00421 {
00422 public:
00424 typedef semaphore lock_type;
00426 typedef semaphore_lock_traits class_type;
00427
00428
00429 public:
00431 static void lock(semaphore &c)
00432 {
00433 lock_instance(c);
00434 }
00435
00437 static void unlock(semaphore &c)
00438 {
00439 unlock_instance(c);
00440 }
00441 };
00442
00444
00445
00446 #ifdef STLSOFT_UNITTEST
00447 # include "./unittest/semaphore_unittest_.h"
00448 #endif
00449
00450
00451
00452 #ifndef _WINSTL_NO_NAMESPACE
00453 # if defined(_STLSOFT_NO_NAMESPACE) || \
00454 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00455 }
00456 # else
00457 }
00458 }
00459 # endif
00460 #endif
00461
00462
00463
00464 #endif
00465
00466