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 
104 
105 #ifdef RCF_USE_CLOCK_MONOTONIC
106 
107  struct timespec ts = {0};
108  clock_gettime(CLOCK_MONOTONIC, &ts);
109 
110 #else
111 
112  struct timeval tp = {0};
113  gettimeofday(&tp, NULL);
114 
115  // Convert from timeval to timespec.
116  struct timespec ts = {0};
117  ts.tv_sec = tp.tv_sec;
118  ts.tv_nsec = tp.tv_usec * 1000;
119 
120 #endif
121 
122  // Add waitMs to current time.
123  ts.tv_sec += (waitMs / 1000);
124  boost::uint32_t remainderMs = waitMs % 1000;
125  ts.tv_nsec += (remainderMs * 1000 * 1000);
126 
127  // Check for overflow in tv_nsec.
128  if (ts.tv_nsec >= 1000*1000*1000)
129  {
130  BOOST_ASSERT(ts.tv_nsec < 2*1000*1000*1000);
131  ts.tv_sec += 1;
132  ts.tv_nsec -= 1000*1000*1000;
133  }
134 
135  // POSIX automatically unlocks and locks the mutex.
136 
137  int ret = ::pthread_cond_timedwait(&cond_, &lock.mutex().mutex_, &ts); // Ignore EINVAL.
138  if (ret == ETIMEDOUT)
139  {
140  return false;
141  }
142 
143  return true;
144  }
145 
146  // Signal the event.
147  template <typename Lock>
148  void notify_all(Lock& lock)
149  {
150  signal_all(lock);
151  }
152 
153 protected:
154  ::pthread_cond_t cond_;
155  ::pthread_condattr_t condattr_;
156 };
157 
158 } // namespace detail
159 } // namespace RCF
160 
161 #include <RCF/thread/pop_options.hpp>
162 
163 
164 #endif // defined(BOOST_HAS_PTHREADS)
165 
166 #endif // RCF_DETAIL_POSIX_EVENT_HPP