QxOrm  1.5.0
C++ Object Relational Mapping library
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-2008 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 
00040 #ifndef QT_NO_DEBUG
00041 #ifndef _QX_MODE_RELEASE
00042 #if _QX_USE_MEM_LEAK_DETECTION
00043 
00044 #ifndef _FAST_MUTEX_H
00045 #define _FAST_MUTEX_H
00046 
00047 #ifdef _MSC_VER
00048 #pragma once
00049 #endif
00050 
00051 # if !defined(_NOTHREADS)
00052 #   if !defined(_WIN32THREADS) && \
00053             (defined(_WIN32) && defined(_MT))
00054 //      Automatically use _WIN32THREADS when specifying -MT/-MD in MSVC,
00055 //      or -mthreads in MinGW GCC.
00056 #       define _WIN32THREADS
00057 #   elif !defined(_PTHREADS) && \
00058             defined(_REENTRANT)
00059 //      Automatically use _PTHREADS when specifying -pthread in GCC.
00060 //      N.B. I do not detect on _PTHREAD_H since libstdc++-v3 under
00061 //      Linux will silently include <pthread.h> anyway.
00062 #       define _PTHREADS
00063 #   endif
00064 # endif
00065 
00066 # if !defined(_PTHREADS) && !defined(_WIN32THREADS) && !defined(_NOTHREADS)
00067 #   define _NOTHREADS
00068 # endif
00069 
00070 # if defined(_NOTHREADS)
00071 #   if defined(_PTHREADS) || defined(_WIN32THREADS)
00072 #       undef _NOTHREADS
00073 #       error "Cannot define multi-threaded mode with -D_NOTHREADS"
00074 #       if defined(__MINGW32__) && defined(_WIN32THREADS) && !defined(_MT)
00075 #           error "Be sure to specify -mthreads with -D_WIN32THREADS"
00076 #       endif
00077 #   endif
00078 # endif
00079 
00080 # ifndef _FAST_MUTEX_CHECK_INITIALIZATION
00081 
00089 #   define _FAST_MUTEX_CHECK_INITIALIZATION 1
00090 # endif
00091 
00092 # if defined(_PTHREADS) && defined(_WIN32THREADS)
00093 //  Some C++ libraries have _PTHREADS defined even on Win32 platforms.
00094 //  Thus this hack.
00095 #   undef _PTHREADS
00096 # endif
00097 
00098 #ifndef _QX_MODE_RELEASE
00099 #ifndef QT_NO_DEBUG
00100 #   include <stdio.h>
00101 #   include <stdlib.h>
00103 #   define _FAST_MUTEX_ASSERT(_Expr, _Msg) \
00104         if (!(_Expr)) { \
00105             fprintf(stderr, "fast_mutex::%s\n", _Msg); \
00106             abort(); \
00107         }
00108 #else
00109 
00110 #   define _FAST_MUTEX_ASSERT(_Expr, _Msg) \
00111         ((void)0)
00112 #endif // QT_NO_DEBUG
00113 #endif // _QX_MODE_RELEASE
00114 
00115 # ifdef _PTHREADS
00116 #   include <pthread.h>
00121 #   define __VOLATILE volatile
00122 
00126     namespace qx {
00127     namespace memory {
00128     class fast_mutex
00129     {
00130         pthread_mutex_t _M_mtx_impl;
00131 #       if _FAST_MUTEX_CHECK_INITIALIZATION
00132         bool _M_initialized;
00133 #       endif
00134 #ifndef _QX_MODE_RELEASE
00135 #ifndef QT_NO_DEBUG
00136         bool _M_locked;
00137 #endif // QT_NO_DEBUG
00138 #endif // _QX_MODE_RELEASE
00139     public:
00140         fast_mutex()
00141 #ifndef _QX_MODE_RELEASE
00142 #ifndef QT_NO_DEBUG
00143             : _M_locked(false)
00144 #endif // QT_NO_DEBUG
00145 #endif // _QX_MODE_RELEASE
00146         {
00147             ::pthread_mutex_init(&_M_mtx_impl, NULL);
00148 #       if _FAST_MUTEX_CHECK_INITIALIZATION
00149             _M_initialized = true;
00150 #       endif
00151         }
00152         ~fast_mutex()
00153         {
00154             _FAST_MUTEX_ASSERT(!_M_locked, "~fast_mutex(): still locked");
00155 #       if _FAST_MUTEX_CHECK_INITIALIZATION
00156             _M_initialized = false;
00157 #       endif
00158             ::pthread_mutex_destroy(&_M_mtx_impl);
00159         }
00160         void lock()
00161         {
00162 #       if _FAST_MUTEX_CHECK_INITIALIZATION
00163             if (!_M_initialized)
00164                 return;
00165 #       endif
00166             ::pthread_mutex_lock(&_M_mtx_impl);
00167 #ifndef _QX_MODE_RELEASE
00168 #ifndef QT_NO_DEBUG
00169             // The following assertion should _always_ be true for a
00170             // real `fast' pthread_mutex.  However, this assertion can
00171             // help sometimes, when people forget to use `-lpthread' and
00172             // glibc provides an empty implementation.  Having this
00173             // assertion is also more consistent.
00174             _FAST_MUTEX_ASSERT(!_M_locked, "lock(): already locked");
00175             _M_locked = true;
00176 #endif // QT_NO_DEBUG
00177 #endif // _QX_MODE_RELEASE
00178         }
00179         void unlock()
00180         {
00181 #       if _FAST_MUTEX_CHECK_INITIALIZATION
00182             if (!_M_initialized)
00183                 return;
00184 #       endif
00185 #ifndef _QX_MODE_RELEASE
00186 #ifndef QT_NO_DEBUG
00187             _FAST_MUTEX_ASSERT(_M_locked, "unlock(): not locked");
00188             _M_locked = false;
00189 #endif // QT_NO_DEBUG
00190 #endif // _QX_MODE_RELEASE
00191             ::pthread_mutex_unlock(&_M_mtx_impl);
00192         }
00193     private:
00194         fast_mutex(const fast_mutex&);
00195         fast_mutex& operator=(const fast_mutex&);
00196     };
00197     } // namespace memory
00198     } // namespace qx
00199 # endif // _PTHREADS
00200 
00201 # ifdef _WIN32THREADS
00202 #   include <windows.h>
00207 #   define __VOLATILE volatile
00208 
00212     namespace qx {
00213     namespace memory {
00214     class fast_mutex
00215     {
00216         CRITICAL_SECTION _M_mtx_impl;
00217 #       if _FAST_MUTEX_CHECK_INITIALIZATION
00218         bool _M_initialized;
00219 #       endif
00220 #ifndef _QX_MODE_RELEASE
00221 #ifndef QT_NO_DEBUG
00222         bool _M_locked;
00223 #endif // QT_NO_DEBUG
00224 #endif // _QX_MODE_RELEASE
00225     public:
00226         fast_mutex()
00227 #ifndef _QX_MODE_RELEASE
00228 #ifndef QT_NO_DEBUG
00229             : _M_locked(false)
00230 #endif // QT_NO_DEBUG
00231 #endif // _QX_MODE_RELEASE
00232         {
00233             ::InitializeCriticalSection(&_M_mtx_impl);
00234 #       if _FAST_MUTEX_CHECK_INITIALIZATION
00235             _M_initialized = true;
00236 #       endif
00237         }
00238         ~fast_mutex()
00239         {
00240             _FAST_MUTEX_ASSERT(!_M_locked, "~fast_mutex(): still locked");
00241 #       if _FAST_MUTEX_CHECK_INITIALIZATION
00242             _M_initialized = false;
00243 #       endif
00244             ::DeleteCriticalSection(&_M_mtx_impl);
00245         }
00246         void lock()
00247         {
00248 #       if _FAST_MUTEX_CHECK_INITIALIZATION
00249             if (!_M_initialized)
00250                 return;
00251 #       endif
00252             ::EnterCriticalSection(&_M_mtx_impl);
00253 #ifndef _QX_MODE_RELEASE
00254 #ifndef QT_NO_DEBUG
00255             _FAST_MUTEX_ASSERT(!_M_locked, "lock(): already locked");
00256             _M_locked = true;
00257 #endif // QT_NO_DEBUG
00258 #endif // _QX_MODE_RELEASE
00259         }
00260         void unlock()
00261         {
00262 #       if _FAST_MUTEX_CHECK_INITIALIZATION
00263             if (!_M_initialized)
00264                 return;
00265 #       endif
00266 #ifndef _QX_MODE_RELEASE
00267 #ifndef QT_NO_DEBUG
00268             _FAST_MUTEX_ASSERT(_M_locked, "unlock(): not locked");
00269             _M_locked = false;
00270 #endif // QT_NO_DEBUG
00271 #endif // _QX_MODE_RELEASE
00272             ::LeaveCriticalSection(&_M_mtx_impl);
00273         }
00274     private:
00275         fast_mutex(const fast_mutex&);
00276         fast_mutex& operator=(const fast_mutex&);
00277     };
00278     } // namespace memory
00279     } // namespace qx
00280 # endif // _WIN32THREADS
00281 
00282 # ifdef _NOTHREADS
00283 
00287 #   define __VOLATILE
00288 
00292     namespace qx {
00293     namespace memory {
00294     class fast_mutex
00295     {
00296 #ifndef _QX_MODE_RELEASE
00297 #ifndef QT_NO_DEBUG
00298         bool _M_locked;
00299 #endif // QT_NO_DEBUG
00300 #endif // _QX_MODE_RELEASE
00301     public:
00302         fast_mutex()
00303 #ifndef _QX_MODE_RELEASE
00304 #ifndef QT_NO_DEBUG
00305             : _M_locked(false)
00306 #endif // QT_NO_DEBUG
00307 #endif // _QX_MODE_RELEASE
00308         {
00309         }
00310         ~fast_mutex()
00311         {
00312             _FAST_MUTEX_ASSERT(!_M_locked, "~fast_mutex(): still locked");
00313         }
00314         void lock()
00315         {
00316 #ifndef _QX_MODE_RELEASE
00317 #ifndef QT_NO_DEBUG
00318             _FAST_MUTEX_ASSERT(!_M_locked, "lock(): already locked");
00319             _M_locked = true;
00320 #endif // QT_NO_DEBUG
00321 #endif // _QX_MODE_RELEASE
00322         }
00323         void unlock()
00324         {
00325 #ifndef _QX_MODE_RELEASE
00326 #ifndef QT_NO_DEBUG
00327             _FAST_MUTEX_ASSERT(_M_locked, "unlock(): not locked");
00328             _M_locked = false;
00329 #endif // QT_NO_DEBUG
00330 #endif // _QX_MODE_RELEASE
00331         }
00332     private:
00333         fast_mutex(const fast_mutex&);
00334         fast_mutex& operator=(const fast_mutex&);
00335     };
00336     } // namespace memory
00337     } // namespace qx
00338 # endif // _NOTHREADS
00339 
00340 namespace qx {
00341 namespace memory {
00342 
00344 class QX_DLL_EXPORT fast_mutex_autolock
00345 {
00346     fast_mutex& _M_mtx;
00347 public:
00348     explicit fast_mutex_autolock(fast_mutex& __mtx) : _M_mtx(__mtx)
00349     {
00350         _M_mtx.lock();
00351     }
00352     ~fast_mutex_autolock()
00353     {
00354         _M_mtx.unlock();
00355     }
00356 private:
00357     fast_mutex_autolock(const fast_mutex_autolock&);
00358     fast_mutex_autolock& operator=(const fast_mutex_autolock&);
00359 };
00360 
00361 } // namespace memory
00362 } // namespace qx
00363 
00364 #endif // _FAST_MUTEX_H
00365 #endif // _QX_USE_MEM_LEAK_DETECTION
00366 #endif // _QX_MODE_RELEASE
00367 #endif // QT_NO_DEBUG