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