1 // 2 // detail/win_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_WIN_EVENT_HPP 12 #define BOOST_ASIO_DETAIL_WIN_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_WINDOWS) 21 22 #include <boost/asio/detail/assert.hpp> 23 #include <boost/asio/detail/noncopyable.hpp> 24 #include <boost/asio/detail/socket_types.hpp> 25 26 #include <boost/asio/detail/push_options.hpp> 27 28 namespace boost { 29 namespace asio { 30 namespace detail { 31 32 class win_event 33 : private noncopyable 34 { 35 public: 36 // Constructor. 37 BOOST_ASIO_DECL win_event(); 38 39 // Destructor. 40 BOOST_ASIO_DECL ~win_event(); 41 42 // Signal the event. (Retained for backward compatibility.) 43 template <typename Lock> signal(Lock & lock)44 void signal(Lock& lock) 45 { 46 this->signal_all(lock); 47 } 48 49 // Signal all waiters. 50 template <typename Lock> signal_all(Lock & lock)51 void signal_all(Lock& lock) 52 { 53 BOOST_ASIO_ASSERT(lock.locked()); 54 (void)lock; 55 state_ |= 1; 56 ::SetEvent(events_[0]); 57 } 58 59 // Unlock the mutex and signal one waiter. 60 template <typename Lock> unlock_and_signal_one(Lock & lock)61 void unlock_and_signal_one(Lock& lock) 62 { 63 BOOST_ASIO_ASSERT(lock.locked()); 64 state_ |= 1; 65 bool have_waiters = (state_ > 1); 66 lock.unlock(); 67 if (have_waiters) 68 ::SetEvent(events_[1]); 69 } 70 71 // If there's a waiter, unlock the mutex and signal it. 72 template <typename Lock> maybe_unlock_and_signal_one(Lock & lock)73 bool maybe_unlock_and_signal_one(Lock& lock) 74 { 75 BOOST_ASIO_ASSERT(lock.locked()); 76 state_ |= 1; 77 if (state_ > 1) 78 { 79 lock.unlock(); 80 ::SetEvent(events_[1]); 81 return true; 82 } 83 return false; 84 } 85 86 // Reset the event. 87 template <typename Lock> clear(Lock & lock)88 void clear(Lock& lock) 89 { 90 BOOST_ASIO_ASSERT(lock.locked()); 91 (void)lock; 92 ::ResetEvent(events_[0]); 93 state_ &= ~std::size_t(1); 94 } 95 96 // Wait for the event to become signalled. 97 template <typename Lock> wait(Lock & lock)98 void wait(Lock& lock) 99 { 100 BOOST_ASIO_ASSERT(lock.locked()); 101 while ((state_ & 1) == 0) 102 { 103 state_ += 2; 104 lock.unlock(); 105 ::WaitForMultipleObjects(2, events_, false, INFINITE); 106 lock.lock(); 107 state_ -= 2; 108 } 109 } 110 111 private: 112 HANDLE events_[2]; 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/win_event.ipp> 124 #endif // defined(BOOST_ASIO_HEADER_ONLY) 125 126 #endif // defined(BOOST_ASIO_WINDOWS) 127 128 #endif // BOOST_ASIO_DETAIL_WIN_EVENT_HPP 129