Ice 3.7 C++11 API Reference
Monitor.h
Go to the documentation of this file.
1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 #ifndef ICE_UTIL_MONITOR_H
6 #define ICE_UTIL_MONITOR_H
7 
8 #include <IceUtil/Config.h>
9 #include <IceUtil/Lock.h>
10 #include <IceUtil/Cond.h>
11 
12 namespace IceUtil
13 {
14 
15 //
16 // This monitor implements the Mesa monitor semantics. That is any
17 // calls to notify() or notifyAll() are delayed until the monitor is
18 // unlocked.
19 //
20 template <class T>
21 class Monitor
22 {
23 public:
24 
27 
30 
31  //
32  // Note that lock/tryLock & unlock in general should not be used
33  // directly. Instead use Lock & TryLock.
34  //
35  void lock() const;
36  void unlock() const;
37  bool tryLock() const;
38 
39  void wait() const;
40  bool timedWait(const Time&) const;
41  void notify();
42  void notifyAll();
43 
44 private:
45 
46  // noncopyable
47  Monitor(const Monitor&);
48  void operator=(const Monitor&);
49 
50  void notifyImpl(int) const;
51 
52  mutable Cond _cond;
53  T _mutex;
54  mutable int _nnotify;
55 };
56 
57 } // End namespace IceUtil
58 
59 //
60 // Since this monitor implements the Mesa monitor semantics calls to
61 // notify() or notifyAll() are delayed until the monitor is
62 // unlocked. This can happen either due to a call to unlock(), or a
63 // call to wait(). The _nnotify flag keeps track of the number of
64 // pending notification calls. -1 indicates a broadcast, a positive
65 // number indicates <n> calls to notify(). The _nnotify flag is reset
66 // upon initial acquisition of the monitor lock (either through a call
67 // to lock(), or a return from wait().
68 //
69 
70 template <class T> inline
72  _nnotify(0)
73 {
74 }
75 
76 template <class T> inline
78 {
79 }
80 
81 template <class T> inline void
83 {
84  _mutex.lock();
85  if(_mutex.willUnlock())
86  {
87  //
88  // On the first mutex acquisition reset the number pending
89  // notifications.
90  //
91  _nnotify = 0;
92  }
93 }
94 
95 template <class T> inline void
97 {
98  if(_mutex.willUnlock())
99  {
100  //
101  // Perform any pending notifications.
102  //
103  notifyImpl(_nnotify);
104  }
105  _mutex.unlock();
106 
107 /*
108  int nnotify = _nnotify;
109  if(_mutex.unlock())
110  {
111  //
112  // Perform any pending notifications.
113  //
114  notifyImpl(nnotify);
115  }
116 */
117 }
118 
119 template <class T> inline bool
121 {
122  bool result = _mutex.tryLock();
123  if(result && _mutex.willUnlock())
124  {
125  //
126  // On the first mutex acquisition reset the number pending
127  // notifications.
128  //
129  _nnotify = 0;
130  }
131  return result;
132 }
133 
134 template <class T> inline void
136 {
137  //
138  // Perform any pending notifies
139  //
140  notifyImpl(_nnotify);
141 
142  //
143  // Wait for a notification
144  //
145  try
146  {
147  _cond.waitImpl(_mutex);
148  //
149  // Reset the nnotify count once wait() returns.
150  //
151  }
152  catch(...)
153  {
154  _nnotify = 0;
155  throw;
156  }
157 
158  _nnotify = 0;
159 }
160 
161 template <class T> inline bool
163 {
164  //
165  // Perform any pending notifies.
166  //
167  notifyImpl(_nnotify);
168 
169  bool rc;
170  //
171  // Wait for a notification.
172  //
173  try
174  {
175  rc = _cond.timedWaitImpl(_mutex, timeout);
176 
177  //
178  // Reset the nnotify count once wait() returns.
179  //
180  }
181  catch(...)
182  {
183  _nnotify = 0;
184  throw;
185  }
186 
187  _nnotify = 0;
188  return rc;
189 }
190 
191 template <class T> inline void
193 {
194  //
195  // Increment the _nnotify flag, unless a broadcast has already
196  // been requested.
197  //
198  if(_nnotify != -1)
199  {
200  ++_nnotify;
201  }
202 }
203 
204 template <class T> inline void
206 {
207  //
208  // -1 (indicates broadcast)
209  //
210  _nnotify = -1;
211 }
212 
213 template <class T> inline void
214 IceUtil::Monitor<T>::notifyImpl(int nnotify) const
215 {
216  //
217  // Zero indicates no notifies.
218  //
219  if(nnotify != 0)
220  {
221  //
222  // -1 means notifyAll.
223  //
224  if(nnotify == -1)
225  {
226  _cond.broadcast();
227  return;
228  }
229  else
230  {
231  //
232  // Otherwise notify n times.
233  //
234  while(nnotify > 0)
235  {
236  _cond.signal();
237  --nnotify;
238  }
239  }
240  }
241 }
242 
243 #endif
IceUtil::TryLockT
Definition: Lock.h:118
IceUtil::Cond
Definition: Cond.h:53
IceUtil::Monitor::notifyAll
void notifyAll()
Definition: Monitor.h:205
IceUtil::Monitor::notify
void notify()
Definition: Monitor.h:192
IceUtil::LockT
Definition: Lock.h:37
IceUtil::Monitor::Monitor
Monitor()
Definition: Monitor.h:71
IceUtil
Definition: Optional.h:1095
IceUtil::Monitor::Lock
LockT< Monitor< T > > Lock
Definition: Monitor.h:25
IceUtil::Monitor::tryLock
bool tryLock() const
Definition: Monitor.h:120
IceUtil::Monitor
Definition: Monitor.h:22
IceUtil::Monitor::wait
void wait() const
Definition: Monitor.h:135
Cond.h
IceUtil::Monitor::timedWait
bool timedWait(const Time &) const
Definition: Monitor.h:162
Lock.h
IceUtil::Time
Definition: Time.h:18
Config.h
IceUtil::Monitor::lock
void lock() const
Definition: Monitor.h:82
IceUtil::Monitor::TryLock
TryLockT< Monitor< T > > TryLock
Definition: Monitor.h:26
IceUtil::Monitor::unlock
void unlock() const
Definition: Monitor.h:96
IceUtil::Monitor::~Monitor
~Monitor()
Definition: Monitor.h:77