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 BOOST_ASIO_DETAIL_POSIX_EVENT_HPP 12 #define BOOST_ASIO_DETAIL_POSIX_EVENT_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include <boost/asio/detail/config.hpp> 19 20 #if defined(BOOST_ASIO_HAS_PTHREADS) 21 22 #include <pthread.h> 23 #include <boost/asio/detail/assert.hpp> 24 #include <boost/asio/detail/noncopyable.hpp> 25 26 #include <boost/asio/detail/push_options.hpp> 27 28 namespace boost { 29 namespace asio { 30 namespace detail { 31 32 class posix_event 33 : private noncopyable 34 { 35 public: 36 // Constructor. 37 BOOST_ASIO_DECL posix_event(); 38 39 // Destructor. ~posix_event()40 ~posix_event() 41 { 42 ::pthread_cond_destroy(&cond_); 43 } 44 45 // Signal the event. (Retained for backward compatibility.) 46 template <typename Lock> signal(Lock & lock)47 void signal(Lock& lock) 48 { 49 this->signal_all(lock); 50 } 51 52 // Signal all waiters. 53 template <typename Lock> signal_all(Lock & lock)54 void signal_all(Lock& lock) 55 { 56 BOOST_ASIO_ASSERT(lock.locked()); 57 (void)lock; 58 state_ |= 1; 59 ::pthread_cond_broadcast(&cond_); // Ignore EINVAL. 60 } 61 62 // Unlock the mutex and signal one waiter. 63 template <typename Lock> unlock_and_signal_one(Lock & lock)64 void unlock_and_signal_one(Lock& lock) 65 { 66 BOOST_ASIO_ASSERT(lock.locked()); 67 state_ |= 1; 68 bool have_waiters = (state_ > 1); 69 lock.unlock(); 70 if (have_waiters) 71 ::pthread_cond_signal(&cond_); // Ignore EINVAL. 72 } 73 74 // If there's a waiter, unlock the mutex and signal it. 75 template <typename Lock> maybe_unlock_and_signal_one(Lock & lock)76 bool maybe_unlock_and_signal_one(Lock& lock) 77 { 78 BOOST_ASIO_ASSERT(lock.locked()); 79 state_ |= 1; 80 if (state_ > 1) 81 { 82 lock.unlock(); 83 ::pthread_cond_signal(&cond_); // Ignore EINVAL. 84 return true; 85 } 86 return false; 87 } 88 89 // Reset the event. 90 template <typename Lock> clear(Lock & lock)91 void clear(Lock& lock) 92 { 93 BOOST_ASIO_ASSERT(lock.locked()); 94 (void)lock; 95 state_ &= ~std::size_t(1); 96 } 97 98 // Wait for the event to become signalled. 99 template <typename Lock> wait(Lock & lock)100 void wait(Lock& lock) 101 { 102 BOOST_ASIO_ASSERT(lock.locked()); 103 while ((state_ & 1) == 0) 104 { 105 state_ += 2; 106 ::pthread_cond_wait(&cond_, &lock.mutex().mutex_); // Ignore EINVAL. 107 state_ -= 2; 108 } 109 } 110 111 private: 112 ::pthread_cond_t cond_; 113 std::size_t state_; 114 }; 115 116 } // namespace detail 117 } // namespace asio 118 } // namespace boost 119 120 #include <boost/asio/detail/pop_options.hpp> 121 122 #if defined(BOOST_ASIO_HEADER_ONLY) 123 # include <boost/asio/detail/impl/posix_event.ipp> 124 #endif // defined(BOOST_ASIO_HEADER_ONLY) 125 126 #endif // defined(BOOST_ASIO_HAS_PTHREADS) 127 128 #endif // BOOST_ASIO_DETAIL_POSIX_EVENT_HPP 129