File indexing completed on 2025-01-18 09:28:42
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_DETAIL_POSIX_EVENT_HPP
0012 #define BOOST_ASIO_DETAIL_POSIX_EVENT_HPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019
0020 #if defined(BOOST_ASIO_HAS_PTHREADS)
0021
0022 #include <cstddef>
0023 #include <pthread.h>
0024 #include <boost/asio/detail/assert.hpp>
0025 #include <boost/asio/detail/noncopyable.hpp>
0026
0027 #include <boost/asio/detail/push_options.hpp>
0028
0029 namespace boost {
0030 namespace asio {
0031 namespace detail {
0032
0033 class posix_event
0034 : private noncopyable
0035 {
0036 public:
0037
0038 BOOST_ASIO_DECL posix_event();
0039
0040
0041 ~posix_event()
0042 {
0043 ::pthread_cond_destroy(&cond_);
0044 }
0045
0046
0047 template <typename Lock>
0048 void signal(Lock& lock)
0049 {
0050 this->signal_all(lock);
0051 }
0052
0053
0054 template <typename Lock>
0055 void signal_all(Lock& lock)
0056 {
0057 BOOST_ASIO_ASSERT(lock.locked());
0058 (void)lock;
0059 state_ |= 1;
0060 ::pthread_cond_broadcast(&cond_);
0061 }
0062
0063
0064 template <typename Lock>
0065 void unlock_and_signal_one(Lock& lock)
0066 {
0067 BOOST_ASIO_ASSERT(lock.locked());
0068 state_ |= 1;
0069 bool have_waiters = (state_ > 1);
0070 lock.unlock();
0071 if (have_waiters)
0072 ::pthread_cond_signal(&cond_);
0073 }
0074
0075
0076 template <typename Lock>
0077 void unlock_and_signal_one_for_destruction(Lock& lock)
0078 {
0079 BOOST_ASIO_ASSERT(lock.locked());
0080 state_ |= 1;
0081 bool have_waiters = (state_ > 1);
0082 if (have_waiters)
0083 ::pthread_cond_signal(&cond_);
0084 lock.unlock();
0085 }
0086
0087
0088 template <typename Lock>
0089 bool maybe_unlock_and_signal_one(Lock& lock)
0090 {
0091 BOOST_ASIO_ASSERT(lock.locked());
0092 state_ |= 1;
0093 if (state_ > 1)
0094 {
0095 lock.unlock();
0096 ::pthread_cond_signal(&cond_);
0097 return true;
0098 }
0099 return false;
0100 }
0101
0102
0103 template <typename Lock>
0104 void clear(Lock& lock)
0105 {
0106 BOOST_ASIO_ASSERT(lock.locked());
0107 (void)lock;
0108 state_ &= ~std::size_t(1);
0109 }
0110
0111
0112 template <typename Lock>
0113 void wait(Lock& lock)
0114 {
0115 BOOST_ASIO_ASSERT(lock.locked());
0116 while ((state_ & 1) == 0)
0117 {
0118 state_ += 2;
0119 ::pthread_cond_wait(&cond_, &lock.mutex().mutex_);
0120 state_ -= 2;
0121 }
0122 }
0123
0124
0125 template <typename Lock>
0126 bool wait_for_usec(Lock& lock, long usec)
0127 {
0128 BOOST_ASIO_ASSERT(lock.locked());
0129 if ((state_ & 1) == 0)
0130 {
0131 state_ += 2;
0132 timespec ts;
0133 #if (defined(__MACH__) && defined(__APPLE__)) \
0134 || (defined(__ANDROID__) && (__ANDROID_API__ < 21) \
0135 && defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE))
0136 ts.tv_sec = usec / 1000000;
0137 ts.tv_nsec = (usec % 1000000) * 1000;
0138 ::pthread_cond_timedwait_relative_np(
0139 &cond_, &lock.mutex().mutex_, &ts);
0140 #else
0141
0142
0143 if (::clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
0144 {
0145 ts.tv_sec += usec / 1000000;
0146 ts.tv_nsec += (usec % 1000000) * 1000;
0147 ts.tv_sec += ts.tv_nsec / 1000000000;
0148 ts.tv_nsec = ts.tv_nsec % 1000000000;
0149 ::pthread_cond_timedwait(&cond_,
0150 &lock.mutex().mutex_, &ts);
0151 }
0152 #endif
0153
0154
0155 state_ -= 2;
0156 }
0157 return (state_ & 1) != 0;
0158 }
0159
0160 private:
0161 ::pthread_cond_t cond_;
0162 std::size_t state_;
0163 };
0164
0165 }
0166 }
0167 }
0168
0169 #include <boost/asio/detail/pop_options.hpp>
0170
0171 #if defined(BOOST_ASIO_HEADER_ONLY)
0172 # include <boost/asio/detail/impl/posix_event.ipp>
0173 #endif
0174
0175 #endif
0176
0177 #endif