📄 ncbimtx.cpp
字号:
/* * =========================================================================== * PRODUCTION $Log: ncbimtx.cpp,v $ * PRODUCTION Revision 1000.2 2004/06/03 19:28:17 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.17 * PRODUCTION * =========================================================================== *//* $Id: ncbimtx.cpp,v 1000.2 2004/06/03 19:28:17 gouriano Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Author: Denis Vakatov, Aleksey Grichenko * * File Description: * Multi-threading -- fast mutexes * * MUTEX: * CInternalMutex -- platform-dependent mutex functionality * */#include <ncbi_pch.hpp>#include <corelib/ncbimtx.hpp>#include <corelib/ncbi_limits.h>#include "ncbidbg_p.hpp"#include <stdio.h>#include <algorithm>#ifdef NCBI_POSIX_THREADS# include <sys/time.h> // for gettimeofday()#endif#define STACK_THRESHOLD (1024)BEGIN_NCBI_SCOPE/////////////////////////////////////////////////////////////////////////////// CInternalMutex:://void SSystemFastMutex::InitializeHandle(void){ // Create platform-dependent mutex handle#if defined(NCBI_WIN32_THREADS) xncbi_Validate((m_Handle = CreateMutex(NULL, FALSE, NULL)) != NULL, "Mutex creation failed");#elif defined(NCBI_POSIX_THREADS) xncbi_Validate(pthread_mutex_init(&m_Handle, 0) == 0, "Mutex creation failed");#endif}void SSystemFastMutex::DestroyHandle(void){ // Destroy system mutex handle#if defined(NCBI_WIN32_THREADS) xncbi_Verify(CloseHandle(m_Handle) != 0);#elif defined(NCBI_POSIX_THREADS) xncbi_Verify(pthread_mutex_destroy(&m_Handle) == 0);#endif}void SSystemFastMutex::InitializeStatic(void){#if !defined(NCBI_NO_THREADS) switch ( m_Magic ) { case eMutexUninitialized: // ok break; case eMutexInitialized: xncbi_Validate(0, "Double initialization of mutex"); break; default: xncbi_Validate(0, "SSystemFastMutex::m_Magic contains invalid value"); break; } InitializeHandle();#endif m_Magic = eMutexInitialized;}void SSystemFastMutex::InitializeDynamic(void){#if !defined(NCBI_NO_THREADS) InitializeHandle();#endif m_Magic = eMutexInitialized;}void SSystemFastMutex::Destroy(void){#if !defined(NCBI_NO_THREADS) xncbi_Validate(IsInitialized(), "Destruction of uninitialized mutex");#endif m_Magic = eMutexUninitialized; DestroyHandle();}void SSystemFastMutex::ThrowUninitialized(void){ NCBI_THROW(CMutexException, eUninitialized, "Mutex uninitialized");}void SSystemFastMutex::ThrowLockFailed(void){ NCBI_THROW(CMutexException, eLock, "Mutex lock failed");}void SSystemFastMutex::ThrowUnlockFailed(void){ NCBI_THROW(CMutexException, eUnlock, "Mutex unlock failed");}void SSystemFastMutex::ThrowTryLockFailed(void){ NCBI_THROW(CMutexException, eTryLock, "Mutex check (TryLock) failed");}void SSystemMutex::Destroy(void){ xncbi_Validate(m_Count == 0, "Destruction of locked mutex"); m_Mutex.Destroy();}#if !defined(NCBI_NO_THREADS)void SSystemMutex::Lock(void){ m_Mutex.CheckInitialized(); CThreadSystemID owner = CThreadSystemID::GetCurrent(); if ( m_Count > 0 && m_Owner.Is(owner) ) { // Don't lock twice, just increase the counter m_Count++; return; } // Lock the mutex and remember the owner m_Mutex.Lock(); assert(m_Count == 0); m_Owner.Set(owner); m_Count = 1;}bool SSystemMutex::TryLock(void){ m_Mutex.CheckInitialized(); CThreadSystemID owner = CThreadSystemID::GetCurrent(); if ( m_Count > 0 && m_Owner.Is(owner) ) { // Don't lock twice, just increase the counter m_Count++; return true; } // If TryLock is successful, remember the owner if ( m_Mutex.TryLock() ) { assert(m_Count == 0); m_Owner.Set(owner); m_Count = 1; return true; } // Cannot lock right now return false;}void SSystemMutex::Unlock(void){ m_Mutex.CheckInitialized(); // No unlocks by threads other than owner. // This includes no unlocks of unlocked mutex. CThreadSystemID owner = CThreadSystemID::GetCurrent(); if ( m_Count == 0 || m_Owner.IsNot(owner) ) { ThrowNotOwned(); } // No real unlocks if counter > 1, just decrease it if (--m_Count > 0) { return; } assert(m_Count == 0); // This was the last lock - clear the owner and unlock the mutex m_Mutex.Unlock();}#endifvoid SSystemMutex::ThrowNotOwned(void){ NCBI_THROW(CMutexException, eOwner, "Mutex is not owned by current thread");}#if defined(NEED_AUTO_INITIALIZE_MUTEX)const char* kInitMutexName = "NCBI_CAutoInitializeStaticMutex";void CAutoInitializeStaticFastMutex::Initialize(void){ if ( m_Mutex.IsInitialized() ) { return; } TSystemMutex init_mutex = CreateMutex(NULL, FALSE, kInitMutexName); assert(init_mutex); assert(WaitForSingleObject(init_mutex, INFINITE) == WAIT_OBJECT_0); if ( !m_Mutex.IsInitialized() ) { m_Mutex.InitializeStatic(); } assert(ReleaseMutex(init_mutex)); assert(m_Mutex.IsInitialized()); CloseHandle(init_mutex);}void CAutoInitializeStaticMutex::Initialize(void){ if ( m_Mutex.IsInitialized() ) { return; } TSystemMutex init_mutex = CreateMutex(NULL, FALSE, kInitMutexName); assert(init_mutex); assert(WaitForSingleObject(init_mutex, INFINITE) == WAIT_OBJECT_0); if ( !m_Mutex.IsInitialized() ) { m_Mutex.InitializeStatic(); } assert(ReleaseMutex(init_mutex)); assert(m_Mutex.IsInitialized()); CloseHandle(init_mutex);}#endifconst char* CMutexException::GetErrCodeString(void) const{ switch (GetErrCode()) { case eLock: return "eLock"; case eUnlock: return "eUnlock"; case eTryLock: return "eTryLock"; case eOwner: return "eOwner"; case eUninitialized: return "eUninitialized"; default: return CException::GetErrCodeString(); }}/////////////////////////////////////////////////////////////////////////////// CInternalRWLock:://#if defined(NCBI_WIN32_THREADS)class CWindowsHandle{public: CWindowsHandle(HANDLE h = NULL) : m_Handle(h) {} CWindowsHandle(HANDLE h, const char* errorMessage) : m_Handle(h) { xncbi_Validate(h != NULL, errorMessage); } ~CWindowsHandle(void) { Close(); } void Close(void) { if ( m_Handle != NULL ) { CloseHandle(m_Handle); m_Handle = NULL; } } void Set(HANDLE h) { Close(); m_Handle = h; } void Set(HANDLE h, const char* errorMessage) { xncbi_Validate(h != NULL, errorMessage); Set(h); } operator HANDLE(void) const { return m_Handle; }protected: HANDLE m_Handle;private: CWindowsHandle(const CWindowsHandle& h); CWindowsHandle& operator=(const CWindowsHandle& h);};class CWindowsSemaphore : public CWindowsHandle{public: CWindowsSemaphore(LONG initialCount = 0, LONG maximumCount = INFINITE) : CWindowsHandle(CreateSemaphore(NULL, initialCount, maximumCount, NULL), "CreateSemaphore() failed") { } LONG Release(LONG add = 1) { LONG prev_sema; xncbi_Validate(ReleaseSemaphore(*this, add, &prev_sema), "CWindowsSemaphore::Release() failed"); return prev_sema; }};#endif#if defined(NCBI_POSIX_THREADS)class CPthreadCond{public: CPthreadCond(void) : m_Initialized(pthread_cond_init(&m_Handle, 0) != 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -