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
25namespace asio {
26namespace detail {
27
28class posix_event
29  : private noncopyable
30{
31public:
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
107private:
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