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