libjmmcg
release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
NTLocking.hpp
Go to the documentation of this file.
1
/******************************************************************************
2
** Copyright © 2002 by J.M.McGuiness, coder@hussar.me.uk
3
**
4
** This library is free software; you can redistribute it and/or
5
** modify it under the terms of the GNU Lesser General Public
6
** License as published by the Free Software Foundation; either
7
** version 2.1 of the License, or (at your option) any later version.
8
**
9
** This library 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 GNU
12
** Lesser General Public License for more details.
13
**
14
** You should have received a copy of the GNU Lesser General Public
15
** License along with this library; if not, write to the Free Software
16
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
*/
18
// DESCRIPTION:
19
// Various classes for wrapping NT event, mutex, critical section, locked counters and semaphore objects.
20
21
#
pragma
once
22
23
#
include
"GetGUID.hpp"
24
25
// This is all implemented inline in the header file for raw speed. It *must* be
26
// as FAST AS POSSIBLE....
27
28
#
pragma
warning
(
push
)
29
#
pragma
warning
(
disable
:
4800
)
// forcing value to bool 'true' or 'false' (performance warning)
30
31
namespace
jmmcg
{
namespace
LIBJMMCG_VER_NAMESPACE
{
namespace
ppd
{
namespace
NTUtils
{
32
33
typedef
api_lock_traits
<
ppd
::
generic_traits
::
MS_Win32
,
heavyweight_threading
>
lock_traits
;
34
35
class
recursive_anon_mutex
:
public
lock
::
lockable
<
lock_traits
>,
protected
non_copyable
{
36
public
:
37
typedef
lock
::
lockable
<
api_lock_traits
<
ppd
::
generic_traits
::
MS_Win32
,
heavyweight_threading
> >
base_t
;
38
typedef
base_t
::
lock_traits
lock_traits
;
39
typedef
lock_traits
::
exception_type
exception_type
;
40
typedef
lock
::
in_process
<
recursive_anon_mutex
>
lock_type
;
41
typedef
lock_type
read_lock_type
;
42
typedef
lock_type
write_lock_type
;
43
typedef
lock
::
in_process_unlockable
<
recursive_anon_mutex
>
unlockable_type
;
44
typedef
unlockable_type
read_unlockable_type
;
45
typedef
unlockable_type
write_unlockable_type
;
46
/**
47
To assist in allowing compile-time computation of the algorithmic order of the threading model.
48
*/
49
static
constexpr
generic_traits
::
memory_access_modes
memory_access_mode
=
generic_traits
::
memory_access_modes
::
erew_memory_access
;
50
51
explicit
__stdcall
recursive_anon_mutex
(
const
SECURITY_ATTRIBUTES *
const
sa =
NULL
)
52
:
sec_attrib
(
sa
),
53
mutex_
(::
CreateMutex
(
const_cast
<
SECURITY_ATTRIBUTES
*
const
>(
sec_attrib
),
false
,
NULL
)) {
54
assert(mutex_);
55
}
56
virtual
__stdcall
~
recursive_anon_mutex
()
noexcept
(
true
) {
57
::CloseHandle(mutex_);
58
}
59
60
const
SECURITY_ATTRIBUTES
*
const
__fastcall
SA
()
const
noexcept
(
true
) {
61
return
sec_attrib;
62
}
63
__fastcall
operator
handle_type
()
noexcept
(
true
) {
64
return
mutex_
;
65
}
66
atomic_state_type
__fastcall
lock
(
const
timeout_type
period
)
noexcept
(
true
) {
67
return
static_cast
<
atomic_state_type
>(::
WaitForSingleObject
(
mutex_
,
period
));
68
}
69
atomic_state_type
__fastcall
lock
()
noexcept
(
true
) {
70
return
lock
(
infinite_timeout
());
71
}
72
atomic_state_type
__fastcall
unlock
()
noexcept
(
true
) {
73
return
static_cast
<
atomic_state_type
>(::
ReleaseMutex
(
mutex_
));
74
}
75
void
decay
()
noexcept
(
true
) {}
76
77
private
:
78
friend
class
recursive_mutex
;
79
80
const
SECURITY_ATTRIBUTES *
const
sec_attrib;
81
handle_type mutex_;
82
83
explicit
__stdcall
recursive_anon_mutex(
const
tstring
&n,
const
SECURITY_ATTRIBUTES *
const
sa)
84
: sec_attrib(sa),
85
mutex_(::CreateMutex(
const_cast
<SECURITY_ATTRIBUTES *
const
>(sec_attrib),
false
,n.c_str())) {
86
}
87
};
88
89
class
recursive_mutex
:
public
lock
::
lockable
<
lock_traits
>,
protected
non_assignable
{
90
public
:
91
typedef
lock
::
lockable
<
api_lock_traits
<
ppd
::
generic_traits
::
MS_Win32
,
heavyweight_threading
> >
base_t
;
92
typedef
base_t
::
lock_traits
lock_traits
;
93
typedef
lock_traits
::
exception_type
exception_type
;
94
typedef
lock
::
in_process
<
recursive_mutex
>
lock_type
;
95
typedef
lock_type
read_lock_type
;
96
typedef
lock_type
write_lock_type
;
97
typedef
lock
::
in_process_unlockable
<
recursive_mutex
>
unlockable_type
;
98
typedef
unlockable_type
read_unlockable_type
;
99
typedef
unlockable_type
write_unlockable_type
;
100
/**
101
To assist in allowing compile-time computation of the algorithmic order of the threading model.
102
*/
103
static
constexpr
generic_traits
::
memory_access_modes
memory_access_mode
=
generic_traits
::
memory_access_modes
::
erew_memory_access
;
104
105
explicit
__stdcall
recursive_mutex
(
const
tstring
&n =
_T
(
""
),
const
SECURITY_ATTRIBUTES *
const
sa =
NULL
)
106
:
name
(
n
==
_T
(
""
) ?
NTUtils
::
GetGUID
() :
n
),
107
mutex_
(
name
,
sa
) {
108
}
109
__stdcall
recursive_mutex
(
const
recursive_mutex
&m)
110
:
name
(
m
.
name
),
111
mutex_
(
name
,
m
.
mutex_
.
sec_attrib
) {
112
}
113
virtual
__stdcall
~
recursive_mutex
()
noexcept
(
true
) {
114
}
115
116
const
tstring
&
__fastcall
Name
()
const
noexcept
(
true
) {
117
return
name;
118
}
119
const
SECURITY_ATTRIBUTES
*
const
__fastcall
SA
()
const
noexcept
(
true
) {
120
return
mutex_.SA();
121
}
122
__fastcall
operator
handle_type
()
noexcept
(
true
) {
123
return
mutex_
.
operator
handle_type
();
124
}
125
atomic_state_type
__fastcall
lock
(
const
timeout_type
period
)
noexcept
(
true
) {
126
return
mutex_
.
lock
(
period
);
127
}
128
atomic_state_type
__fastcall
unlock
()
noexcept
(
true
) {
129
return
mutex_
.
unlock
();
130
}
131
static
const
atomic_state_type
__fastcall
lock
(
const
tstring
&
name
,
const
timeout_type
period
,
const
SECURITY_ATTRIBUTES
*
const
sa
=
NULL
) {
132
recursive_mutex
m
(
name
,
sa
);
133
return
m
.
lock
(
period
);
134
}
135
atomic_state_type
__fastcall
lock
()
noexcept
(
true
) {
136
return
lock
(
infinite_timeout
());
137
}
138
static
atomic_state_type
__fastcall
unlock
(
const
tstring
&
name
,
const
SECURITY_ATTRIBUTES
*
const
sa
=
NULL
) {
139
recursive_mutex
m
(
name
,
sa
);
140
return
m
.
unlock
();
141
}
142
void
decay
()
noexcept
(
true
) {}
143
144
private
:
145
const
tstring
name
;
146
recursive_anon_mutex
mutex_;
147
};
148
149
class
anon_event
:
public
lock
::
lockable_settable
<
lock_traits
>,
protected
non_copyable
{
150
public
:
151
typedef
lock
::
lockable_settable
<
api_lock_traits
<
ppd
::
generic_traits
::
MS_Win32
,
heavyweight_threading
> >
base_t
;
152
typedef
base_t
::
lock_traits
lock_traits
;
153
typedef
int
count_type
;
154
typedef
lock_traits
::
exception_type
exception_type
;
155
typedef
base_t
::
atomic_state_type
atomic_state_type
;
156
typedef
atomic_state_type
lock_result_type
;
157
typedef
lock
::
in_process
<
anon_event
>
lock_type
;
158
typedef
lock_type
read_lock_type
;
159
typedef
lock_type
write_lock_type
;
160
161
/**
162
Manual reset and initially signalled.
163
*/
164
explicit
__stdcall
anon_event
(
const
atomic_state_type
state=
atom_set
,
const
SECURITY_ATTRIBUTES *
const
sa =
NULL
)
noexcept
(
true
)
165
:
sec_attrib
(
sa
),
166
event_
(::
CreateEvent
(
const_cast
<
SECURITY_ATTRIBUTES
*
const
>(
sec_attrib
),
true
,
state
==
atom_set
,
NULL
)) {
167
assert(event_);
168
}
169
virtual
__stdcall
~
anon_event
()
noexcept
(
true
) {
170
::CloseHandle(event_);
171
}
172
173
const
SECURITY_ATTRIBUTES
*
const
__fastcall
SA
()
const
noexcept
(
true
) {
174
return
sec_attrib;
175
}
176
__fastcall
operator
handle_type
()
noexcept
(
true
) {
177
return
event_
;
178
}
179
atomic_state_type
__fastcall
set
()
noexcept
(
true
) {
180
return
static_cast
<
atomic_state_type
>(::
SetEvent
(
event_
));
181
}
182
atomic_state_type
__fastcall
reset
()
noexcept
(
true
) {
183
return
unlock
();
184
}
185
lock_result_type
__fastcall
lock
()
noexcept
(
true
) {
186
return
static_cast
<
atomic_state_type
>(::
WaitForSingleObject
(
event_
,
infinite_timeout
()));
187
}
188
lock_result_type
__fastcall
lock
(
const
timeout_type
period
)
noexcept
(
true
) {
189
return
static_cast
<
atomic_state_type
>(::
WaitForSingleObject
(
event_
,
period
));
190
}
191
lock_result_type
__fastcall
unlock
()
noexcept
(
true
) {
192
return
static_cast
<
atomic_state_type
>(::
ResetEvent
(
event_
));
193
}
194
void
clear
()
noexcept
(
true
);
195
void
decay
()
noexcept
(
true
) {}
196
197
private
:
198
friend
class
event
;
199
200
const
SECURITY_ATTRIBUTES *
const
sec_attrib;
201
handle_type event_;
202
203
__stdcall
anon_event(
const
atomic_state_type
state,
const
tstring
&n,
const
SECURITY_ATTRIBUTES *
const
sa)
noexcept
(
true
)
204
: sec_attrib(sa),
205
event_(::CreateEvent(
const_cast
<SECURITY_ATTRIBUTES *
const
>(sec_attrib),
true
, state==atom_set, n.c_str())) {
206
}
207
};
208
209
class
event
:
public
lock
::
lockable_settable
<
lock_traits
>,
protected
non_assignable
{
210
public
:
211
typedef
lock
::
lockable_settable
<
api_lock_traits
<
ppd
::
generic_traits
::
MS_Win32
,
heavyweight_threading
> >
base_t
;
212
typedef
base_t
::
lock_traits
lock_traits
;
213
typedef
int
count_type
;
214
typedef
lock_traits
::
exception_type
exception_type
;
215
typedef
base_t
::
atomic_state_type
atomic_state_type
;
216
typedef
atomic_state_type
lock_result_type
;
217
typedef
lock
::
in_process
<
anon_event
>
lock_type
;
218
typedef
lock_type
read_lock_type
;
219
typedef
lock_type
write_lock_type
;
220
221
/**
222
Manual reset and initially signalled.
223
*/
224
explicit
__stdcall
event
(
const
atomic_state_type
s=
atom_set
,
const
tstring
&n =
_T
(
""
),
const
SECURITY_ATTRIBUTES *
const
sa =
NULL
)
225
:
name
(
n
==
_T
(
""
) ?
NTUtils
::
GetGUID
() :
n
),
226
state
(
s
),
227
event_
(
state
,
name
,
sa
) {
228
}
229
__stdcall
event
(
const
event
&ev)
230
:
name
(
ev
.
name
),
231
state(ev.state),
232
event_
(
state
,
name
,
ev
.
event_
.
sec_attrib
) {
233
}
234
virtual
__stdcall
~
event
()
noexcept
(
true
) {
235
}
236
237
const
tstring
&
__fastcall
Name
()
const
noexcept
(
true
) {
238
return
name;
239
}
240
const
SECURITY_ATTRIBUTES
*
const
__fastcall
SA
()
const
noexcept
(
true
) {
241
return
event_.SA();
242
}
243
__fastcall
operator
handle_type
()
noexcept
(
true
) {
244
return
event_
.
operator
handle_type
();
245
}
246
atomic_state_type
__fastcall
set
()
noexcept
(
true
) {
247
return
event_
.
set
();
248
}
249
atomic_state_type
__fastcall
reset
()
noexcept
(
true
) {
250
return
unlock
();
251
}
252
static
atomic_state_type
__fastcall
set
(
const
tstring
&
name
,
const
SECURITY_ATTRIBUTES
*
const
sa
=
NULL
) {
253
event
e
(
atom_unset
,
name
,
sa
);
254
return
e
.
set
();
255
}
256
static
atomic_state_type
__fastcall
reset
(
const
tstring
&
name
,
const
SECURITY_ATTRIBUTES
*
const
sa
=
NULL
) {
257
return
unlock
(
name
,
sa
);
258
}
259
lock_result_type
__fastcall
lock
()
noexcept
(
true
) {
260
return
event_
.
lock
();
261
}
262
lock_result_type
__fastcall
lock
(
const
timeout_type
period
)
noexcept
(
true
) {
263
return
event_
.
lock
(
period
);
264
}
265
lock_result_type
__fastcall
unlock
()
noexcept
(
true
) {
266
return
event_
.
unlock
();
267
}
268
static
lock_result_type
__fastcall
lock
(
const
tstring
&
name
,
const
timeout_type
period
,
const
SECURITY_ATTRIBUTES
*
const
sa
=
NULL
) {
269
event
e
(
atom_unset
,
name
,
sa
);
270
return
e
.
lock
(
period
);
271
}
272
static
lock_result_type
__fastcall
unlock
(
const
tstring
&
name
,
const
SECURITY_ATTRIBUTES
*
const
sa
)
noexcept
(
true
) {
273
event
e
(
atom_unset
,
name
,
sa
);
274
return
e
.
unlock
();
275
}
276
void
decay
()
noexcept
(
true
) {}
277
278
private
:
279
const
tstring
name
;
280
const
atomic_state_type
state;
281
anon_event
event_;
282
};
283
284
/// Note that Windows NT critical sections cannot be used across processes, as they are un-named. You'll need to use an "event" or "mutex".
285
class
recursive_critical_section
:
public
ppd
::
lock
::
lockable
<
lock_traits
>,
protected
non_copyable
{
286
public
:
287
typedef
lock
::
lockable
<
api_lock_traits
<
ppd
::
generic_traits
::
MS_Win32
,
heavyweight_threading
> >
base_t
;
288
typedef
base_t
::
lock_traits
lock_traits
;
289
typedef
lock_traits
::
exception_type
exception_type
;
290
typedef
lock
::
in_process
<
recursive_critical_section
>
lock_type
;
291
typedef
lock_type
read_lock_type
;
292
typedef
lock_type
write_lock_type
;
293
typedef
lock
::
in_process_unlockable
<
recursive_critical_section
>
unlockable_type
;
294
typedef
unlockable_type
read_unlockable_type
;
295
typedef
unlockable_type
write_unlockable_type
;
296
/**
297
To assist in allowing compile-time computation of the algorithmic order of the threading model.
298
*/
299
static
constexpr
generic_traits
::
memory_access_modes
memory_access_mode
=
generic_traits
::
memory_access_modes
::
erew_memory_access
;
300
301
__stdcall
recursive_critical_section
()
noexcept
(
true
) {
302
::InitializeCriticalSection(&crit_section);
303
}
304
explicit
__stdcall
recursive_critical_section
(
const
timeout_type
)
noexcept
(
true
) {
305
::InitializeCriticalSection(&crit_section);
306
}
307
__stdcall
~
recursive_critical_section
()
noexcept
(
true
) {
308
::DeleteCriticalSection(&crit_section);
309
}
310
311
__fastcall
operator
CRITICAL_SECTION
* ()
noexcept
(
true
) {
312
return
&
crit_section
;
313
}
314
atomic_state_type
__fastcall
lock
(
const
timeout_type
)
noexcept
(
true
) {
315
::
EnterCriticalSection
(&
crit_section
);
316
return
atom_set
;
317
}
318
atomic_state_type
__fastcall
lock
()
noexcept
(
true
) {
319
::
EnterCriticalSection
(&
crit_section
);
320
return
atom_set
;
321
}
322
atomic_state_type
__fastcall
unlock
()
noexcept
(
true
) {
323
::
LeaveCriticalSection
(&
crit_section
);
324
return
atom_unset
;
325
}
326
void
decay
()
noexcept
(
true
) {}
327
328
private
:
329
CRITICAL_SECTION
crit_section
;
330
};
331
332
class
semaphore
:
public
lock
::
lockable
<
lock_traits
>,
protected
non_copyable
{
333
public
:
334
typedef
lock
::
lockable
<
api_lock_traits
<
ppd
::
generic_traits
::
MS_Win32
,
heavyweight_threading
> >
base_t
;
335
typedef
int
count_type
;
336
typedef
base_t
::
lock_traits
lock_traits
;
337
typedef
base_t
::
atomic_state_type
atomic_state_type
;
338
typedef
lock
::
in_process
<
semaphore
>
lock_type
;
339
typedef
lock_type
read_lock_type
;
340
typedef
lock_type
write_lock_type
;
341
typedef
atomic_state_type
lock_result_type
;
342
343
__stdcall
semaphore
(
const
long
max_count,
const
long
init_count,
tchar
const
*name)
noexcept
(
true
) :
sema
(::
CreateSemaphore
(
NULL
,
init_count
,
max_count
,
name
)) {
344
}
345
__stdcall
~
semaphore
()
noexcept
(
true
) {
346
::CloseHandle(sema);
347
}
348
349
__fastcall
operator
handle_type
() {
350
return
sema
;
351
}
352
353
atomic_state_type
__fastcall
lock
(
const
timeout_type
period
)
noexcept
(
true
) {
354
return
static_cast
<
atomic_state_type
>(::
WaitForSingleObject
(
sema
,
period
));
355
}
356
atomic_state_type
__fastcall
unlock
(
const
long
decrement
=1,
long
*
prev_count
=
NULL
)
noexcept
(
true
) {
357
return
static_cast
<
atomic_state_type
>(::
ReleaseSemaphore
(
sema
,
decrement
,
prev_count
));
358
}
359
360
private
:
361
handle_type
sema
;
362
};
363
364
class
anon_semaphore
:
public
semaphore
{
365
public
:
366
__stdcall
anon_semaphore
(
const
long
int
max_count,
const
long
int
init_count)
367
:
semaphore
(
max_count
,
init_count
,
NULL
) {}
368
};
369
370
} } } }
371
372
#
pragma
warning
(
default
:
4800
)
373
#
pragma
warning
(
pop
)
experimental
NT-based
NTSpecific
NTLocking.hpp
Generated on Tue May 11 2021 17:22:01 for libjmmcg by
1.9.2