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 UNIXSTL_INCL_UNIXSTL_SYNCH_HPP_SEMAPHORE
00048 #define UNIXSTL_INCL_UNIXSTL_SYNCH_HPP_SEMAPHORE
00049
00050 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00051 # define UNIXSTL_VER_UNIXSTL_SYNCH_HPP_SEMAPHORE_MAJOR 1
00052 # define UNIXSTL_VER_UNIXSTL_SYNCH_HPP_SEMAPHORE_MINOR 2
00053 # define UNIXSTL_VER_UNIXSTL_SYNCH_HPP_SEMAPHORE_REVISION 2
00054 # define UNIXSTL_VER_UNIXSTL_SYNCH_HPP_SEMAPHORE_EDIT 20
00055 #endif
00056
00057
00058
00059
00060
00061 #ifndef UNIXSTL_INCL_UNIXSTL_H_UNIXSTL
00062 # include <unixstl/unixstl.h>
00063 #endif
00064 #ifndef STLSOFT_INCL_STLSOFT_SYNCH_HPP_CONCEPTS
00065 # include <stlsoft/synch/concepts.hpp>
00066 #endif
00067 #ifndef UNIXSTL_INCL_UNIXSTL_SYNCH_ERROR_HPP_EXCEPTIONS
00068 # include <unixstl/synch/error/exceptions.hpp>
00069 #endif
00070
00071 #ifndef STLSOFT_INCL_H_ERRNO
00072 # define STLSOFT_INCL_H_ERRNO
00073 # include <errno.h>
00074 #endif
00075 #ifndef STLSOFT_INCL_H_SEMAPHORE
00076 # define STLSOFT_INCL_H_SEMAPHORE
00077 # include <semaphore.h>
00078 #endif
00079
00080
00081
00082
00083
00084 #ifndef _UNIXSTL_NO_NAMESPACE
00085 # if defined(_STLSOFT_NO_NAMESPACE) || \
00086 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00087
00088 namespace unixstl
00089 {
00090 # else
00091
00092
00093 namespace stlsoft
00094 {
00095
00096 namespace unixstl_project
00097 {
00098
00099 # endif
00100 #endif
00101
00102
00103
00104
00105
00106
00112 class semaphore
00113 : public stlsoft_ns_qual(critical_section)< STLSOFT_CRITICAL_SECTION_ISNOT_RECURSIVE
00114 , STLSOFT_CRITICAL_SECTION_IS_TRYABLE
00115 >
00116 , public stlsoft_ns_qual(synchronisable_object_tag)
00117 {
00120 public:
00121 typedef semaphore class_type;
00122 typedef sem_t* handle_type;
00123 typedef us_bool_t bool_type;
00124 typedef us_size_t count_type;
00125
00126 typedef sem_t* resource_type;
00128
00131 public:
00132 enum
00133 {
00134 maxCountValue = _POSIX_SEM_VALUE_MAX
00135 };
00137
00140 public:
00142 semaphore(handle_type sem, bool_type bTakeOwnership)
00143 : m_sem(sem)
00144 , m_bOwnHandle(bTakeOwnership)
00145 {
00146 UNIXSTL_ASSERT(NULL != sem);
00147 }
00149 ss_explicit_k semaphore(count_type initialCount, bool_type bInterProcessShared = false)
00150 : m_sem(create_semaphore_(&m_semInternal, initialCount, bInterProcessShared))
00151 , m_bOwnHandle(true)
00152 {}
00153
00155 ~semaphore() stlsoft_throw_0()
00156 {
00157 if( NULL != m_sem &&
00158 m_bOwnHandle)
00159 {
00160 ::sem_destroy(m_sem);
00161 }
00162 }
00163
00164 #if 0
00165 void close() stlsoft_throw_0()
00166 {
00167 if( NULL != m_sem &&
00168 m_bOwnHandle)
00169 {
00170 ::sem_destroy(m_sem);
00171 m_sem = NULL;
00172 }
00173 }
00174 #endif
00175
00177
00180 public:
00182 void lock()
00183 {
00184 UNIXSTL_ASSERT(NULL != m_sem);
00185
00186 if(::sem_wait(m_sem) < 0)
00187 {
00188 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00189 STLSOFT_THROW_X(synchronisation_exception("semaphore wait failed", errno));
00190 #endif
00191 }
00192 }
00196 bool_type try_lock()
00197 {
00198 UNIXSTL_ASSERT(NULL != m_sem);
00199
00200 int res = ::sem_trywait(m_sem);
00201
00202 if(0 == res)
00203 {
00204 return true;
00205 }
00206 else
00207 {
00208 if(EAGAIN != res)
00209 {
00210 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00211 STLSOFT_THROW_X(synchronisation_exception("semaphore wait failed", errno));
00212 #endif
00213 }
00214 }
00215
00216 return false;
00217 }
00220 void unlock()
00221 {
00222 UNIXSTL_ASSERT(NULL != m_sem);
00223
00224 if(::sem_post(m_sem) < 0)
00225 {
00226 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00227 STLSOFT_THROW_X(synchronisation_exception("semaphore release failed", errno));
00228 #endif
00229 }
00230 }
00232
00235 public:
00237 handle_type handle() stlsoft_throw_0()
00238 {
00239 return m_sem;
00240 }
00242 handle_type get() stlsoft_throw_0()
00243 {
00244 return m_sem;
00245 }
00247
00248
00249 private:
00250 static handle_type create_semaphore_(sem_t* internal, count_type initialCount, bool_type bInterProcessShared)
00251 {
00252 UNIXSTL_ASSERT(initialCount <= maxCountValue);
00253
00254 handle_type sem;
00255
00256 if(::sem_init(internal, bInterProcessShared, initialCount) < 0)
00257 {
00258 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00259 STLSOFT_THROW_X(synchronisation_exception("Failed to create kernel semaphore object", errno));
00260 #else
00261 sem = NULL;
00262 #endif
00263 }
00264 else
00265 {
00266 sem = internal;
00267 }
00268
00269 return sem;
00270 }
00271
00272
00273 private:
00274 sem_t m_semInternal;
00275 handle_type m_sem;
00276 const bool_type m_bOwnHandle;
00277
00278
00279 private:
00280 semaphore(class_type const& rhs);
00281 semaphore& operator =(class_type const& rhs);
00282 };
00283
00284
00285
00286
00287
00288 #ifndef _UNIXSTL_NO_NAMESPACE
00289 # if defined(_STLSOFT_NO_NAMESPACE) || \
00290 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00291 }
00292 # else
00293 }
00294 # endif
00295 #endif
00296
00303 inline void lock_instance(unixstl_ns_qual(semaphore) &sem)
00304 {
00305 sem.lock();
00306 }
00307
00314 inline void unlock_instance(unixstl_ns_qual(semaphore) &sem)
00315 {
00316 sem.unlock();
00317 }
00318
00319 #ifndef _UNIXSTL_NO_NAMESPACE
00320 # if defined(_STLSOFT_NO_NAMESPACE) || \
00321 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00322 namespace unixstl {
00323 # else
00324 namespace unixstl_project {
00325 # if defined(STLSOFT_COMPILER_IS_BORLAND)
00326 using ::stlsoft::lock_instance;
00327 using ::stlsoft::unlock_instance;
00328 # endif
00329 # endif
00330 #endif
00331
00332
00333
00334
00335
00336
00341 struct semaphore_lock_traits
00342 {
00343 public:
00345 typedef semaphore lock_type;
00346 typedef semaphore_lock_traits class_type;
00347
00348
00349 public:
00351 static void lock(semaphore &c)
00352 {
00353 lock_instance(c);
00354 }
00355
00357 static void unlock(semaphore &c)
00358 {
00359 unlock_instance(c);
00360 }
00361 };
00362
00364
00365
00366 #ifdef STLSOFT_UNITTEST
00367 # include "./unittest/semaphore_unittest_.h"
00368 #endif
00369
00370
00371
00372 #ifndef _UNIXSTL_NO_NAMESPACE
00373 # if defined(_STLSOFT_NO_NAMESPACE) || \
00374 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00375 }
00376 # else
00377 }
00378 }
00379 # endif
00380 #endif
00381
00382
00383
00384 #endif
00385
00386