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

📄 ncbiobj.cpp

📁 ncbi源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * =========================================================================== * PRODUCTION $Log: ncbiobj.cpp,v $ * PRODUCTION Revision 1000.5  2004/06/01 19:09:16  gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.45 * PRODUCTION * =========================================================================== *//*  $Id: ncbiobj.cpp,v 1000.5 2004/06/01 19:09:16 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:  *   Eugene Vasilchenko * * File Description: *   Standard CObject and CRef classes for reference counter based GC * */#include <ncbi_pch.hpp>#include <corelib/ncbiobj.hpp>#include <corelib/ncbimtx.hpp>//#define USE_SINGLE_ALLOC// There was a long and bootless discussion:// is it possible to determine whether the object has been created// on the stack or on the heap.// Correct answer is "it is impossible"// Still, we try to... (we know it is not 100% bulletproof)//// Attempts include://// 1. operator new puts a pointer to newly allocated memory in the list.//    Object constructor scans the list, if it finds itself there -//    yes, it has been created on the heap. (If it does not find itself//    there, it still may have been created on the heap).//    This method requires thread synchronization.//// 2. operator new puts a special mask (eCounterNew two times) in the//    newly allocated memory. Object constructor looks for this mask,//    if it finds it there - yes, it has been created on the heap.//// 3. operator new puts a special mask (single eCounterNew) in the//    newly allocated memory. Object constructor looks for this mask,//    if it finds it there, it also compares addresses of a variable//    on the stack and itself (also using STACK_THRESHOLD). If these two//    are "far enough from each other" - yes, the object is on the heap.//// From these three methods, the first one seems to be most reliable,// but also most slow.// Method #2 is hopefully reliable enough// Method #3 is unreliable at all (we saw this)//#define USE_HEAPOBJ_LIST  0#if USE_HEAPOBJ_LIST#  include <corelib/ncbi_safe_static.hpp>#  include <list>#  include <algorithm>#else#  define USE_COMPLEX_MASK  1#  if USE_COMPLEX_MASK#    define STACK_THRESHOLD (64)#  else#    define STACK_THRESHOLD (16*1024)#  endif#endifBEGIN_NCBI_SCOPE///////////////////////////////////////////////////////////////////////////////  CObject:://DEFINE_STATIC_FAST_MUTEX(sm_ObjectMutex);#if defined(NCBI_COUNTER_NEED_MUTEX)// CAtomicCounter doesn't normally have a .cpp file of its own, so this// goes here instead.DEFINE_STATIC_FAST_MUTEX(sm_AtomicCounterMutex);CAtomicCounter::TValue CAtomicCounter::Add(int delta) THROWS_NONE{    CFastMutexGuard LOCK(sm_AtomicCounterMutex);    return m_Value += delta;}#endif#if USE_HEAPOBJ_LISTstatic CSafeStaticPtr< list<const void*> > s_heap_obj;#endif#if USE_COMPLEX_MASKstatic inline CAtomicCounter* GetSecondCounter(CObject* ptr){  return reinterpret_cast<CAtomicCounter*> (ptr + 1);}#endif#ifdef USE_SINGLE_ALLOC#define SINGLE_ALLOC_THRESHOLD (   2*1024)#define SINGLE_ALLOC_POOL_SIZE (1024*1024)DEFINE_STATIC_FAST_MUTEX(sx_SingleAllocMutex);static char*  single_alloc_pool = 0;static size_t single_alloc_pool_size = 0;void* single_alloc(size_t size){    if ( size > SINGLE_ALLOC_THRESHOLD ) {        return ::operator new(size);    }    sx_SingleAllocMutex.Lock();    size_t pool_size = single_alloc_pool_size;    char* pool;    if ( size > pool_size ) {        pool_size = SINGLE_ALLOC_THRESHOLD;        pool = (char*) malloc(pool_size);        if ( !pool ) {            sx_SingleAllocMutex.Unlock();            throw bad_alloc();        }        memset(pool, 0, pool_size);        single_alloc_pool = pool;        single_alloc_pool_size = pool_size;    }    else {        pool = single_alloc_pool;    }    single_alloc_pool      = pool      + size;    single_alloc_pool_size = pool_size - size;    sx_SingleAllocMutex.Unlock();    return pool;}#endif// CObject local new operator to mark allocation in heapvoid* CObject::operator new(size_t size){    _ASSERT(size >= sizeof(CObject));    size = max(size, sizeof(CObject) + sizeof(TCounter));#ifdef USE_SINGLE_ALLOC    void* ptr = single_alloc(size);#  if USE_COMPLEX_MASK    GetSecondCounter(static_cast<CObject*>(ptr))->Set(eCounterNew);#  endif// USE_COMPLEX_MASK    static_cast<CObject*>(ptr)->m_Counter.Set(eCounterNew);    return ptr;#else    void* ptr = ::operator new(size);#if USE_HEAPOBJ_LIST    {{        CFastMutexGuard LOCK(sm_ObjectMutex);        s_heap_obj->push_front(ptr);    }}#else// USE_HEAPOBJ_LIST    memset(ptr, 0, size);#  if USE_COMPLEX_MASK    GetSecondCounter(static_cast<CObject*>(ptr))->Set(eCounterNew);#  endif// USE_COMPLEX_MASK#endif// USE_HEAPOBJ_LIST    static_cast<CObject*>(ptr)->m_Counter.Set(eCounterNew);    return ptr;#endif}// CObject local new operator to mark allocation in other memory chunkvoid* CObject::operator new(size_t size, void* place){    _ASSERT(size >= sizeof(CObject));#ifdef USE_SINGLE_ALLOC    return place;#else    memset(place, 0, size);    return place;#endif}// complement placement delete operator -> do nothingvoid CObject::operator delete(void* /*ptr*/, void* /*place*/){}// CObject local new operator to mark allocation in heapvoid* CObject::operator new[](size_t size){#ifdef USE_SINGLE_ALLOC    return single_alloc(size);#else# ifdef NCBI_OS_MSWIN    void* ptr = ::operator new(size);# else    void* ptr = ::operator new[](size);# endif    memset(ptr, 0, size);    return ptr;#endif}void CObject::operator delete(void* ptr){#ifdef USE_SINGLE_ALLOC#else# ifdef _DEBUG    CObject* objectPtr = static_cast<CObject*>(ptr);    _ASSERT(objectPtr->m_Counter.Get() == eCounterDeleted  ||            objectPtr->m_Counter.Get() == eCounterNew);# endif    ::operator delete(ptr);#endif}void CObject::operator delete[](void* ptr){#ifdef USE_SINGLE_ALLOC#else#  ifdef NCBI_OS_MSWIN    ::operator delete(ptr);#  else    ::operator delete[](ptr);#  endif#endif}// initialization in debug modevoid CObject::InitCounter(void){    // This code can't use Get(), which may block waiting for an    // update that will never happen.    // ATTENTION:  this code can cause UMR (Uninit Mem Read) -- it's okay here!    if ( m_Counter.m_Value != eCounterNew ) {        // takes care of statically allocated case        m_Counter.Set(eCounterNotInHeap);    }    else {        bool inStack = false;#if USE_HEAPOBJ_LIST        const void* ptr = dynamic_cast<const void*>(this);        {{            CFastMutexGuard LOCK(sm_ObjectMutex);            list<const void*>::iterator i =                find( s_heap_obj->begin(), s_heap_obj->end(), ptr);            inStack = (i == s_heap_obj->end());            if (!inStack) {                s_heap_obj->erase(i);            }        }}#else // USE_HEAPOBJ_LIST#  if USE_COMPLEX_MASK        inStack = GetSecondCounter(this)->m_Value != eCounterNew;#  endif // USE_COMPLEX_MASK        // m_Counter == eCounterNew -> possibly in heap        if (!inStack) {        char stackObject;        const char* stackObjectPtr = &stackObject;        const char* objectPtr = reinterpret_cast<const char*>(this);        inStack =#  ifdef STACK_GROWS_UP            (objectPtr < stackObjectPtr) &&#  else            (objectPtr < stackObjectPtr + STACK_THRESHOLD) &&#  endif#  ifdef STACK_GROWS_DOWN            (objectPtr > stackObjectPtr);#  else            (objectPtr > stackObjectPtr - STACK_THRESHOLD);#  endif        }#endif // USE_HEAPOBJ_LIST        // surely not in heap        if ( inStack )            m_Counter.Set(eCounterNotInHeap);        else            m_Counter.Set(eCounterInHeap);    }}CObject::CObject(void){    InitCounter();}CObject::CObject(const CObject& /*src*/){    InitCounter();}#ifdef _DEBUG# define ObjFatal Fatal#else# define ObjFatal Critical#endifCObject::~CObject(void){    TCount count = m_Counter.Get();    if ( count == TCount(eCounterInHeap)  ||         count == TCount(eCounterNotInHeap) ) {        // reference counter is zero -> ok    }    else if ( ObjectStateValid(count) ) {        _ASSERT(ObjectStateReferenced(count));        // referenced object        ERR_POST(ObjFatal << "CObject::~CObject: "                 "Referenced CObject may not be deleted");    }    else if ( count == eCounterDeleted ) {        // deleted object        ERR_POST(ObjFatal << "CObject::~CObject: "                 "CObject is already deleted");    }    else {        // bad object        ERR_POST(ObjFatal << "CObject::~CObject: "                 "CObject is corrupted");    }    // mark object as deleted    m_Counter.Set(eCounterDeleted);}void CObject::CheckReferenceOverflow(TCount count) const{    if ( ObjectStateValid(count) ) {        // counter overflow        NCBI_THROW(CObjectException, eRefOverflow,                   "CObject's reference counter overflow");    }    else if ( count == eCounterDeleted ) {        // deleted object        NCBI_THROW(CObjectException, eDeleted,                   "CObject is already deleted");    }    else {        // bad object        NCBI_THROW(CObjectException, eCorrupted,                   "CObject is corrupted");    }}void CObject::RemoveLastReference(void) const{    TCount count = m_Counter.Get();    if ( ObjectStateCanBeDeleted(count) ) {        if ( count == TCount(eCounterInHeap) ) {            // last reference to heap object -> delete            delete this;            return;        }    }    else {        if ( ObjectStateValid(count) ) {            // last reference to non heap object -> do nothing            return;        }    }    // Error here    // restore original value    m_Counter.Add(eCounterStep);    _ASSERT(!ObjectStateValid(count + eCounterStep));    // bad object    ERR_POST(ObjFatal << "CObject::RemoveLastReference: "             "Unreferenced CObject may not be released");}void CObject::ReleaseReference(void) const{    TCount count = m_Counter.Add(-eCounterStep) + eCounterStep;    if ( ObjectStateReferenced(count) ) {        return;    }    m_Counter.Add(eCounterStep); // undo    // error    if ( !ObjectStateValid(count) ) {        NCBI_THROW(CObjectException, eCorrupted,                   "CObject is corrupted");    } else {        NCBI_THROW(CObjectException, eNoRef,                   "Unreferenced CObject may not be released");    }}void CObject::DoNotDeleteThisObject(void){    bool is_valid;    {{        CFastMutexGuard LOCK(sm_ObjectMutex);        TCount count = m_Counter.Get();        is_valid = ObjectStateValid(count);        if (is_valid  &&  !ObjectStateReferenced(count)) {            m_Counter.Set(eCounterNotInHeap);            return;        }    }}        if ( is_valid ) {        NCBI_THROW(CObjectException, eRefUnref,                   "Referenced CObject cannot be made unreferenced one");    }    else {        NCBI_THROW(CObjectException, eCorrupted,                   "CObject is corrupted");    }}void CObject::DoDeleteThisObject(void){    {{        CFastMutexGuard LOCK(sm_ObjectMutex);        TCount count = m_Counter.Get();        if ( ObjectStateValid(count) ) {            if ( !(count & eStateBitsInHeap) ) {                m_Counter.Add(eStateBitsInHeap);            }            return;        }    }}    NCBI_THROW(CObjectException, eCorrupted,

⌨️ 快捷键说明

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