fast_mutex.h Source File

Back to the index.

fast_mutex.h
Go to the documentation of this file.
1 /*
2  * Modified for GXemul:
3  *
4  * 1. Classes have Doxygen brief sections, indicating that they are
5  * part of Wu Yongwei's debug new/delete package.
6  */
7 
8 // -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
9 // vim:tabstop=4:shiftwidth=4:expandtab:
10 
11 /*
12  * Copyright (C) 2004-2005 Wu Yongwei <adah at users dot sourceforge dot net>
13  *
14  * This software is provided 'as-is', without any express or implied
15  * warranty. In no event will the authors be held liable for any
16  * damages arising from the use of this software.
17  *
18  * Permission is granted to anyone to use this software for any purpose,
19  * including commercial applications, and to alter it and redistribute
20  * it freely, subject to the following restrictions:
21  *
22  * 1. The origin of this software must not be misrepresented; you must
23  * not claim that you wrote the original software. If you use this
24  * software in a product, an acknowledgment in the product
25  * documentation would be appreciated but is not required.
26  * 2. Altered source versions must be plainly marked as such, and must
27  * not be misrepresented as being the original software.
28  * 3. This notice may not be removed or altered from any source
29  * distribution.
30  *
31  * This file is part of Stones of Nvwa:
32  * http://sourceforge.net/projects/nvwa
33  *
34  */
35 
36 /**
37  * @file fast_mutex.h
38  *
39  * A fast mutex implementation for POSIX and Win32.
40  *
41  * @version 1.18, 2005/05/06
42  * @author Wu Yongwei
43  *
44  */
45 
46 #ifndef _FAST_MUTEX_H
47 #define _FAST_MUTEX_H
48 
49 # if !defined(_NOTHREADS)
50 # if !defined(_WIN32THREADS) && \
51  (defined(_WIN32) && defined(_MT))
52 // Automatically use _WIN32THREADS when specifying -MT/-MD in MSVC,
53 // or -mthreads in MinGW GCC.
54 # define _WIN32THREADS
55 # elif !defined(_PTHREADS) && \
56  defined(_REENTRANT)
57 // Automatically use _PTHREADS when specifying -pthread in GCC.
58 // N.B. I do not detect on _PTHREAD_H since libstdc++-v3 under
59 // Linux will silently include <pthread.h> anyway.
60 # define _PTHREADS
61 # endif
62 # endif
63 
64 # if !defined(_PTHREADS) && !defined(_WIN32THREADS) && !defined(_NOTHREADS)
65 # define _NOTHREADS
66 # endif
67 
68 # if defined(_NOTHREADS)
69 # if defined(_PTHREADS) || defined(_WIN32THREADS)
70 # undef _NOTHREADS
71 # error "Cannot define multi-threaded mode with -D_NOTHREADS"
72 # if defined(__MINGW32__) && defined(_WIN32THREADS) && !defined(_MT)
73 # error "Be sure to specify -mthreads with -D_WIN32THREADS"
74 # endif
75 # endif
76 # endif
77 
78 # ifndef _FAST_MUTEX_CHECK_INITIALIZATION
79 /**
80  * Macro to control whether to check for initialization status for each
81  * lock/unlock operation. Defining it to a non-zero value will enable
82  * the check, so that the construction/destruction of a static object
83  * using a static fast_mutex not yet constructed or already destroyed
84  * will work (with lock/unlock operations ignored). Defining it to zero
85  * will disable to check.
86  */
87 # define _FAST_MUTEX_CHECK_INITIALIZATION 1
88 # endif
89 
90 # if defined(_PTHREADS) && defined(_WIN32THREADS)
91 // Some C++ libraries have _PTHREADS defined even on Win32 platforms.
92 // Thus this hack.
93 # undef _PTHREADS
94 # endif
95 
96 # ifdef _DEBUG
97 # include <stdio.h>
98 # include <stdlib.h>
99 /** Macro for fast_mutex assertions. Real version (for debug mode). */
100 # define _FAST_MUTEX_ASSERT(_Expr, _Msg) \
101  if (!(_Expr)) { \
102  fprintf(stderr, "fast_mutex::%s\n", _Msg); \
103  abort(); \
104  }
105 # else
106 /** Macro for fast_mutex assertions. Fake version (for release mode). */
107 # define _FAST_MUTEX_ASSERT(_Expr, _Msg) \
108  ((void)0)
109 # endif
110 
111 # ifdef _PTHREADS
112 # include <pthread.h>
113 /**
114  * Macro alias to `volatile' semantics. Here it is truly volatile since
115  * it is in a multi-threaded (POSIX threads) environment.
116  */
117 # define __VOLATILE volatile
118  /**
119  * \brief Part of Wu Yongwei's new/delete debug
120  * memory leak detector.
121  *
122  * Class for non-reentrant fast mutexes. This is the implementation
123  * for POSIX threads.
124  */
125  class fast_mutex
126  {
127  pthread_mutex_t _M_mtx_impl;
128 # if _FAST_MUTEX_CHECK_INITIALIZATION
129  bool _M_initialized;
130 # endif
131 # ifdef _DEBUG
132  bool _M_locked;
133 # endif
134  public:
135  fast_mutex()
136 # ifdef _DEBUG
137  : _M_locked(false)
138 # endif
139  {
140  ::pthread_mutex_init(&_M_mtx_impl, NULL);
141 # if _FAST_MUTEX_CHECK_INITIALIZATION
142  _M_initialized = true;
143 # endif
144  }
145  ~fast_mutex()
146  {
147  _FAST_MUTEX_ASSERT(!_M_locked, "~fast_mutex(): still locked");
148 # if _FAST_MUTEX_CHECK_INITIALIZATION
149  _M_initialized = false;
150 # endif
151  ::pthread_mutex_destroy(&_M_mtx_impl);
152  }
153  void lock()
154  {
155 # if _FAST_MUTEX_CHECK_INITIALIZATION
156  if (!_M_initialized)
157  return;
158 # endif
159  ::pthread_mutex_lock(&_M_mtx_impl);
160 # ifdef _DEBUG
161  // The following assertion should _always_ be true for a
162  // real `fast' pthread_mutex. However, this assertion can
163  // help sometimes, when people forget to use `-lpthread' and
164  // glibc provides an empty implementation. Having this
165  // assertion is also more consistent.
166  _FAST_MUTEX_ASSERT(!_M_locked, "lock(): already locked");
167  _M_locked = true;
168 # endif
169  }
170  void unlock()
171  {
172 # if _FAST_MUTEX_CHECK_INITIALIZATION
173  if (!_M_initialized)
174  return;
175 # endif
176 # ifdef _DEBUG
177  _FAST_MUTEX_ASSERT(_M_locked, "unlock(): not locked");
178  _M_locked = false;
179 # endif
180  ::pthread_mutex_unlock(&_M_mtx_impl);
181  }
182  private:
183  fast_mutex(const fast_mutex&);
184  fast_mutex& operator=(const fast_mutex&);
185  };
186 # endif // _PTHREADS
187 
188 # ifdef _WIN32THREADS
189 # include <windows.h>
190 /**
191  * Macro alias to `volatile' semantics. Here it is truly volatile since
192  * it is in a multi-threaded (Win32 threads) environment.
193  */
194 # define __VOLATILE volatile
195  /**
196  * \brief Part of Wu Yongwei's new/delete debug
197  * memory leak detector.
198  *
199  * Class for non-reentrant fast mutexes. This is the implementation
200  * for Win32 threads.
201  */
202  class fast_mutex
203  {
204  CRITICAL_SECTION _M_mtx_impl;
205 # if _FAST_MUTEX_CHECK_INITIALIZATION
206  bool _M_initialized;
207 # endif
208 # ifdef _DEBUG
209  bool _M_locked;
210 # endif
211  public:
212  fast_mutex()
213 # ifdef _DEBUG
214  : _M_locked(false)
215 # endif
216  {
217  ::InitializeCriticalSection(&_M_mtx_impl);
218 # if _FAST_MUTEX_CHECK_INITIALIZATION
219  _M_initialized = true;
220 # endif
221  }
222  ~fast_mutex()
223  {
224  _FAST_MUTEX_ASSERT(!_M_locked, "~fast_mutex(): still locked");
225 # if _FAST_MUTEX_CHECK_INITIALIZATION
226  _M_initialized = false;
227 # endif
228  ::DeleteCriticalSection(&_M_mtx_impl);
229  }
230  void lock()
231  {
232 # if _FAST_MUTEX_CHECK_INITIALIZATION
233  if (!_M_initialized)
234  return;
235 # endif
236  ::EnterCriticalSection(&_M_mtx_impl);
237 # ifdef _DEBUG
238  _FAST_MUTEX_ASSERT(!_M_locked, "lock(): already locked");
239  _M_locked = true;
240 # endif
241  }
242  void unlock()
243  {
244 # if _FAST_MUTEX_CHECK_INITIALIZATION
245  if (!_M_initialized)
246  return;
247 # endif
248 # ifdef _DEBUG
249  _FAST_MUTEX_ASSERT(_M_locked, "unlock(): not locked");
250  _M_locked = false;
251 # endif
252  ::LeaveCriticalSection(&_M_mtx_impl);
253  }
254  private:
255  fast_mutex(const fast_mutex&);
256  fast_mutex& operator=(const fast_mutex&);
257  };
258 # endif // _WIN32THREADS
259 
260 # ifdef _NOTHREADS
261 /**
262  * Macro alias to `volatile' semantics. Here it is not truly volatile
263  * since it is in a single-threaded environment.
264  */
265 # define __VOLATILE
266  /**
267  * \brief Part of Wu Yongwei's new/delete debug
268  * memory leak detector.
269  *
270  * Class for non-reentrant fast mutexes. This is the null
271  * implementation for single-threaded environments.
272  */
274  {
275 # ifdef _DEBUG
276  bool _M_locked;
277 # endif
278  public:
280 # ifdef _DEBUG
281  : _M_locked(false)
282 # endif
283  {
284  }
286  {
287  _FAST_MUTEX_ASSERT(!_M_locked, "~fast_mutex(): still locked");
288  }
289  void lock()
290  {
291 # ifdef _DEBUG
292  _FAST_MUTEX_ASSERT(!_M_locked, "lock(): already locked");
293  _M_locked = true;
294 # endif
295  }
296  void unlock()
297  {
298 # ifdef _DEBUG
299  _FAST_MUTEX_ASSERT(_M_locked, "unlock(): not locked");
300  _M_locked = false;
301 # endif
302  }
303  private:
304  fast_mutex(const fast_mutex&);
305  fast_mutex& operator=(const fast_mutex&);
306  };
307 # endif // _NOTHREADS
308 
309 /**
310  * \brief Part of Wu Yongwei's new/delete debug
311  * memory leak detector.
312  *
313  * An acquistion-on-initialization lock class based on fast_mutex.
314  */
316 {
317  fast_mutex& _M_mtx;
318 public:
319  explicit fast_mutex_autolock(fast_mutex& __mtx) : _M_mtx(__mtx)
320  {
321  _M_mtx.lock();
322  }
324  {
325  _M_mtx.unlock();
326  }
327 private:
329  fast_mutex_autolock& operator=(const fast_mutex_autolock&);
330 };
331 
332 #endif // _FAST_MUTEX_H
fast_mutex::unlock
void unlock()
Definition: fast_mutex.h:296
fast_mutex::fast_mutex
fast_mutex()
Definition: fast_mutex.h:279
fast_mutex_autolock
Part of Wu Yongwei's new/delete debug memory leak detector.
Definition: fast_mutex.h:316
fast_mutex::lock
void lock()
Definition: fast_mutex.h:289
fast_mutex_autolock::~fast_mutex_autolock
~fast_mutex_autolock()
Definition: fast_mutex.h:323
fast_mutex
Part of Wu Yongwei's new/delete debug memory leak detector.
Definition: fast_mutex.h:274
fast_mutex::~fast_mutex
~fast_mutex()
Definition: fast_mutex.h:285
_FAST_MUTEX_ASSERT
#define _FAST_MUTEX_ASSERT(_Expr, _Msg)
Definition: fast_mutex.h:107
fast_mutex_autolock::fast_mutex_autolock
fast_mutex_autolock(fast_mutex &__mtx)
Definition: fast_mutex.h:319

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18