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 
34 
36  public:
46  /**
47  To assist in allowing compile-time computation of the algorithmic order of the threading model.
48  */
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:
100  /**
101  To assist in allowing compile-time computation of the algorithmic order of the threading model.
102  */
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),
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) {
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) {
140  return m.unlock();
141  }
142  void decay() noexcept(true) {}
143 
144  private:
145  const tstring name;
146  recursive_anon_mutex mutex_;
147  };
148 
150  public:
153  typedef int count_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) {
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:
213  typedef int count_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),
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".
286  public:
296  /**
297  To assist in allowing compile-time computation of the algorithmic order of the threading model.
298  */
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) {
316  return atom_set;
317  }
318  atomic_state_type __fastcall lock() noexcept(true) {
320  return atom_set;
321  }
322  atomic_state_type __fastcall unlock() noexcept(true) {
324  return atom_unset;
325  }
326  void decay() noexcept(true) {}
327 
328  private:
330  };
331 
332  class semaphore : public lock::lockable<lock_traits>, protected non_copyable {
333  public:
335  typedef int count_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:
362  };
363 
364  class anon_semaphore : public semaphore {
365  public:
366  __stdcall anon_semaphore(const long int max_count, const long int init_count)
368  };
369 
370 } } } }
371 
372 #pragma warning(default:4800)
373 #pragma warning(pop)