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

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