IBR-DTNSuite  0.10
Conditional.cpp
Go to the documentation of this file.
1 /*
2  * Conditional.cpp
3  *
4  * Copyright (C) 2011 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
22 #include "ibrcommon/config.h"
25 #include <sys/time.h>
26 #include <unistd.h>
27 
28 #ifdef __DEVELOPMENT_ASSERTIONS__
29 #include <cassert>
30 #endif
31 
32 #include <pthread.h>
33 
34 namespace ibrcommon
35 {
36  Conditional::Conditional() : Mutex(MUTEX_NORMAL), _abort(false)
37  {
38  pthread_cond_init(&cond, &attr.attr);
39  }
40 
42  {
43  pthread_cond_destroy(&cond);
44  }
45 
46  bool Conditional::isLocked()
47  {
48  try {
49  trylock();
50  leave();
51  } catch (const ibrcommon::MutexException&) {
52  return true;
53  }
54 
55  return false;
56  }
57 
58  void Conditional::signal (bool broadcast) throw ()
59  {
60 #ifdef __DEVELOPMENT_ASSERTIONS__
61  // assert a locked Conditional
62  assert(isLocked());
63 #endif
64 
65  if (broadcast)
66  pthread_cond_broadcast( &cond );
67  else
68  pthread_cond_signal( &cond );
69  }
70 
71  void Conditional::wait(size_t timeout) throw (ConditionalAbortException)
72  {
73 #ifdef __DEVELOPMENT_ASSERTIONS__
74  // assert a locked Conditional
75  assert(isLocked());
76 #endif
77 
78  if (_abort) throw ConditionalAbortException(ConditionalAbortException::COND_ABORT);
79 
80  if (timeout == 0)
81  {
82  pthread_cond_wait( &cond, &m_mutex );
83  if (_abort) throw ConditionalAbortException(ConditionalAbortException::COND_ABORT);
84  }
85  else
86  {
87  struct timespec ts;
88  gettimeout(timeout, &ts);
89  wait(&ts);
90  if (_abort) throw ConditionalAbortException(ConditionalAbortException::COND_ABORT);
91  }
92  }
93 
94  void Conditional::wait(struct timespec *ts) throw (ConditionalAbortException)
95  {
96 #ifdef __DEVELOPMENT_ASSERTIONS__
97  // assert a locked Conditional
98  assert(isLocked());
99 #endif
100 
101  if (_abort) throw ConditionalAbortException(ConditionalAbortException::COND_ABORT);
102 
103  int ret = pthread_cond_timedwait(&cond, &m_mutex, ts);
104 
105  if(ret == ETIMEDOUT)
106  {
107  throw ConditionalAbortException(ConditionalAbortException::COND_TIMEOUT, "conditional wait timed out");
108  }
109  else if (ret != 0)
110  {
111  throw ConditionalAbortException(ConditionalAbortException::COND_ERROR, "error on locking conditional mutex");
112  }
113 
114  if (_abort) throw ConditionalAbortException(ConditionalAbortException::COND_ABORT);
115  }
116 
117  Conditional::attribute Conditional::attr;
118 
119  Conditional::attribute::attribute()
120  {
121  pthread_condattr_init(&attr);
122 
123 #if _POSIX_TIMERS > 0 && defined(HAVE_PTHREAD_CONDATTR_SETCLOCK)
124  #if defined(_POSIX_MONOTONIC_CLOCK)
125  pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
126  #else
127  pthread_condattr_setclock(&attr, CLOCK_REALTIME);
128  #endif
129 #endif
130  }
131 
132  void Conditional::gettimeout(size_t msec, struct timespec *ts) throw ()
133  {
134 #if _POSIX_TIMERS > 0 && defined(HAVE_PTHREAD_CONDATTR_SETCLOCK)
135  #if defined(_POSIX_MONOTONIC_CLOCK)
136  clock_gettime(CLOCK_MONOTONIC, ts);
137  #else
138  clock_gettime(CLOCK_REALTIME, ts);
139  #endif
140 #else
141  timeval tv;
142  ::gettimeofday(&tv, NULL);
143  ts->tv_sec = tv.tv_sec;
144  ts->tv_nsec = tv.tv_usec * 1000l;
145 #endif
146  ts->tv_sec += msec / 1000;
147  ts->tv_nsec += (msec % 1000) * 1000000l;
148  while(ts->tv_nsec > 1000000000l) {
149  ++ts->tv_sec;
150  ts->tv_nsec -= 1000000000l;
151  }
152  }
153 
154  void Conditional::abort() throw ()
155  {
156 #ifdef __DEVELOPMENT_ASSERTIONS__
157  // assert a locked Conditional
158  assert(isLocked());
159 #endif // __DEVELOPMENT_ASSERTIONS__
160 
161  signal(true);
162  _abort = true;
163  }
164 
165  void Conditional::reset() throw ()
166  {
167  _abort = false;
168  }
169 }
170