123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367 |
- // -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
- // vim:tabstop=4:shiftwidth=4:expandtab:
- /*
- * Copyright (C) 2004-2008 Wu Yongwei <adah at users dot sourceforge dot net>
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any
- * damages arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute
- * it freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must
- * not claim that you wrote the original software. If you use this
- * software in a product, an acknowledgement in the product
- * documentation would be appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must
- * not be misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source
- * distribution.
- *
- * This file is part of Stones of Nvwa:
- * http://sourceforge.net/projects/nvwa
- *
- */
- /*!
- * \file fast_mutex.h
- * \ingroup QxMemLeak
- *
- * A fast mutex implementation for POSIX and Win32.
- *
- * \version 1.18, 2005/05/06
- * \author Wu Yongwei
- *
- */
- #ifndef QT_NO_DEBUG
- #ifndef _QX_MODE_RELEASE
- #if _QX_USE_MEM_LEAK_DETECTION
- #ifndef _FAST_MUTEX_H
- #define _FAST_MUTEX_H
- #ifdef _MSC_VER
- #pragma once
- #endif
- # if !defined(_NOTHREADS)
- # if !defined(_WIN32THREADS) && \
- (defined(_WIN32) && defined(_MT))
- // Automatically use _WIN32THREADS when specifying -MT/-MD in MSVC,
- // or -mthreads in MinGW GCC.
- # define _WIN32THREADS
- # elif !defined(_PTHREADS) && \
- defined(_REENTRANT)
- // Automatically use _PTHREADS when specifying -pthread in GCC.
- // N.B. I do not detect on _PTHREAD_H since libstdc++-v3 under
- // Linux will silently include <pthread.h> anyway.
- # define _PTHREADS
- # endif
- # endif
- # if !defined(_PTHREADS) && !defined(_WIN32THREADS) && !defined(_NOTHREADS)
- # define _NOTHREADS
- # endif
- # if defined(_NOTHREADS)
- # if defined(_PTHREADS) || defined(_WIN32THREADS)
- # undef _NOTHREADS
- # error "Cannot define multi-threaded mode with -D_NOTHREADS"
- # if defined(__MINGW32__) && defined(_WIN32THREADS) && !defined(_MT)
- # error "Be sure to specify -mthreads with -D_WIN32THREADS"
- # endif
- # endif
- # endif
- # ifndef _FAST_MUTEX_CHECK_INITIALIZATION
- /**
- * Macro to control whether to check for initialization status for each
- * lock/unlock operation. Defining it to a non-zero value will enable
- * the check, so that the construction/destruction of a static object
- * using a static fast_mutex not yet constructed or already destroyed
- * will work (with lock/unlock operations ignored). Defining it to zero
- * will disable to check.
- */
- # define _FAST_MUTEX_CHECK_INITIALIZATION 1
- # endif
- # if defined(_PTHREADS) && defined(_WIN32THREADS)
- // Some C++ libraries have _PTHREADS defined even on Win32 platforms.
- // Thus this hack.
- # undef _PTHREADS
- # endif
- #ifndef _QX_MODE_RELEASE
- #ifndef QT_NO_DEBUG
- # include <stdio.h>
- # include <stdlib.h>
- /** Macro for fast_mutex assertions. Real version (for debug mode). */
- # define _FAST_MUTEX_ASSERT(_Expr, _Msg) \
- if (!(_Expr)) { \
- fprintf(stderr, "fast_mutex::%s\n", _Msg); \
- abort(); \
- }
- #else
- /** Macro for fast_mutex assertions. Fake version (for release mode). */
- # define _FAST_MUTEX_ASSERT(_Expr, _Msg) \
- ((void)0)
- #endif // QT_NO_DEBUG
- #endif // _QX_MODE_RELEASE
- # ifdef _PTHREADS
- # include <pthread.h>
- /**
- * Macro alias to `volatile' semantics. Here it is truly volatile since
- * it is in a multi-threaded (POSIX threads) environment.
- */
- # define __VOLATILE volatile
- /**
- * Class for non-reentrant fast mutexes. This is the implementation
- * for POSIX threads.
- */
- namespace qx {
- namespace memory {
- class fast_mutex
- {
- pthread_mutex_t _M_mtx_impl;
- # if _FAST_MUTEX_CHECK_INITIALIZATION
- bool _M_initialized;
- # endif
- #ifndef _QX_MODE_RELEASE
- #ifndef QT_NO_DEBUG
- bool _M_locked;
- #endif // QT_NO_DEBUG
- #endif // _QX_MODE_RELEASE
- public:
- fast_mutex()
- #ifndef _QX_MODE_RELEASE
- #ifndef QT_NO_DEBUG
- : _M_locked(false)
- #endif // QT_NO_DEBUG
- #endif // _QX_MODE_RELEASE
- {
- ::pthread_mutex_init(&_M_mtx_impl, NULL);
- # if _FAST_MUTEX_CHECK_INITIALIZATION
- _M_initialized = true;
- # endif
- }
- ~fast_mutex()
- {
- _FAST_MUTEX_ASSERT(!_M_locked, "~fast_mutex(): still locked");
- # if _FAST_MUTEX_CHECK_INITIALIZATION
- _M_initialized = false;
- # endif
- ::pthread_mutex_destroy(&_M_mtx_impl);
- }
- void lock()
- {
- # if _FAST_MUTEX_CHECK_INITIALIZATION
- if (!_M_initialized)
- return;
- # endif
- ::pthread_mutex_lock(&_M_mtx_impl);
- #ifndef _QX_MODE_RELEASE
- #ifndef QT_NO_DEBUG
- // The following assertion should _always_ be true for a
- // real `fast' pthread_mutex. However, this assertion can
- // help sometimes, when people forget to use `-lpthread' and
- // glibc provides an empty implementation. Having this
- // assertion is also more consistent.
- _FAST_MUTEX_ASSERT(!_M_locked, "lock(): already locked");
- _M_locked = true;
- #endif // QT_NO_DEBUG
- #endif // _QX_MODE_RELEASE
- }
- void unlock()
- {
- # if _FAST_MUTEX_CHECK_INITIALIZATION
- if (!_M_initialized)
- return;
- # endif
- #ifndef _QX_MODE_RELEASE
- #ifndef QT_NO_DEBUG
- _FAST_MUTEX_ASSERT(_M_locked, "unlock(): not locked");
- _M_locked = false;
- #endif // QT_NO_DEBUG
- #endif // _QX_MODE_RELEASE
- ::pthread_mutex_unlock(&_M_mtx_impl);
- }
- private:
- fast_mutex(const fast_mutex&);
- fast_mutex& operator=(const fast_mutex&);
- };
- } // namespace memory
- } // namespace qx
- # endif // _PTHREADS
- # ifdef _WIN32THREADS
- # include <windows.h>
- /**
- * Macro alias to `volatile' semantics. Here it is truly volatile since
- * it is in a multi-threaded (Win32 threads) environment.
- */
- # define __VOLATILE volatile
- /**
- * Class for non-reentrant fast mutexes. This is the implementation
- * for Win32 threads.
- */
- namespace qx {
- namespace memory {
- class fast_mutex
- {
- CRITICAL_SECTION _M_mtx_impl;
- # if _FAST_MUTEX_CHECK_INITIALIZATION
- bool _M_initialized;
- # endif
- #ifndef _QX_MODE_RELEASE
- #ifndef QT_NO_DEBUG
- bool _M_locked;
- #endif // QT_NO_DEBUG
- #endif // _QX_MODE_RELEASE
- public:
- fast_mutex()
- #ifndef _QX_MODE_RELEASE
- #ifndef QT_NO_DEBUG
- : _M_locked(false)
- #endif // QT_NO_DEBUG
- #endif // _QX_MODE_RELEASE
- {
- ::InitializeCriticalSection(&_M_mtx_impl);
- # if _FAST_MUTEX_CHECK_INITIALIZATION
- _M_initialized = true;
- # endif
- }
- ~fast_mutex()
- {
- _FAST_MUTEX_ASSERT(!_M_locked, "~fast_mutex(): still locked");
- # if _FAST_MUTEX_CHECK_INITIALIZATION
- _M_initialized = false;
- # endif
- ::DeleteCriticalSection(&_M_mtx_impl);
- }
- void lock()
- {
- # if _FAST_MUTEX_CHECK_INITIALIZATION
- if (!_M_initialized)
- return;
- # endif
- ::EnterCriticalSection(&_M_mtx_impl);
- #ifndef _QX_MODE_RELEASE
- #ifndef QT_NO_DEBUG
- _FAST_MUTEX_ASSERT(!_M_locked, "lock(): already locked");
- _M_locked = true;
- #endif // QT_NO_DEBUG
- #endif // _QX_MODE_RELEASE
- }
- void unlock()
- {
- # if _FAST_MUTEX_CHECK_INITIALIZATION
- if (!_M_initialized)
- return;
- # endif
- #ifndef _QX_MODE_RELEASE
- #ifndef QT_NO_DEBUG
- _FAST_MUTEX_ASSERT(_M_locked, "unlock(): not locked");
- _M_locked = false;
- #endif // QT_NO_DEBUG
- #endif // _QX_MODE_RELEASE
- ::LeaveCriticalSection(&_M_mtx_impl);
- }
- private:
- fast_mutex(const fast_mutex&);
- fast_mutex& operator=(const fast_mutex&);
- };
- } // namespace memory
- } // namespace qx
- # endif // _WIN32THREADS
- # ifdef _NOTHREADS
- /**
- * Macro alias to `volatile' semantics. Here it is not truly volatile
- * since it is in a single-threaded environment.
- */
- # define __VOLATILE
- /**
- * Class for non-reentrant fast mutexes. This is the null
- * implementation for single-threaded environments.
- */
- namespace qx {
- namespace memory {
- class fast_mutex
- {
- #ifndef _QX_MODE_RELEASE
- #ifndef QT_NO_DEBUG
- bool _M_locked;
- #endif // QT_NO_DEBUG
- #endif // _QX_MODE_RELEASE
- public:
- fast_mutex()
- #ifndef _QX_MODE_RELEASE
- #ifndef QT_NO_DEBUG
- : _M_locked(false)
- #endif // QT_NO_DEBUG
- #endif // _QX_MODE_RELEASE
- {
- }
- ~fast_mutex()
- {
- _FAST_MUTEX_ASSERT(!_M_locked, "~fast_mutex(): still locked");
- }
- void lock()
- {
- #ifndef _QX_MODE_RELEASE
- #ifndef QT_NO_DEBUG
- _FAST_MUTEX_ASSERT(!_M_locked, "lock(): already locked");
- _M_locked = true;
- #endif // QT_NO_DEBUG
- #endif // _QX_MODE_RELEASE
- }
- void unlock()
- {
- #ifndef _QX_MODE_RELEASE
- #ifndef QT_NO_DEBUG
- _FAST_MUTEX_ASSERT(_M_locked, "unlock(): not locked");
- _M_locked = false;
- #endif // QT_NO_DEBUG
- #endif // _QX_MODE_RELEASE
- }
- private:
- fast_mutex(const fast_mutex&);
- fast_mutex& operator=(const fast_mutex&);
- };
- } // namespace memory
- } // namespace qx
- # endif // _NOTHREADS
- namespace qx {
- namespace memory {
- /** An acquistion-on-initialization lock class based on fast_mutex. */
- class QX_DLL_EXPORT fast_mutex_autolock
- {
- fast_mutex& _M_mtx;
- public:
- explicit fast_mutex_autolock(fast_mutex& __mtx) : _M_mtx(__mtx)
- {
- _M_mtx.lock();
- }
- ~fast_mutex_autolock()
- {
- _M_mtx.unlock();
- }
- private:
- fast_mutex_autolock(const fast_mutex_autolock&);
- fast_mutex_autolock& operator=(const fast_mutex_autolock&);
- };
- } // namespace memory
- } // namespace qx
- #endif // _FAST_MUTEX_H
- #endif // _QX_USE_MEM_LEAK_DETECTION
- #endif // _QX_MODE_RELEASE
- #endif // QT_NO_DEBUG
|