SUMO - Simulation of Urban MObility
|
00001 // -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- 00002 // vim:tabstop=4:shiftwidth=4:expandtab: 00003 #ifdef _MSC_VER 00004 #include <windows_config.h> 00005 #else 00006 #include <config.h> 00007 #endif 00008 #ifdef CHECK_MEMORY_LEAKS 00009 /* 00010 * Copyright (C) 2004-2008 Wu Yongwei <adah at users dot sourceforge dot net> 00011 * 00012 * This software is provided 'as-is', without any express or implied 00013 * warranty. In no event will the authors be held liable for any 00014 * damages arising from the use of this software. 00015 * 00016 * Permission is granted to anyone to use this software for any purpose, 00017 * including commercial applications, and to alter it and redistribute 00018 * it freely, subject to the following restrictions: 00019 * 00020 * 1. The origin of this software must not be misrepresented; you must 00021 * not claim that you wrote the original software. If you use this 00022 * software in a product, an acknowledgement in the product 00023 * documentation would be appreciated but is not required. 00024 * 2. Altered source versions must be plainly marked as such, and must 00025 * not be misrepresented as being the original software. 00026 * 3. This notice may not be removed or altered from any source 00027 * distribution. 00028 * 00029 * This file is part of Stones of Nvwa: 00030 * http://sourceforge.net/projects/nvwa 00031 * 00032 */ 00033 00044 #ifndef _FAST_MUTEX_H 00045 #define _FAST_MUTEX_H 00046 00047 # if !defined(_NOTHREADS) 00048 # if !defined(_WIN32THREADS) && \ 00049 (defined(_WIN32) && defined(_MT)) 00050 // Automatically use _WIN32THREADS when specifying -MT/-MD in MSVC, 00051 // or -mthreads in MinGW GCC. 00052 # define _WIN32THREADS 00053 # elif !defined(_PTHREADS) && \ 00054 defined(_REENTRANT) 00055 // Automatically use _PTHREADS when specifying -pthread in GCC. 00056 // N.B. I do not detect on _PTHREAD_H since libstdc++-v3 under 00057 // Linux will silently include <pthread.h> anyway. 00058 # define _PTHREADS 00059 # endif 00060 # endif 00061 00062 # if !defined(_PTHREADS) && !defined(_WIN32THREADS) && !defined(_NOTHREADS) 00063 # define _NOTHREADS 00064 # endif 00065 00066 # if defined(_NOTHREADS) 00067 # if defined(_PTHREADS) || defined(_WIN32THREADS) 00068 # undef _NOTHREADS 00069 # error "Cannot define multi-threaded mode with -D_NOTHREADS" 00070 # if defined(__MINGW32__) && defined(_WIN32THREADS) && !defined(_MT) 00071 # error "Be sure to specify -mthreads with -D_WIN32THREADS" 00072 # endif 00073 # endif 00074 # endif 00075 00076 # ifndef _FAST_MUTEX_CHECK_INITIALIZATION 00077 00085 # define _FAST_MUTEX_CHECK_INITIALIZATION 1 00086 # endif 00087 00088 # if defined(_PTHREADS) && defined(_WIN32THREADS) 00089 // Some C++ libraries have _PTHREADS defined even on Win32 platforms. 00090 // Thus this hack. 00091 # undef _PTHREADS 00092 # endif 00093 00094 # ifdef _DEBUG 00095 # include <stdio.h> 00096 # include <stdlib.h> 00098 # define _FAST_MUTEX_ASSERT(_Expr, _Msg) \ 00099 if (!(_Expr)) { \ 00100 fprintf(stderr, "fast_mutex::%s\n", _Msg); \ 00101 abort(); \ 00102 } 00103 # else 00104 00105 # define _FAST_MUTEX_ASSERT(_Expr, _Msg) \ 00106 ((void)0) 00107 # endif 00108 00109 # ifdef _PTHREADS 00110 # include <pthread.h> 00115 # define __VOLATILE volatile 00116 00120 class fast_mutex 00121 { 00122 pthread_mutex_t _M_mtx_impl; 00123 # if _FAST_MUTEX_CHECK_INITIALIZATION 00124 bool _M_initialized; 00125 # endif 00126 # ifdef _DEBUG 00127 bool _M_locked; 00128 # endif 00129 public: 00130 fast_mutex() 00131 # ifdef _DEBUG 00132 : _M_locked(false) 00133 # endif 00134 { 00135 ::pthread_mutex_init(&_M_mtx_impl, NULL); 00136 # if _FAST_MUTEX_CHECK_INITIALIZATION 00137 _M_initialized = true; 00138 # endif 00139 } 00140 ~fast_mutex() 00141 { 00142 _FAST_MUTEX_ASSERT(!_M_locked, "~fast_mutex(): still locked"); 00143 # if _FAST_MUTEX_CHECK_INITIALIZATION 00144 _M_initialized = false; 00145 # endif 00146 ::pthread_mutex_destroy(&_M_mtx_impl); 00147 } 00148 void lock() 00149 { 00150 # if _FAST_MUTEX_CHECK_INITIALIZATION 00151 if (!_M_initialized) 00152 return; 00153 # endif 00154 ::pthread_mutex_lock(&_M_mtx_impl); 00155 # ifdef _DEBUG 00156 // The following assertion should _always_ be true for a 00157 // real `fast' pthread_mutex. However, this assertion can 00158 // help sometimes, when people forget to use `-lpthread' and 00159 // glibc provides an empty implementation. Having this 00160 // assertion is also more consistent. 00161 _FAST_MUTEX_ASSERT(!_M_locked, "lock(): already locked"); 00162 _M_locked = true; 00163 # endif 00164 } 00165 void unlock() 00166 { 00167 # if _FAST_MUTEX_CHECK_INITIALIZATION 00168 if (!_M_initialized) 00169 return; 00170 # endif 00171 # ifdef _DEBUG 00172 _FAST_MUTEX_ASSERT(_M_locked, "unlock(): not locked"); 00173 _M_locked = false; 00174 # endif 00175 ::pthread_mutex_unlock(&_M_mtx_impl); 00176 } 00177 private: 00178 fast_mutex(const fast_mutex&); 00179 fast_mutex& operator=(const fast_mutex&); 00180 }; 00181 # endif // _PTHREADS 00182 00183 # ifdef _WIN32THREADS 00184 # include <windows.h> 00189 # define __VOLATILE volatile 00190 00194 class fast_mutex 00195 { 00196 CRITICAL_SECTION _M_mtx_impl; 00197 # if _FAST_MUTEX_CHECK_INITIALIZATION 00198 bool _M_initialized; 00199 # endif 00200 # ifdef _DEBUG 00201 bool _M_locked; 00202 # endif 00203 public: 00204 fast_mutex() 00205 # ifdef _DEBUG 00206 : _M_locked(false) 00207 # endif 00208 { 00209 ::InitializeCriticalSection(&_M_mtx_impl); 00210 # if _FAST_MUTEX_CHECK_INITIALIZATION 00211 _M_initialized = true; 00212 # endif 00213 } 00214 ~fast_mutex() 00215 { 00216 _FAST_MUTEX_ASSERT(!_M_locked, "~fast_mutex(): still locked"); 00217 # if _FAST_MUTEX_CHECK_INITIALIZATION 00218 _M_initialized = false; 00219 # endif 00220 ::DeleteCriticalSection(&_M_mtx_impl); 00221 } 00222 void lock() 00223 { 00224 # if _FAST_MUTEX_CHECK_INITIALIZATION 00225 if (!_M_initialized) 00226 return; 00227 # endif 00228 ::EnterCriticalSection(&_M_mtx_impl); 00229 # ifdef _DEBUG 00230 _FAST_MUTEX_ASSERT(!_M_locked, "lock(): already locked"); 00231 _M_locked = true; 00232 # endif 00233 } 00234 void unlock() 00235 { 00236 # if _FAST_MUTEX_CHECK_INITIALIZATION 00237 if (!_M_initialized) 00238 return; 00239 # endif 00240 # ifdef _DEBUG 00241 _FAST_MUTEX_ASSERT(_M_locked, "unlock(): not locked"); 00242 _M_locked = false; 00243 # endif 00244 ::LeaveCriticalSection(&_M_mtx_impl); 00245 } 00246 private: 00247 fast_mutex(const fast_mutex&); 00248 fast_mutex& operator=(const fast_mutex&); 00249 }; 00250 # endif // _WIN32THREADS 00251 00252 # ifdef _NOTHREADS 00253 00257 # define __VOLATILE 00258 00262 class fast_mutex 00263 { 00264 # ifdef _DEBUG 00265 bool _M_locked; 00266 # endif 00267 public: 00268 fast_mutex() 00269 # ifdef _DEBUG 00270 : _M_locked(false) 00271 # endif 00272 { 00273 } 00274 ~fast_mutex() 00275 { 00276 _FAST_MUTEX_ASSERT(!_M_locked, "~fast_mutex(): still locked"); 00277 } 00278 void lock() 00279 { 00280 # ifdef _DEBUG 00281 _FAST_MUTEX_ASSERT(!_M_locked, "lock(): already locked"); 00282 _M_locked = true; 00283 # endif 00284 } 00285 void unlock() 00286 { 00287 # ifdef _DEBUG 00288 _FAST_MUTEX_ASSERT(_M_locked, "unlock(): not locked"); 00289 _M_locked = false; 00290 # endif 00291 } 00292 private: 00293 fast_mutex(const fast_mutex&); 00294 fast_mutex& operator=(const fast_mutex&); 00295 }; 00296 # endif // _NOTHREADS 00297 00299 class fast_mutex_autolock 00300 { 00301 fast_mutex& _M_mtx; 00302 public: 00303 explicit fast_mutex_autolock(fast_mutex& __mtx) : _M_mtx(__mtx) 00304 { 00305 _M_mtx.lock(); 00306 } 00307 ~fast_mutex_autolock() 00308 { 00309 _M_mtx.unlock(); 00310 } 00311 private: 00312 fast_mutex_autolock(const fast_mutex_autolock&); 00313 fast_mutex_autolock& operator=(const fast_mutex_autolock&); 00314 }; 00315 00316 #endif // _FAST_MUTEX_H 00317 00318 00319 #endif 00320