SUMO - Simulation of Urban MObility
fast_mutex.h
Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines