2 // detail/posix_event.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_DETAIL_POSIX_EVENT_HPP
12 #define BOOST_ASIO_DETAIL_POSIX_EVENT_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
20 #if defined(BOOST_ASIO_HAS_PTHREADS)
24 #include <boost/asio/detail/assert.hpp>
25 #include <boost/asio/detail/noncopyable.hpp>
27 #include <boost/asio/detail/push_options.hpp>
38 BOOST_ASIO_DECL posix_event();
43 ::pthread_cond_destroy(&cond_);
46 // Signal the event. (Retained for backward compatibility.)
47 template <typename Lock>
48 void signal(Lock& lock)
50 this->signal_all(lock);
53 // Signal all waiters.
54 template <typename Lock>
55 void signal_all(Lock& lock)
57 BOOST_ASIO_ASSERT(lock.locked());
60 ::pthread_cond_broadcast(&cond_); // Ignore EINVAL.
63 // Unlock the mutex and signal one waiter.
64 template <typename Lock>
65 void unlock_and_signal_one(Lock& lock)
67 BOOST_ASIO_ASSERT(lock.locked());
69 bool have_waiters = (state_ > 1);
72 ::pthread_cond_signal(&cond_); // Ignore EINVAL.
75 // Unlock the mutex and signal one waiter who may destroy us.
76 template <typename Lock>
77 void unlock_and_signal_one_for_destruction(Lock& lock)
79 BOOST_ASIO_ASSERT(lock.locked());
81 bool have_waiters = (state_ > 1);
83 ::pthread_cond_signal(&cond_); // Ignore EINVAL.
87 // If there's a waiter, unlock the mutex and signal it.
88 template <typename Lock>
89 bool maybe_unlock_and_signal_one(Lock& lock)
91 BOOST_ASIO_ASSERT(lock.locked());
96 ::pthread_cond_signal(&cond_); // Ignore EINVAL.
103 template <typename Lock>
104 void clear(Lock& lock)
106 BOOST_ASIO_ASSERT(lock.locked());
108 state_ &= ~std::size_t(1);
111 // Wait for the event to become signalled.
112 template <typename Lock>
113 void wait(Lock& lock)
115 BOOST_ASIO_ASSERT(lock.locked());
116 while ((state_ & 1) == 0)
119 ::pthread_cond_wait(&cond_, &lock.mutex().mutex_); // Ignore EINVAL.
124 // Timed wait for the event to become signalled.
125 template <typename Lock>
126 bool wait_for_usec(Lock& lock, long usec)
128 BOOST_ASIO_ASSERT(lock.locked());
129 if ((state_ & 1) == 0)
133 #if (defined(__MACH__) && defined(__APPLE__)) \
134 || (defined(__ANDROID__) && (__ANDROID_API__ < 21) \
135 && defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE))
136 ts.tv_sec = usec / 1000000;
137 ts.tv_nsec = (usec % 1000000) * 1000;
138 ::pthread_cond_timedwait_relative_np(
139 &cond_, &lock.mutex().mutex_, &ts); // Ignore EINVAL.
140 #else // (defined(__MACH__) && defined(__APPLE__))
141 // || (defined(__ANDROID__) && (__ANDROID_API__ < 21)
142 // && defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE))
143 if (::clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
145 ts.tv_sec += usec / 1000000;
146 ts.tv_nsec += (usec % 1000000) * 1000;
147 ts.tv_sec += ts.tv_nsec / 1000000000;
148 ts.tv_nsec = ts.tv_nsec % 1000000000;
149 ::pthread_cond_timedwait(&cond_,
150 &lock.mutex().mutex_, &ts); // Ignore EINVAL.
152 #endif // (defined(__MACH__) && defined(__APPLE__))
153 // || (defined(__ANDROID__) && (__ANDROID_API__ < 21)
154 // && defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE))
157 return (state_ & 1) != 0;
161 ::pthread_cond_t cond_;
165 } // namespace detail
169 #include <boost/asio/detail/pop_options.hpp>
171 #if defined(BOOST_ASIO_HEADER_ONLY)
172 # include <boost/asio/detail/impl/posix_event.ipp>
173 #endif // defined(BOOST_ASIO_HEADER_ONLY)
175 #endif // defined(BOOST_ASIO_HAS_PTHREADS)
177 #endif // BOOST_ASIO_DETAIL_POSIX_EVENT_HPP