condition.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2012. 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_CONDITION_HPP
  11. #define BOOST_INTERPROCESS_POSIX_CONDITION_HPP
  12. #if (defined _MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif
  15. #include <boost/interprocess/detail/config_begin.hpp>
  16. #include <boost/interprocess/detail/workaround.hpp>
  17. #include <pthread.h>
  18. #include <errno.h>
  19. #include <boost/interprocess/sync/posix/pthread_helpers.hpp>
  20. #include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
  21. #include <boost/interprocess/detail/posix_time_types_wrk.hpp>
  22. #include <boost/interprocess/sync/posix/mutex.hpp>
  23. #include <boost/assert.hpp>
  24. namespace boost {
  25. namespace interprocess {
  26. namespace ipcdetail {
  27. class posix_condition
  28. {
  29. //Non-copyable
  30. posix_condition(const posix_condition &);
  31. posix_condition &operator=(const posix_condition &);
  32. public:
  33. //!Constructs a posix_condition. On error throws interprocess_exception.
  34. posix_condition();
  35. //!Destroys *this
  36. //!liberating system resources.
  37. ~posix_condition();
  38. //!If there is a thread waiting on *this, change that
  39. //!thread's state to ready. Otherwise there is no effect.
  40. void notify_one();
  41. //!Change the state of all threads waiting on *this to ready.
  42. //!If there are no waiting threads, notify_all() has no effect.
  43. void notify_all();
  44. //!Releases the lock on the posix_mutex object associated with lock, blocks
  45. //!the current thread of execution until readied by a call to
  46. //!this->notify_one() or this->notify_all(), and then reacquires the lock.
  47. template <typename L>
  48. void wait(L& lock)
  49. {
  50. if (!lock)
  51. throw lock_exception();
  52. this->do_wait(*lock.mutex());
  53. }
  54. //!The same as:
  55. //!while (!pred()) wait(lock)
  56. template <typename L, typename Pr>
  57. void wait(L& lock, Pr pred)
  58. {
  59. if (!lock)
  60. throw lock_exception();
  61. while (!pred())
  62. this->do_wait(*lock.mutex());
  63. }
  64. //!Releases the lock on the posix_mutex object associated with lock, blocks
  65. //!the current thread of execution until readied by a call to
  66. //!this->notify_one() or this->notify_all(), or until time abs_time is reached,
  67. //!and then reacquires the lock.
  68. //!Returns: false if time abs_time is reached, otherwise true.
  69. template <typename L>
  70. bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
  71. {
  72. if(abs_time == boost::posix_time::pos_infin){
  73. this->wait(lock);
  74. return true;
  75. }
  76. if (!lock)
  77. throw lock_exception();
  78. return this->do_timed_wait(abs_time, *lock.mutex());
  79. }
  80. //!The same as: while (!pred()) {
  81. //! if (!timed_wait(lock, abs_time)) return pred();
  82. //! } return true;
  83. template <typename L, typename Pr>
  84. bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
  85. {
  86. if(abs_time == boost::posix_time::pos_infin){
  87. this->wait(lock, pred);
  88. return true;
  89. }
  90. if (!lock)
  91. throw lock_exception();
  92. while (!pred()){
  93. if (!this->do_timed_wait(abs_time, *lock.mutex()))
  94. return pred();
  95. }
  96. return true;
  97. }
  98. void do_wait(posix_mutex &mut);
  99. bool do_timed_wait(const boost::posix_time::ptime &abs_time, posix_mutex &mut);
  100. private:
  101. pthread_cond_t m_condition;
  102. };
  103. inline posix_condition::posix_condition()
  104. {
  105. int res;
  106. pthread_condattr_t cond_attr;
  107. res = pthread_condattr_init(&cond_attr);
  108. if(res != 0){
  109. throw interprocess_exception("pthread_condattr_init failed");
  110. }
  111. res = pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED);
  112. if(res != 0){
  113. pthread_condattr_destroy(&cond_attr);
  114. throw interprocess_exception(res);
  115. }
  116. res = pthread_cond_init(&m_condition, &cond_attr);
  117. pthread_condattr_destroy(&cond_attr);
  118. if(res != 0){
  119. throw interprocess_exception(res);
  120. }
  121. }
  122. inline posix_condition::~posix_condition()
  123. {
  124. int res = 0;
  125. res = pthread_cond_destroy(&m_condition);
  126. BOOST_ASSERT(res == 0); (void)res;
  127. }
  128. inline void posix_condition::notify_one()
  129. {
  130. int res = 0;
  131. res = pthread_cond_signal(&m_condition);
  132. BOOST_ASSERT(res == 0); (void)res;
  133. }
  134. inline void posix_condition::notify_all()
  135. {
  136. int res = 0;
  137. res = pthread_cond_broadcast(&m_condition);
  138. BOOST_ASSERT(res == 0); (void)res;
  139. }
  140. inline void posix_condition::do_wait(posix_mutex &mut)
  141. {
  142. pthread_mutex_t* pmutex = &mut.m_mut;
  143. int res = 0;
  144. res = pthread_cond_wait(&m_condition, pmutex);
  145. BOOST_ASSERT(res == 0); (void)res;
  146. }
  147. inline bool posix_condition::do_timed_wait
  148. (const boost::posix_time::ptime &abs_time, posix_mutex &mut)
  149. {
  150. timespec ts = ptime_to_timespec(abs_time);
  151. pthread_mutex_t* pmutex = &mut.m_mut;
  152. int res = 0;
  153. res = pthread_cond_timedwait(&m_condition, pmutex, &ts);
  154. BOOST_ASSERT(res == 0 || res == ETIMEDOUT);
  155. return res != ETIMEDOUT;
  156. }
  157. } //namespace ipcdetail
  158. } //namespace interprocess
  159. } //namespace boost
  160. #include <boost/interprocess/detail/config_end.hpp>
  161. #endif //#ifndef BOOST_INTERPROCESS_POSIX_CONDITION_HPP