1 // 2 // detail/posix_event.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 // 10 11 #ifndef ASIO_DETAIL_POSIX_EVENT_HPP 12 #define ASIO_DETAIL_POSIX_EVENT_HPP 13 14 15 #include "asio/detail/config.hpp" 16 17 #if defined(ASIO_HAS_PTHREADS) 18 19 #include <pthread.h> 20 #include "asio/detail/assert.hpp" 21 #include "asio/detail/noncopyable.hpp" 22 23 #include "asio/detail/push_options.hpp" 24 25 namespace asio { 26 namespace detail { 27 28 class posix_event 29 : private noncopyable 30 { 31 public: 32 // Constructor. 33 ASIO_DECL posix_event(); 34 35 // Destructor. ~posix_event()36 ~posix_event() 37 { 38 ::pthread_cond_destroy(&cond_); 39 } 40 41 // Signal the event. (Retained for backward compatibility.) 42 template <typename Lock> signal(Lock & lock)43 void signal(Lock& lock) 44 { 45 this->signal_all(lock); 46 } 47 48 // Signal all waiters. 49 template <typename Lock> signal_all(Lock & lock)50 void signal_all(Lock& lock) 51 { 52 ASIO_ASSERT(lock.locked()); 53 (void)lock; 54 state_ |= 1; 55 ::pthread_cond_broadcast(&cond_); // Ignore EINVAL. 56 } 57 58 // Unlock the mutex and signal one waiter. 59 template <typename Lock> unlock_and_signal_one(Lock & lock)60 void unlock_and_signal_one(Lock& lock) 61 { 62 ASIO_ASSERT(lock.locked()); 63 state_ |= 1; 64 bool have_waiters = (state_ > 1); 65 lock.unlock(); 66 if (have_waiters) 67 ::pthread_cond_signal(&cond_); // Ignore EINVAL. 68 } 69 70 // If there's a waiter, unlock the mutex and signal it. 71 template <typename Lock> maybe_unlock_and_signal_one(Lock & lock)72 bool maybe_unlock_and_signal_one(Lock& lock) 73 { 74 ASIO_ASSERT(lock.locked()); 75 state_ |= 1; 76 if (state_ > 1) 77 { 78 lock.unlock(); 79 ::pthread_cond_signal(&cond_); // Ignore EINVAL. 80 return true; 81 } 82 return false; 83 } 84 85 // Reset the event. 86 template <typename Lock> clear(Lock & lock)87 void clear(Lock& lock) 88 { 89 ASIO_ASSERT(lock.locked()); 90 (void)lock; 91 state_ &= ~std::size_t(1); 92 } 93 94 // Wait for the event to become signalled. 95 template <typename Lock> wait(Lock & lock)96 void wait(Lock& lock) 97 { 98 ASIO_ASSERT(lock.locked()); 99 while ((state_ & 1) == 0) 100 { 101 state_ += 2; 102 ::pthread_cond_wait(&cond_, &lock.mutex().mutex_); // Ignore EINVAL. 103 state_ -= 2; 104 } 105 } 106 107 private: 108 ::pthread_cond_t cond_; 109 std::size_t state_; 110 }; 111 112 } // namespace detail 113 } // namespace asio 114 115 #include "asio/detail/pop_options.hpp" 116 117 # include "asio/detail/impl/posix_event.ipp" 118 119 #endif // defined(ASIO_HAS_PTHREADS) 120 121 #endif // ASIO_DETAIL_POSIX_EVENT_HPP 122