A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
unix-system-condition.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2008 University of Washington
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */
18 
19 #include <pthread.h>
20 #include <cerrno> // for ETIMEDOUT
21 #include <sys/time.h>
22 
23 #include "fatal-error.h"
24 #include "system-condition.h"
25 #include "log.h"
26 
27 
28 NS_LOG_COMPONENT_DEFINE ("SystemCondition");
29 
30 namespace ns3 {
31 
33 public:
35  static const uint64_t NS_PER_SEC = (uint64_t)1000000000;
36 
39 
40  void SetCondition (bool condition);
41  bool GetCondition (void);
42  void Signal (void);
43  void Broadcast (void);
44  void Wait (void);
45  bool TimedWait (uint64_t ns);
46 
47 private:
48  pthread_mutex_t m_mutex;
49  pthread_cond_t m_cond;
51 };
52 
54 {
55  NS_LOG_FUNCTION (this);
56 
57  m_condition = false;
58 
59  pthread_mutexattr_t mAttr;
60  pthread_mutexattr_init (&mAttr);
61 //
62 // Linux and OS X (at least) have, of course chosen different names for the
63 // error checking flags just to make life difficult.
64 //
65 #if defined (PTHREAD_MUTEX_ERRORCHECK_NP)
66  pthread_mutexattr_settype (&mAttr, PTHREAD_MUTEX_ERRORCHECK_NP);
67 #else
68  pthread_mutexattr_settype (&mAttr, PTHREAD_MUTEX_ERRORCHECK);
69 #endif
70  pthread_mutex_init (&m_mutex, &mAttr);
71 
72  pthread_condattr_t cAttr;
73  pthread_condattr_init (&cAttr);
74  pthread_condattr_setpshared (&cAttr, PTHREAD_PROCESS_PRIVATE);
75  pthread_cond_init (&m_cond, &cAttr);
76 }
77 
79 {
80  NS_LOG_FUNCTION (this);
81  pthread_mutex_destroy (&m_mutex);
82  pthread_cond_destroy (&m_cond);
83 }
84 
85 void
87 {
88  NS_LOG_FUNCTION (this << condition);
89  m_condition = condition;
90 }
91 
92 bool
94 {
95  NS_LOG_FUNCTION (this);
96  return m_condition;
97 }
98 
99 void
101 {
102  NS_LOG_FUNCTION (this);
103 
104  pthread_mutex_lock (&m_mutex);
105  pthread_cond_signal (&m_cond);
106  pthread_mutex_unlock (&m_mutex);
107 }
108 
109 void
111 {
112  NS_LOG_FUNCTION (this);
113 
114  pthread_mutex_lock (&m_mutex);
115  pthread_cond_broadcast (&m_cond);
116  pthread_mutex_unlock (&m_mutex);
117 }
118 
119 void
121 {
122  NS_LOG_FUNCTION (this);
123 
124  pthread_mutex_lock (&m_mutex);
125  m_condition = false;
126  while (m_condition == false)
127  {
128  pthread_cond_wait (&m_cond, &m_mutex);
129  }
130  pthread_mutex_unlock (&m_mutex);
131 }
132 
133 bool
135 {
136  NS_LOG_FUNCTION (this << ns);
137 
138  struct timespec ts;
139  ts.tv_sec = ns / NS_PER_SEC;
140  ts.tv_nsec = ns % NS_PER_SEC;
141 
142  struct timeval tv;
143  gettimeofday (&tv, NULL);
144 
145  ts.tv_sec += tv.tv_sec;
146  ts.tv_nsec += tv.tv_usec * 1000;
147  if (ts.tv_nsec > (int64_t)NS_PER_SEC)
148  {
149  ++ts.tv_sec;
150  ts.tv_nsec %= NS_PER_SEC;
151  }
152 
153  int rc;
154 
155  pthread_mutex_lock (&m_mutex);
156  while (m_condition == false)
157  {
158  rc = pthread_cond_timedwait (&m_cond, &m_mutex, &ts);
159  if (rc == ETIMEDOUT)
160  {
161  pthread_mutex_unlock (&m_mutex);
162  return true;
163  }
164  }
165  pthread_mutex_unlock (&m_mutex);
166  return false;
167 }
168 
170  : m_priv (new SystemConditionPrivate ())
171 {
172  NS_LOG_FUNCTION (this);;
173 }
174 
176 {
177  NS_LOG_FUNCTION (this);
178  delete m_priv;
179 }
180 
181 void
183 {
184  NS_LOG_FUNCTION (this << condition);
185  m_priv->SetCondition (condition);
186 }
187 
188 bool
190 {
191  NS_LOG_FUNCTION (this);
192  return m_priv->GetCondition ();
193 }
194 
195 void
197 {
198  NS_LOG_FUNCTION (this);
199  m_priv->Signal ();
200 }
201 
202 void
204 {
205  NS_LOG_FUNCTION (this);
206  m_priv->Broadcast ();
207 }
208 
209 void
211 {
212  NS_LOG_FUNCTION (this);
213  m_priv->Wait ();
214 }
215 
216 bool
218 {
219  NS_LOG_FUNCTION (this << ns);
220  return m_priv->TimedWait (ns);
221 }
222 
223 } // namespace ns3
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
void Signal(void)
Release one thread if waiting for the condition to be true.
void Broadcast(void)
Release all threads waiting for the condition to be true.
void Wait(void)
Wait, possibly forever, for the condition to be true.
void SetCondition(bool condition)
Set the value of the underlying condition.
bool GetCondition(void)
Get the value of the underlying condition.
bool TimedWait(uint64_t ns)
Wait a maximum of ns nanoseconds for the condition to be true.
SystemConditionPrivate * m_priv
static const uint64_t NS_PER_SEC
Conversion from ns to s.