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

Generated on Mon Dec 31 15:07:24 2007 for Nvwa by  doxygen 1.5.1