PageRenderTime 41ms CodeModel.GetById 1ms app.highlight 30ms RepoModel.GetById 6ms app.codeStats 1ms

/Src/Dependencies/Boost/boost/interprocess/sync/posix/semaphore_wrapper.hpp

http://hadesmem.googlecode.com/
C++ Header | 265 lines | 204 code | 42 blank | 19 comment | 27 complexity | 0338e551e0f436d39408eba78a438651 MD5 | raw file
  1//////////////////////////////////////////////////////////////////////////////
  2//
  3// (C) Copyright Ion Gaztanaga 2005-2009. Distributed under the Boost
  4// Software License, Version 1.0. (See accompanying file
  5// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6//
  7// See http://www.boost.org/libs/interprocess for documentation.
  8//
  9//////////////////////////////////////////////////////////////////////////////
 10
 11#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP
 12#define BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP
 13
 14#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
 15#include <boost/interprocess/exceptions.hpp>
 16#include <boost/interprocess/creation_tags.hpp>
 17#include <boost/interprocess/detail/os_file_functions.hpp>
 18#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
 19#include <boost/interprocess/permissions.hpp>
 20#include <string>
 21#include <semaphore.h>
 22#include <boost/assert.hpp>
 23
 24#ifdef SEM_FAILED
 25#define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast<sem_t*>(SEM_FAILED))
 26#else
 27#define BOOST_INTERPROCESS_POSIX_SEM_FAILED (reinterpret_cast<sem_t*>(-1))
 28#endif
 29
 30#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
 31#include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
 32#else
 33#include <boost/interprocess/detail/os_thread_functions.hpp>
 34#endif
 35
 36namespace boost {
 37namespace interprocess {
 38
 39/// @cond
 40namespace detail{ class interprocess_tester; }
 41/// @endcond
 42
 43namespace detail {
 44
 45inline bool semaphore_open
 46   (sem_t *&handle, detail::create_enum_t type, const char *origname, 
 47    unsigned int count, const permissions &perm = permissions())
 48{
 49   std::string name;
 50   #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
 51   detail::add_leading_slash(origname, name);
 52   #else
 53   detail::create_tmp_and_clean_old_and_get_filename(origname, name);
 54   #endif
 55
 56   //Create new mapping
 57   int oflag = 0;
 58   switch(type){
 59      case detail::DoOpen:
 60         //No addition
 61      break;
 62      case detail::DoCreate:
 63         oflag |= (O_CREAT | O_EXCL);
 64      break;
 65      case detail::DoOpenOrCreate:
 66         oflag |= O_CREAT;
 67      break;
 68      default:
 69         {
 70            error_info err = other_error;
 71            throw interprocess_exception(err);
 72         }
 73   }
 74
 75   //Open file using POSIX API
 76   if(oflag & O_CREAT)
 77      handle = sem_open(name.c_str(), oflag, perm.get_permissions(), count);
 78   else
 79      handle = sem_open(name.c_str(), oflag);
 80
 81   //Check for error
 82   if(handle == BOOST_INTERPROCESS_POSIX_SEM_FAILED){
 83      throw interprocess_exception(error_info(errno));
 84   }
 85
 86   return true;
 87}
 88
 89inline void semaphore_close(sem_t *handle)
 90{
 91   int ret = sem_close(handle);
 92   if(ret != 0){  
 93      BOOST_ASSERT(0);
 94   }
 95}
 96
 97inline bool semaphore_unlink(const char *semname)
 98{
 99   try{
100      std::string sem_str;
101      #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
102      detail::add_leading_slash(semname, sem_str);
103      #else
104      detail::tmp_filename(semname, sem_str);
105      #endif
106      return 0 != sem_unlink(sem_str.c_str());
107   }
108   catch(...){
109      return false;
110   }
111}
112
113inline void semaphore_init(sem_t *handle, unsigned int initialCount)
114{
115   int ret = sem_init(handle, 1, initialCount);
116   //According to SUSV3 version 2003 edition, the return value of a successful
117   //sem_init call is not defined, but -1 is returned on failure.
118   //In the future, a successful call might be required to return 0.
119   if(ret == -1){
120      throw interprocess_exception(system_error_code());
121   }
122}
123
124inline void semaphore_destroy(sem_t *handle)
125{
126   int ret = sem_destroy(handle);
127   if(ret != 0){  
128      BOOST_ASSERT(0);
129   }
130}
131
132inline void semaphore_post(sem_t *handle)
133{
134   int ret = sem_post(handle);
135   if(ret != 0){
136      throw interprocess_exception(system_error_code());
137   }
138}
139
140inline void semaphore_wait(sem_t *handle)
141{
142   int ret = sem_wait(handle);
143   if(ret != 0){
144      throw interprocess_exception(system_error_code());
145   }
146}
147
148inline bool semaphore_try_wait(sem_t *handle)
149{
150   int res = sem_trywait(handle);
151   if(res == 0)
152      return true;
153   if(system_error_code() == EAGAIN){
154      return false;
155   }
156   throw interprocess_exception(system_error_code());
157   return false;
158}
159
160inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime &abs_time)
161{
162   #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
163   timespec tspec = detail::ptime_to_timespec(abs_time);
164   for (;;){
165      int res = sem_timedwait(handle, &tspec);
166      if(res == 0)
167         return true;
168      if (res > 0){
169         //buggy glibc, copy the returned error code to errno
170         errno = res;
171      }
172      if(system_error_code() == ETIMEDOUT){
173         return false;
174      }
175      throw interprocess_exception(system_error_code());
176   }
177   return false;
178   #else //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
179   boost::posix_time::ptime now;
180   while((now = microsec_clock::universal_time()) < abs_time){
181      if(semaphore_try_wait(handle))
182         return true;
183      thread_yield();
184   }
185   return false;
186   #endif   //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
187}
188
189
190class named_semaphore_wrapper
191{
192   named_semaphore_wrapper();
193   named_semaphore_wrapper(const named_semaphore_wrapper&);
194   named_semaphore_wrapper &operator= (const named_semaphore_wrapper &);
195
196   public:
197   named_semaphore_wrapper
198      (detail::create_enum_t type, const char *name, unsigned int count, const permissions &perm = permissions())
199   {  semaphore_open(mp_sem, type, name, count, perm);   }
200
201   ~named_semaphore_wrapper()
202   {
203      if(mp_sem != BOOST_INTERPROCESS_POSIX_SEM_FAILED)
204         semaphore_close(mp_sem);
205   }
206
207   void post()
208   {  semaphore_post(mp_sem); }
209
210   void wait()
211   {  semaphore_wait(mp_sem); }
212
213   bool try_wait()
214   {  return semaphore_try_wait(mp_sem); }
215
216   bool timed_wait(const boost::posix_time::ptime &abs_time)
217   {  return semaphore_timed_wait(mp_sem, abs_time); }
218
219   static bool remove(const char *name)
220   {  return semaphore_unlink(name);   }
221
222   private:
223   friend class detail::interprocess_tester;
224   void dont_close_on_destruction()
225   {  mp_sem = BOOST_INTERPROCESS_POSIX_SEM_FAILED; }
226
227   sem_t      *mp_sem;
228};
229
230class semaphore_wrapper
231{
232   semaphore_wrapper();
233   semaphore_wrapper(const semaphore_wrapper&);
234   semaphore_wrapper &operator= (const semaphore_wrapper &);
235
236   public:
237   semaphore_wrapper(unsigned int initialCount)
238   {  semaphore_init(&m_sem, initialCount);  }
239
240   ~semaphore_wrapper()
241   {  semaphore_destroy(&m_sem);  }
242
243   void post()
244   {  semaphore_post(&m_sem); }
245
246   void wait()
247   {  semaphore_wait(&m_sem); }
248
249   bool try_wait()
250   {  return semaphore_try_wait(&m_sem); }
251
252   bool timed_wait(const boost::posix_time::ptime &abs_time)
253   {  return semaphore_timed_wait(&m_sem, abs_time); }
254
255   private:
256   sem_t       m_sem;
257};
258
259}  //namespace detail {
260}  //namespace interprocess {
261}  //namespace boost {
262
263#undef BOOST_INTERPROCESS_POSIX_SEM_FAILED
264
265#endif   //#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP