Ice 3.7 C++11 API Reference
IceUtil
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
25
typedef
LockT<Monitor<T>
>
Lock
;
26
typedef
TryLockT<Monitor<T>
>
TryLock
;
27
28
Monitor
();
29
~Monitor
();
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
71
IceUtil::Monitor<T>::Monitor
() :
72
_nnotify(0)
73
{
74
}
75
76
template
<
class
T>
inline
77
IceUtil::Monitor<T>::~Monitor
()
78
{
79
}
80
81
template
<
class
T>
inline
void
82
IceUtil::Monitor<T>::lock
()
const
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
96
IceUtil::Monitor<T>::unlock
()
const
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
120
IceUtil::Monitor<T>::tryLock
()
const
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
135
IceUtil::Monitor<T>::wait
()
const
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
162
IceUtil::Monitor<T>::timedWait
(
const
Time
& timeout)
const
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
192
IceUtil::Monitor<T>::notify
()
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
205
IceUtil::Monitor<T>::notifyAll
()
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
Generated by
1.8.20