RCFProto
 All Classes Functions Typedefs
posix_event.hpp
1 
2 //******************************************************************************
3 // RCF - Remote Call Framework
4 //
5 // Copyright (c) 2005 - 2013, Delta V Software. All rights reserved.
6 // http://www.deltavsoft.com
7 //
8 // RCF is distributed under dual licenses - closed source or GPL.
9 // Consult your particular license for conditions of use.
10 //
11 // If you have not purchased a commercial license, you are using RCF
12 // under GPL terms.
13 //
14 // Version: 2.0
15 // Contact: support <at> deltavsoft.com
16 //
17 //******************************************************************************
18 
19 //
20 // detail/posix_event.hpp
21 // ~~~~~~~~~~~~~~~~~~~~~~
22 //
23 // Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
24 //
25 // Distributed under the Boost Software License, Version 1.0. (See accompanying
26 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
27 //
28 
29 #ifndef RCF_DETAIL_POSIX_EVENT_HPP
30 #define RCF_DETAIL_POSIX_EVENT_HPP
31 
32 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
33 # pragma once
34 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
35 
36 #if defined(BOOST_HAS_PTHREADS)
37 
38 #include <boost/assert.hpp>
39 #include <pthread.h>
40 #include <errno.h>
41 
42 #include <RCF/thread/push_options.hpp>
43 
44 #include <sys/time.h>
45 
46 namespace RCF {
47 namespace detail {
48 
49 class posix_event
50  : private noncopyable
51 {
52 public:
53  // Constructor.
54  RCF_EXPORT posix_event();
55 
56  // Destructor.
57  ~posix_event()
58  {
59  ::pthread_cond_destroy(&cond_);
60  }
61 
62  // Signal one waiting thread.
63  template <typename Lock>
64  void signal_one(Lock& lock)
65  {
66  BOOST_ASSERT(lock.locked());
67  (void)lock;
68  ::pthread_cond_signal(&cond_); // Ignore EINVAL.
69  }
70 
71  // Signal all waiting threads.
72  template <typename Lock>
73  void signal_all(Lock& lock)
74  {
75  BOOST_ASSERT(lock.locked());
76  (void)lock;
77  ::pthread_cond_broadcast(&cond_); // Ignore EINVAL.
78  }
79 
80  // Reset the event.
81  template <typename Lock>
82  void clear(Lock& lock)
83  {
84  BOOST_ASSERT(lock.locked());
85  (void)lock;
86  }
87 
88  // Wait for the event to become signalled.
89  template <typename Lock>
90  void wait(Lock& lock)
91  {
92  // POSIX automatically unlocks and locks the mutex.
93 
94  BOOST_ASSERT(lock.locked());
95  ::pthread_cond_wait(&cond_, &lock.mutex().mutex_); // Ignore EINVAL.
96  }
97 
98  template <typename Lock>
99  bool timed_wait(Lock& lock, boost::uint32_t waitMs)
100  {
101  BOOST_ASSERT(lock.locked());
102 
103  struct timeval tp = {0};
104  gettimeofday(&tp, NULL);
105 
106  // Convert from timeval to timespec.
107  struct timespec ts = {0};
108  ts.tv_sec = tp.tv_sec;
109  ts.tv_nsec = tp.tv_usec * 1000;
110 
111  // Add waitMs to current time.
112  ts.tv_sec += (waitMs / 1000);
113  boost::uint32_t remainderMs = waitMs % 1000;
114  ts.tv_nsec += (remainderMs * 1000 * 1000);
115 
116  // Check for overflow in tv_nsec.
117  if (ts.tv_nsec >= 1000*1000*1000)
118  {
119  BOOST_ASSERT(ts.tv_nsec < 2*1000*1000*1000);
120  ts.tv_sec += 1;
121  ts.tv_nsec -= 1000*1000*1000;
122  }
123 
124  // POSIX automatically unlocks and locks the mutex.
125 
126  int ret = ::pthread_cond_timedwait(&cond_, &lock.mutex().mutex_, &ts); // Ignore EINVAL.
127  if (ret == ETIMEDOUT)
128  {
129  return false;
130  }
131 
132  return true;
133  }
134 
135  // Signal the event.
136  template <typename Lock>
137  void notify_all(Lock& lock)
138  {
139  signal_all(lock);
140  }
141 
142 protected:
143  ::pthread_cond_t cond_;
144 };
145 
146 } // namespace detail
147 } // namespace RCF
148 
149 #include <RCF/thread/pop_options.hpp>
150 
151 
152 #endif // defined(BOOST_HAS_PTHREADS)
153 
154 #endif // RCF_DETAIL_POSIX_EVENT_HPP