Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:45

0001 //
0002 // detail/std_event.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_DETAIL_STD_EVENT_HPP
0012 #define BOOST_ASIO_DETAIL_STD_EVENT_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 #include <chrono>
0020 #include <condition_variable>
0021 #include <boost/asio/detail/assert.hpp>
0022 #include <boost/asio/detail/noncopyable.hpp>
0023 
0024 #include <boost/asio/detail/push_options.hpp>
0025 
0026 namespace boost {
0027 namespace asio {
0028 namespace detail {
0029 
0030 class std_event
0031   : private noncopyable
0032 {
0033 public:
0034   // Constructor.
0035   std_event()
0036     : state_(0)
0037   {
0038   }
0039 
0040   // Destructor.
0041   ~std_event()
0042   {
0043   }
0044 
0045   // Signal the event. (Retained for backward compatibility.)
0046   template <typename Lock>
0047   void signal(Lock& lock)
0048   {
0049     this->signal_all(lock);
0050   }
0051 
0052   // Signal all waiters.
0053   template <typename Lock>
0054   void signal_all(Lock& lock)
0055   {
0056     BOOST_ASIO_ASSERT(lock.locked());
0057     (void)lock;
0058     state_ |= 1;
0059     cond_.notify_all();
0060   }
0061 
0062   // Unlock the mutex and signal one waiter.
0063   template <typename Lock>
0064   void unlock_and_signal_one(Lock& lock)
0065   {
0066     BOOST_ASIO_ASSERT(lock.locked());
0067     state_ |= 1;
0068     bool have_waiters = (state_ > 1);
0069     lock.unlock();
0070     if (have_waiters)
0071       cond_.notify_one();
0072   }
0073 
0074   // Unlock the mutex and signal one waiter who may destroy us.
0075   template <typename Lock>
0076   void unlock_and_signal_one_for_destruction(Lock& lock)
0077   {
0078     BOOST_ASIO_ASSERT(lock.locked());
0079     state_ |= 1;
0080     bool have_waiters = (state_ > 1);
0081     if (have_waiters)
0082       cond_.notify_one();
0083     lock.unlock();
0084   }
0085 
0086   // If there's a waiter, unlock the mutex and signal it.
0087   template <typename Lock>
0088   bool maybe_unlock_and_signal_one(Lock& lock)
0089   {
0090     BOOST_ASIO_ASSERT(lock.locked());
0091     state_ |= 1;
0092     if (state_ > 1)
0093     {
0094       lock.unlock();
0095       cond_.notify_one();
0096       return true;
0097     }
0098     return false;
0099   }
0100 
0101   // Reset the event.
0102   template <typename Lock>
0103   void clear(Lock& lock)
0104   {
0105     BOOST_ASIO_ASSERT(lock.locked());
0106     (void)lock;
0107     state_ &= ~std::size_t(1);
0108   }
0109 
0110   // Wait for the event to become signalled.
0111   template <typename Lock>
0112   void wait(Lock& lock)
0113   {
0114     BOOST_ASIO_ASSERT(lock.locked());
0115     unique_lock_adapter u_lock(lock);
0116     while ((state_ & 1) == 0)
0117     {
0118       waiter w(state_);
0119       cond_.wait(u_lock.unique_lock_);
0120     }
0121   }
0122 
0123   // Timed wait for the event to become signalled.
0124   template <typename Lock>
0125   bool wait_for_usec(Lock& lock, long usec)
0126   {
0127     BOOST_ASIO_ASSERT(lock.locked());
0128     unique_lock_adapter u_lock(lock);
0129     if ((state_ & 1) == 0)
0130     {
0131       waiter w(state_);
0132       cond_.wait_for(u_lock.unique_lock_, std::chrono::microseconds(usec));
0133     }
0134     return (state_ & 1) != 0;
0135   }
0136 
0137 private:
0138   // Helper class to temporarily adapt a scoped_lock into a unique_lock so that
0139   // it can be passed to std::condition_variable::wait().
0140   struct unique_lock_adapter
0141   {
0142     template <typename Lock>
0143     explicit unique_lock_adapter(Lock& lock)
0144       : unique_lock_(lock.mutex().mutex_, std::adopt_lock)
0145     {
0146     }
0147 
0148     ~unique_lock_adapter()
0149     {
0150       unique_lock_.release();
0151     }
0152 
0153     std::unique_lock<std::mutex> unique_lock_;
0154   };
0155 
0156   // Helper to increment and decrement the state to track outstanding waiters.
0157   class waiter
0158   {
0159   public:
0160     explicit waiter(std::size_t& state)
0161       : state_(state)
0162     {
0163       state_ += 2;
0164     }
0165 
0166     ~waiter()
0167     {
0168       state_ -= 2;
0169     }
0170 
0171   private:
0172     std::size_t& state_;
0173   };
0174 
0175   std::condition_variable cond_;
0176   std::size_t state_;
0177 };
0178 
0179 } // namespace detail
0180 } // namespace asio
0181 } // namespace boost
0182 
0183 #include <boost/asio/detail/pop_options.hpp>
0184 
0185 #endif // BOOST_ASIO_DETAIL_STD_EVENT_HPP