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

📄 ncbi_safe_static.hpp

📁 ncbi源码
💻 HPP
字号:
/* * =========================================================================== * PRODUCTION $Log: ncbi_safe_static.hpp,v $ * PRODUCTION Revision 1000.1  2004/06/01 19:07:46  gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.12 * PRODUCTION * =========================================================================== */#ifndef NCBI_SAFE_STATIC__HPP#define NCBI_SAFE_STATIC__HPP/*  $Id: ncbi_safe_static.hpp,v 1000.1 2004/06/01 19:07:46 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:   Aleksey Grichenko * * File Description: *   Static variables safety - create on demand, destroy on termination * *   CSafeStaticPtr_Base::   --  base class for CSafePtr<> and CSafeRef<> *   CSafeStaticPtr<>::      -- create variable on demand, destroy on program *                              termination (see NCBIOBJ for CSafeRef<> class) *   CSafeStaticRef<>::      -- create variable on demand, destroy on program *                              termination (see NCBIOBJ for CSafeRef<> class) *   CSafeStaticGuard::      -- guarantee for CSafePtr<> and CSafeRef<> *                              destruction and cleanup * */#include <corelib/ncbistl.hpp>#include <corelib/ncbiobj.hpp>#include <corelib/ncbithr.hpp>#include <stack>BEGIN_NCBI_SCOPE/////////////////////////////////////////////////////////////////////////////////  CSafeStaticPtr_Base::////    Base class for CSafeStaticPtr<> and CSafeStaticRef<> templates.//// Base class for CSafeStaticPtr<> and CSafeStaticRef<> templatesclass NCBI_XNCBI_EXPORT CSafeStaticPtr_Base{public:    // User cleanup function type    typedef void (*FSelfCleanup)(void** ptr);    typedef void (*FUserCleanup)(void*  ptr);    // Set user-provided cleanup function to be executed on destruction    CSafeStaticPtr_Base(FSelfCleanup self_cleanup,                        FUserCleanup user_cleanup = 0)        : m_SelfCleanup(self_cleanup),          m_UserCleanup(user_cleanup)    {}protected:    void* m_Ptr;          // Pointer to the data    // Prepare to the object initialization: check current thread, lock    // the mutex and store its state to "mutex_locked", return "true"    // if the object must be created or "false" if already created.    bool Init_Lock(bool* mutex_locked);    // Finalize object initialization: release the mutex if "mutex_locked"    void Init_Unlock(bool mutex_locked);private:    FSelfCleanup m_SelfCleanup;  // Derived class' cleanup function    FUserCleanup m_UserCleanup;  // User-provided  cleanup function    // To be called by CSafeStaticGuard on the program termination    friend class CSafeStaticGuard;    void Cleanup(void)    {        if ( m_UserCleanup )  m_UserCleanup(m_Ptr);        if ( m_SelfCleanup )  m_SelfCleanup(&m_Ptr);    }};/////////////////////////////////////////////////////////////////////////////////  CSafeStaticPtr<>::////    For simple on-demand variables.//    Create the variable of type "T" on demand,//    destroy it on the program termination.//template <class T>class CSafeStaticPtr : public CSafeStaticPtr_Base{public:    // Set the cleanup function to be called on variable destruction    CSafeStaticPtr(FUserCleanup user_cleanup = 0)        : CSafeStaticPtr_Base(SelfCleanup, user_cleanup)    {}    // Create the variable if not created yet, return the reference    T& Get(void)    {        if ( !m_Ptr ) {            Init();        }        return *static_cast<T*> (m_Ptr);    }    T* operator -> (void) { return &Get(); }    T& operator *  (void) { return  Get(); }    // Initialize with an existing object. The object MUST be    // allocated with "new T" -- it will be destroyed with    // "delete object" in the end. Set() works only for    // not yet initialized safe-static variables.    void Set(T* object);private:    // Initialize the object    void Init(void);    // "virtual" cleanup function    static void SelfCleanup(void** ptr)    {        T* tmp = static_cast<T*> (*ptr);        *ptr = 0;        delete tmp;    }};/////////////////////////////////////////////////////////////////////////////////  CSafeStaticRef<>::////    For on-demand CObject-derived object.//    Create the variable of type "T" using CRef<>//    (to avoid premature destruction).//template <class T>class CSafeStaticRef : public CSafeStaticPtr_Base{public:    // Set the cleanup function to be called on variable destruction    CSafeStaticRef(FUserCleanup user_cleanup = 0)        : CSafeStaticPtr_Base(SelfCleanup, user_cleanup)    {}    // Create the variable if not created yet, return the reference    T& Get(void)    {        if ( !m_Ptr ) {            Init();        }        return static_cast<CRef<T>*> (m_Ptr)->GetObject();    }    T* operator -> (void) { return &Get(); }    T& operator *  (void) { return  Get(); }    // Initialize with an existing object. The object MUST be    // allocated with "new T" to avoid premature destruction.    // Set() works only for un-initialized safe-static variables.    void Set(T* object);private:    // Initialize the object and the reference    void Init(void);    // "virtual" cleanup function    static void SelfCleanup(void** ptr)    {        CRef<T>* tmp = static_cast< CRef<T>* > (*ptr);        *ptr = 0;        delete tmp;    }};/////////////////////////////////////////////////////////////////////////////////  CSafeStaticGuard::////    Register all on-demand variables,//    destroy them on the program termination.class NCBI_XNCBI_EXPORT CSafeStaticGuard{public:    // Check if already initialized. If not - create the stack,    // otherwise just increment the reference count.    CSafeStaticGuard(void);    // Check reference count, and if it is zero, then destroy    // all registered variables.    ~CSafeStaticGuard(void);    // Add new on-demand variable to the cleanup stack.    static void Register(CSafeStaticPtr_Base* ptr)    {        if ( !sm_Stack ) {            Get();        }        sm_Stack->push(ptr);    }private:    // Initialize the guard, return pointer to it.    static CSafeStaticGuard* Get(void);    // Stack to keep registered variables.    typedef stack<CSafeStaticPtr_Base*> TStack;    static TStack* sm_Stack;    // Reference counter. The stack is destroyed when    // the last reference is removed.    static int sm_RefCount;};///////////////////////////////////////////////////////////////////////////////// This static variable must be present in all modules using// on-demand variables. The guard must be created first// regardless of the modules initialization order.//static CSafeStaticGuard s_CleanupGuard;///////////////////////////////////////////////////////////////////////////////// Large inline methodstemplate <class T>inlinevoid CSafeStaticPtr<T>::Set(T* object){    bool mutex_locked = false;    if ( Init_Lock(&mutex_locked) ) {        // Set the new object and register for cleanup        try {            m_Ptr = object;            CSafeStaticGuard::Register(this);        }        catch (CException& e) {            Init_Unlock(mutex_locked);            NCBI_RETHROW_SAME(e, "CSafeStaticPtr::Set: Register() failed");        }        catch (...) {            Init_Unlock(mutex_locked);            NCBI_THROW(CCoreException,eCore,                       "CSafeStaticPtr::Set: Register() failed");        }    }    Init_Unlock(mutex_locked);}template <class T>inlinevoid CSafeStaticPtr<T>::Init(void){    bool mutex_locked = false;    if ( Init_Lock(&mutex_locked) ) {        // Create the object and register for cleanup        try {            m_Ptr = new T;            CSafeStaticGuard::Register(this);        }        catch (CException& e) {            Init_Unlock(mutex_locked);            NCBI_RETHROW_SAME(e, "CSafeStaticPtr::Init: Register() failed");        }        catch (...) {            Init_Unlock(mutex_locked);            NCBI_THROW(CCoreException,eCore,                       "CSafeStaticPtr::Init: Register() failed");        }    }    Init_Unlock(mutex_locked);}template <class T>inlinevoid CSafeStaticRef<T>::Set(T* object){    bool mutex_locked = false;    if ( Init_Lock(&mutex_locked) ) {        // Set the new object and register for cleanup        try {            m_Ptr = new CRef<T> (object);            CSafeStaticGuard::Register(this);        }        catch (CException& e) {            Init_Unlock(mutex_locked);            NCBI_RETHROW_SAME(e, "CSafeStaticRef::Set: Register() failed");        }        catch (...) {            Init_Unlock(mutex_locked);            NCBI_THROW(CCoreException,eCore,                       "CSafeStaticRef::Set: Register() failed");        }    }    Init_Unlock(mutex_locked);}template <class T>inlinevoid CSafeStaticRef<T>::Init(void){    bool mutex_locked = false;    if ( Init_Lock(&mutex_locked) ) {        // Create the object and register for cleanup        try {            m_Ptr = new CRef<T> (new T);            CSafeStaticGuard::Register(this);        }        catch (CException& e) {            Init_Unlock(mutex_locked);            NCBI_RETHROW_SAME(e, "CSafeStaticRef::Init: Register() failed");        }        catch (...) {            Init_Unlock(mutex_locked);            NCBI_THROW(CCoreException,eCore,                       "CSafeStaticRef::Init: Register() failed");        }    }    Init_Unlock(mutex_locked);}END_NCBI_SCOPE/* * =========================================================================== * $Log: ncbi_safe_static.hpp,v $ * Revision 1000.1  2004/06/01 19:07:46  gouriano * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.12 * * Revision 1.12  2004/04/26 14:28:59  ucko * Move large inline methods [Set(), Init()] from CSafeStatic{Ptr,Ref}'s * definitions to the end of the file, both to reduce clutter and because * GCC 3.4 insists on seeing CSafeStaticGuard first. * * Revision 1.11  2002/12/18 22:53:21  dicuccio * Added export specifier for building DLLs in windows.  Added global list of * all such specifiers in mswin_exports.hpp, included through ncbistl.hpp * * Revision 1.10  2002/09/19 20:05:41  vasilche * Safe initialization of static mutexes * * Revision 1.9  2002/07/15 18:17:50  gouriano * renamed CNcbiException and its descendents * * Revision 1.8  2002/07/11 14:17:53  gouriano * exceptions replaced by CNcbiException-type ones * * Revision 1.7  2002/04/11 20:39:15  ivanov * CVS log moved to end of the file * * Revision 1.6  2001/12/07 18:48:48  grichenk * Improved CSafeStaticGuard behaviour. * * Revision 1.5  2001/08/24 13:42:37  grichenk * Added CSafeStaticXXX::Set() methods for initialization with an * existing object * * Revision 1.4  2001/04/06 15:45:26  grichenk * Modified SelfCleanup() methods for more safety * * Revision 1.3  2001/03/30 23:10:10  grichenk * Protected from double initializations and deadlocks in multithread * environment * * Revision 1.2  2001/03/26 21:01:41  vakatov * CSafeStaticPtr, CSafeStaticRef -- added "operator *" * * Revision 1.1  2001/03/26 20:38:33  vakatov * Initial revision (by A.Grichenko) * * =========================================================================== */#endif  /* NCBI_SAFE_STATIC__HPP */

⌨️ 快捷键说明

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