⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ncbithr.cpp

📁 ncbi源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * =========================================================================== * PRODUCTION $Log: ncbithr.cpp,v $ * PRODUCTION Revision 1000.1  2004/06/01 19:09:26  gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.30 * PRODUCTION * =========================================================================== *//*  $Id: ncbithr.cpp,v 1000.1 2004/06/01 19:09:26 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 -- classes, functions, and features. * *    TLS: *      CTlsBase         -- TLS implementation (base class for CTls<>) * *    THREAD: *      CThread          -- thread wrapper class * *    RW-LOCK: *      CInternalRWLock  -- platform-dependent RW-lock structure (fwd-decl) *      CRWLock          -- Read/Write lock related  data and methods * */#include <ncbi_pch.hpp>#include <corelib/ncbithr.hpp>#include <corelib/ncbimtx.hpp>#include <corelib/ncbi_safe_static.hpp>#include <corelib/ncbi_limits.h>#include <corelib/ncbi_system.hpp>#include <assert.h>#ifdef NCBI_POSIX_THREADS#  include <sys/time.h> // for gettimeofday()#endif#include "ncbidbg_p.hpp"BEGIN_NCBI_SCOPE///////////////////////////////////////////////////////////////////////////////  CTlsBase:://// Flag and function to report s_Tls_TlsSet destructionstatic bool s_TlsSetDestroyed = false;static void s_TlsSetCleanup(void* /* ptr */){    s_TlsSetDestroyed = true;}// Set of all TLS objects -- to prevent memory leaks due to// undestroyed TLS objects, and to avoid premature TLS destruction.typedef set< CRef<CTlsBase> > TTls_TlsSet;static CSafeStaticPtr<TTls_TlsSet> s_Tls_TlsSet(s_TlsSetCleanup);// Protects "s_Tls_TlsSet"struct S {    DECLARE_CLASS_STATIC_FAST_MUTEX(s_TlsMutex0);};DEFINE_CLASS_STATIC_FAST_MUTEX(S::s_TlsMutex0);#define s_TlsMutex S::s_TlsMutex0CTlsBase::CTlsBase(void){    DoDeleteThisObject();    // Create platform-dependent TLS key (index)#if defined(NCBI_WIN32_THREADS)    xncbi_Verify((m_Key = TlsAlloc()) != DWORD(-1));#elif defined(NCBI_POSIX_THREADS)    xncbi_Verify(pthread_key_create(&m_Key, 0) == 0);#else    m_Key = 0;#endif    m_Initialized = true;    // Add to the cleanup set if it still exists    if ( !s_TlsSetDestroyed ) {        CFastMutexGuard guard(s_TlsMutex);        s_Tls_TlsSet->insert(CRef<CTlsBase> (this));    }}CTlsBase::~CTlsBase(void){    x_Reset();    m_Initialized = false;    // Destroy system TLS key#if defined(NCBI_WIN32_THREADS)    if ( TlsFree(m_Key) ) {        m_Key = 0;        return;    }    assert(0);#elif defined(NCBI_POSIX_THREADS)    if (pthread_key_delete(m_Key) == 0) {        m_Key = 0;        return;    }    assert(0);#else    m_Key = 0;    return;#endif}void CTlsBase::x_Discard(void){    if ( s_TlsSetDestroyed ) {        return;  // Nothing to do - the TLS set has been destroyed    }    CFastMutexGuard guard(s_TlsMutex);    NON_CONST_ITERATE(TTls_TlsSet, it, *s_Tls_TlsSet) {        if (it->GetPointer() == this) {            s_Tls_TlsSet->erase(it);            break;        }    }}// Platform-specific TLS data storinginlinevoid s_TlsSetValue(TTlsKey& key, void* data, const char* err_message){#if defined(NCBI_WIN32_THREADS)    xncbi_Validate(TlsSetValue(key, data), err_message);#elif defined(NCBI_POSIX_THREADS)    xncbi_Validate(pthread_setspecific(key, data) == 0, err_message);#else    key = data;    assert(err_message);  // to get rid of the "unused variable" warning#endif}void CTlsBase::x_SetValue(void*        value,                          FCleanupBase cleanup,                          void*        cleanup_data){    if ( !m_Initialized ) {        return;    }    // Get previously stored data    STlsData* tls_data = static_cast<STlsData*> (x_GetTlsData());    // Create and initialize TLS structure, if it was not present    if ( !tls_data ) {        tls_data = new STlsData;        xncbi_Validate(tls_data != 0,                       "CTlsBase::x_SetValue() -- cannot allocate "                       "memory for TLS data");        tls_data->m_Value       = 0;        tls_data->m_CleanupFunc = 0;        tls_data->m_CleanupData = 0;    }    // Cleanup    if (tls_data->m_CleanupFunc  &&  tls_data->m_Value != value) {        tls_data->m_CleanupFunc(tls_data->m_Value, tls_data->m_CleanupData);    }    // Store the values    tls_data->m_Value       = value;    tls_data->m_CleanupFunc = cleanup;    tls_data->m_CleanupData = cleanup_data;    // Store the structure in the TLS    s_TlsSetValue(m_Key, tls_data,                  "CTlsBase::x_SetValue() -- error setting value");    // Add to the used TLS list to cleanup data in the thread Exit()    CThread::AddUsedTls(this);}void CTlsBase::x_Reset(void){    if ( !m_Initialized ) {        return;    }    // Get previously stored data    STlsData* tls_data = static_cast<STlsData*> (x_GetTlsData());    if ( !tls_data ) {        return;    }    // Cleanup & destroy    if ( tls_data->m_CleanupFunc ) {        tls_data->m_CleanupFunc(tls_data->m_Value, tls_data->m_CleanupData);    }    delete tls_data;    // Store NULL in the TLS    s_TlsSetValue(m_Key, 0,                  "CTlsBase::x_Reset() -- error cleaning-up TLS");}///////////////////////////////////////////////////////////////////////////////  CExitThreadException::////    Exception used to terminate threads safely, cleaning up//    all the resources allocated.//class CExitThreadException{public:    // Create new exception object, initialize counter.    CExitThreadException(void);    // Create a copy of exception object, increase counter.    CExitThreadException(const CExitThreadException& prev);    // Destroy the object, decrease counter. If the counter is    // zero outside of CThread::Wrapper(), rethrow exception.    ~CExitThreadException(void);    // Inform the object it has reached CThread::Wrapper().    void EnterWrapper(void)    {        *m_InWrapper = true;    }private:    int* m_RefCount;    bool* m_InWrapper;};CExitThreadException::CExitThreadException(void)    : m_RefCount(new int),      m_InWrapper(new bool){    *m_RefCount = 1;    *m_InWrapper = false;}CExitThreadException::CExitThreadException(const CExitThreadException& prev)    : m_RefCount(prev.m_RefCount),      m_InWrapper(prev.m_InWrapper){    (*m_RefCount)++;}CExitThreadException::~CExitThreadException(void){    if (--(*m_RefCount) > 0) {        // Not the last object - continue to handle exceptions        return;    }    bool tmp_in_wrapper = *m_InWrapper; // save the flag    delete m_RefCount;    delete m_InWrapper;    if ( !tmp_in_wrapper ) {        // Something is wrong - terminate the thread        assert(((void)("CThread::Exit() -- cannot exit thread"), 0));#if defined(NCBI_WIN32_THREADS)        ExitThread(0);#elif defined(NCBI_POSIX_THREADS)        pthread_exit(0);#endif    }}///////////////////////////////////////////////////////////////////////////////  CThread:://// Mutex to protect CThread members and to make sure that Wrapper() function// will not proceed until after the appropriate Run() is finished.DEFINE_STATIC_FAST_MUTEX(s_ThreadMutex);DEFINE_STATIC_FAST_MUTEX(s_TlsCleanupMutex);// Internal storage for thread objects and related variables/functionsCTls<CThread>* CThread::sm_ThreadsTls;void s_CleanupThreadsTls(void* /* ptr */){    CThread::sm_ThreadsTls = 0;  // Indicate that the TLS is destroyed}void CThread::CreateThreadsTls(void){    static CSafeStaticRef< CTls<CThread> >        s_ThreadsTlsRef(s_CleanupThreadsTls);    sm_ThreadsTls = &s_ThreadsTlsRef.Get();}TWrapperRes CThread::Wrapper(TWrapperArg arg){    // Get thread object and self ID    CThread* thread_obj = static_cast<CThread*>(arg);    // Set Toolkit thread ID. Otherwise no mutexes will work!    {{        CFastMutexGuard guard(s_ThreadMutex);        static int s_ThreadCount = 0;        s_ThreadCount++;        thread_obj->m_ID = s_ThreadCount;        xncbi_Validate(thread_obj->m_ID != 0,                       "CThread::Wrapper() -- error assigning thread ID");        GetThreadsTls().SetValue(thread_obj);    }}    // Run user-provided thread main function here    try {        thread_obj->m_ExitData = thread_obj->Main();    }    catch (CExitThreadException& e) {        e.EnterWrapper();    }    STD_CATCH_ALL("CThread::Wrapper: CThread::Main() failed");    // Call user-provided OnExit()    try {        thread_obj->OnExit();    }    STD_CATCH_ALL("CThread::Wrapper: CThread::OnExit() failed");    // Cleanup local storages used by this thread    {{        CFastMutexGuard tls_cleanup_guard(s_TlsCleanupMutex);        NON_CONST_ITERATE(TTlsSet, it, thread_obj->m_UsedTls) {            CRef<CTlsBase> tls = *it;            tls->x_Reset();        }    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -