// -*- 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 * * 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 object_level_lock.h * \ingroup QxMemLeak * * In essence Loki ObjectLevelLockable re-engineered to use a fast_mutex * class. Check also Andrei Alexandrescu's article * "Multithreading and the C++ Type System" for the ideas behind. * * \version 1.4, 2004/05/09 * \author Wu Yongwei * */ #ifndef QT_NO_DEBUG #ifndef _QX_MODE_RELEASE #if _QX_USE_MEM_LEAK_DETECTION #ifndef _OBJECT_LEVEL_LOCK_H #define _OBJECT_LEVEL_LOCK_H #ifdef _MSC_VER #pragma once #endif #include "fast_mutex.h" namespace qx { namespace memory { # ifdef _NOTHREADS /** * Helper class for object-level locking. This is the * single-threaded implementation. */ template class object_level_lock { public: /** Type that provides locking/unlocking semantics. */ class lock { #ifndef _QX_MODE_RELEASE #ifndef QT_NO_DEBUG const object_level_lock& _M_host; #endif // QT_NO_DEBUG #endif // _QX_MODE_RELEASE lock(const lock&); lock& operator=(const lock&); public: explicit lock(const object_level_lock& __host) #ifndef _QX_MODE_RELEASE #ifndef QT_NO_DEBUG : _M_host(__host) #endif // QT_NO_DEBUG #endif // _QX_MODE_RELEASE {} #ifndef _QX_MODE_RELEASE #ifndef QT_NO_DEBUG // The purpose of this method is allow one to write code // like "assert(guard.get_locked_object() == this)" to // ensure that the locked object is exactly the object being // accessed. const object_level_lock* get_locked_object() const { return &_M_host; } #endif // QT_NO_DEBUG #endif // _QX_MODE_RELEASE }; typedef _Host volatile_type; }; # else /** * Helper class for class-level locking. This is the multi-threaded * implementation. */ template class object_level_lock { mutable fast_mutex _M_mtx; public: class lock; friend class lock; /** Type that provides locking/unlocking semantics. */ class lock { const object_level_lock& _M_host; lock(const lock&); lock& operator=(const lock&); public: explicit lock(const object_level_lock& __host) : _M_host(__host) { _M_host._M_mtx.lock(); } ~lock() { _M_host._M_mtx.unlock(); } #ifndef _QX_MODE_RELEASE #ifndef QT_NO_DEBUG // The purpose of this method is allow one to write code // like "assert(guard.get_locked_object() == this)" to // ensure that the locked object is exactly the object being // accessed. const object_level_lock* get_locked_object() const { return &_M_host; } #endif // QT_NO_DEBUG #endif // _QX_MODE_RELEASE }; typedef volatile _Host volatile_type; }; # endif // _NOTHREADS } // namespace memory } // namespace qx #endif // _OBJECT_LEVEL_LOCK_H #endif // _QX_USE_MEM_LEAK_DETECTION #endif // _QX_MODE_RELEASE #endif // QT_NO_DEBUG