ncbiobj.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:25k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ncbiobj.cpp,v $
  4.  * PRODUCTION Revision 1000.5  2004/06/01 19:09:16  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.45
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: ncbiobj.cpp,v 1000.5 2004/06/01 19:09:16 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author: 
  35.  *   Eugene Vasilchenko
  36.  *
  37.  * File Description:
  38.  *   Standard CObject and CRef classes for reference counter based GC
  39.  *
  40.  */
  41. #include <ncbi_pch.hpp>
  42. #include <corelib/ncbiobj.hpp>
  43. #include <corelib/ncbimtx.hpp>
  44. //#define USE_SINGLE_ALLOC
  45. // There was a long and bootless discussion:
  46. // is it possible to determine whether the object has been created
  47. // on the stack or on the heap.
  48. // Correct answer is "it is impossible"
  49. // Still, we try to... (we know it is not 100% bulletproof)
  50. //
  51. // Attempts include:
  52. //
  53. // 1. operator new puts a pointer to newly allocated memory in the list.
  54. //    Object constructor scans the list, if it finds itself there -
  55. //    yes, it has been created on the heap. (If it does not find itself
  56. //    there, it still may have been created on the heap).
  57. //    This method requires thread synchronization.
  58. //
  59. // 2. operator new puts a special mask (eCounterNew two times) in the
  60. //    newly allocated memory. Object constructor looks for this mask,
  61. //    if it finds it there - yes, it has been created on the heap.
  62. //
  63. // 3. operator new puts a special mask (single eCounterNew) in the
  64. //    newly allocated memory. Object constructor looks for this mask,
  65. //    if it finds it there, it also compares addresses of a variable
  66. //    on the stack and itself (also using STACK_THRESHOLD). If these two
  67. //    are "far enough from each other" - yes, the object is on the heap.
  68. //
  69. // From these three methods, the first one seems to be most reliable,
  70. // but also most slow.
  71. // Method #2 is hopefully reliable enough
  72. // Method #3 is unreliable at all (we saw this)
  73. //
  74. #define USE_HEAPOBJ_LIST  0
  75. #if USE_HEAPOBJ_LIST
  76. #  include <corelib/ncbi_safe_static.hpp>
  77. #  include <list>
  78. #  include <algorithm>
  79. #else
  80. #  define USE_COMPLEX_MASK  1
  81. #  if USE_COMPLEX_MASK
  82. #    define STACK_THRESHOLD (64)
  83. #  else
  84. #    define STACK_THRESHOLD (16*1024)
  85. #  endif
  86. #endif
  87. BEGIN_NCBI_SCOPE
  88. /////////////////////////////////////////////////////////////////////////////
  89. //  CObject::
  90. //
  91. DEFINE_STATIC_FAST_MUTEX(sm_ObjectMutex);
  92. #if defined(NCBI_COUNTER_NEED_MUTEX)
  93. // CAtomicCounter doesn't normally have a .cpp file of its own, so this
  94. // goes here instead.
  95. DEFINE_STATIC_FAST_MUTEX(sm_AtomicCounterMutex);
  96. CAtomicCounter::TValue CAtomicCounter::Add(int delta) THROWS_NONE
  97. {
  98.     CFastMutexGuard LOCK(sm_AtomicCounterMutex);
  99.     return m_Value += delta;
  100. }
  101. #endif
  102. #if USE_HEAPOBJ_LIST
  103. static CSafeStaticPtr< list<const void*> > s_heap_obj;
  104. #endif
  105. #if USE_COMPLEX_MASK
  106. static inline CAtomicCounter* GetSecondCounter(CObject* ptr)
  107. {
  108.   return reinterpret_cast<CAtomicCounter*> (ptr + 1);
  109. }
  110. #endif
  111. #ifdef USE_SINGLE_ALLOC
  112. #define SINGLE_ALLOC_THRESHOLD (   2*1024)
  113. #define SINGLE_ALLOC_POOL_SIZE (1024*1024)
  114. DEFINE_STATIC_FAST_MUTEX(sx_SingleAllocMutex);
  115. static char*  single_alloc_pool = 0;
  116. static size_t single_alloc_pool_size = 0;
  117. void* single_alloc(size_t size)
  118. {
  119.     if ( size > SINGLE_ALLOC_THRESHOLD ) {
  120.         return ::operator new(size);
  121.     }
  122.     sx_SingleAllocMutex.Lock();
  123.     size_t pool_size = single_alloc_pool_size;
  124.     char* pool;
  125.     if ( size > pool_size ) {
  126.         pool_size = SINGLE_ALLOC_THRESHOLD;
  127.         pool = (char*) malloc(pool_size);
  128.         if ( !pool ) {
  129.             sx_SingleAllocMutex.Unlock();
  130.             throw bad_alloc();
  131.         }
  132.         memset(pool, 0, pool_size);
  133.         single_alloc_pool = pool;
  134.         single_alloc_pool_size = pool_size;
  135.     }
  136.     else {
  137.         pool = single_alloc_pool;
  138.     }
  139.     single_alloc_pool      = pool      + size;
  140.     single_alloc_pool_size = pool_size - size;
  141.     sx_SingleAllocMutex.Unlock();
  142.     return pool;
  143. }
  144. #endif
  145. // CObject local new operator to mark allocation in heap
  146. void* CObject::operator new(size_t size)
  147. {
  148.     _ASSERT(size >= sizeof(CObject));
  149.     size = max(size, sizeof(CObject) + sizeof(TCounter));
  150. #ifdef USE_SINGLE_ALLOC
  151.     void* ptr = single_alloc(size);
  152. #  if USE_COMPLEX_MASK
  153.     GetSecondCounter(static_cast<CObject*>(ptr))->Set(eCounterNew);
  154. #  endif// USE_COMPLEX_MASK
  155.     static_cast<CObject*>(ptr)->m_Counter.Set(eCounterNew);
  156.     return ptr;
  157. #else
  158.     void* ptr = ::operator new(size);
  159. #if USE_HEAPOBJ_LIST
  160.     {{
  161.         CFastMutexGuard LOCK(sm_ObjectMutex);
  162.         s_heap_obj->push_front(ptr);
  163.     }}
  164. #else// USE_HEAPOBJ_LIST
  165.     memset(ptr, 0, size);
  166. #  if USE_COMPLEX_MASK
  167.     GetSecondCounter(static_cast<CObject*>(ptr))->Set(eCounterNew);
  168. #  endif// USE_COMPLEX_MASK
  169. #endif// USE_HEAPOBJ_LIST
  170.     static_cast<CObject*>(ptr)->m_Counter.Set(eCounterNew);
  171.     return ptr;
  172. #endif
  173. }
  174. // CObject local new operator to mark allocation in other memory chunk
  175. void* CObject::operator new(size_t size, void* place)
  176. {
  177.     _ASSERT(size >= sizeof(CObject));
  178. #ifdef USE_SINGLE_ALLOC
  179.     return place;
  180. #else
  181.     memset(place, 0, size);
  182.     return place;
  183. #endif
  184. }
  185. // complement placement delete operator -> do nothing
  186. void CObject::operator delete(void* /*ptr*/, void* /*place*/)
  187. {
  188. }
  189. // CObject local new operator to mark allocation in heap
  190. void* CObject::operator new[](size_t size)
  191. {
  192. #ifdef USE_SINGLE_ALLOC
  193.     return single_alloc(size);
  194. #else
  195. # ifdef NCBI_OS_MSWIN
  196.     void* ptr = ::operator new(size);
  197. # else
  198.     void* ptr = ::operator new[](size);
  199. # endif
  200.     memset(ptr, 0, size);
  201.     return ptr;
  202. #endif
  203. }
  204. void CObject::operator delete(void* ptr)
  205. {
  206. #ifdef USE_SINGLE_ALLOC
  207. #else
  208. # ifdef _DEBUG
  209.     CObject* objectPtr = static_cast<CObject*>(ptr);
  210.     _ASSERT(objectPtr->m_Counter.Get() == eCounterDeleted  ||
  211.             objectPtr->m_Counter.Get() == eCounterNew);
  212. # endif
  213.     ::operator delete(ptr);
  214. #endif
  215. }
  216. void CObject::operator delete[](void* ptr)
  217. {
  218. #ifdef USE_SINGLE_ALLOC
  219. #else
  220. #  ifdef NCBI_OS_MSWIN
  221.     ::operator delete(ptr);
  222. #  else
  223.     ::operator delete[](ptr);
  224. #  endif
  225. #endif
  226. }
  227. // initialization in debug mode
  228. void CObject::InitCounter(void)
  229. {
  230.     // This code can't use Get(), which may block waiting for an
  231.     // update that will never happen.
  232.     // ATTENTION:  this code can cause UMR (Uninit Mem Read) -- it's okay here!
  233.     if ( m_Counter.m_Value != eCounterNew ) {
  234.         // takes care of statically allocated case
  235.         m_Counter.Set(eCounterNotInHeap);
  236.     }
  237.     else {
  238.         bool inStack = false;
  239. #if USE_HEAPOBJ_LIST
  240.         const void* ptr = dynamic_cast<const void*>(this);
  241.         {{
  242.             CFastMutexGuard LOCK(sm_ObjectMutex);
  243.             list<const void*>::iterator i =
  244.                 find( s_heap_obj->begin(), s_heap_obj->end(), ptr);
  245.             inStack = (i == s_heap_obj->end());
  246.             if (!inStack) {
  247.                 s_heap_obj->erase(i);
  248.             }
  249.         }}
  250. #else // USE_HEAPOBJ_LIST
  251. #  if USE_COMPLEX_MASK
  252.         inStack = GetSecondCounter(this)->m_Value != eCounterNew;
  253. #  endif // USE_COMPLEX_MASK
  254.         // m_Counter == eCounterNew -> possibly in heap
  255.         if (!inStack) {
  256.         char stackObject;
  257.         const char* stackObjectPtr = &stackObject;
  258.         const char* objectPtr = reinterpret_cast<const char*>(this);
  259.         inStack =
  260. #  ifdef STACK_GROWS_UP
  261.             (objectPtr < stackObjectPtr) &&
  262. #  else
  263.             (objectPtr < stackObjectPtr + STACK_THRESHOLD) &&
  264. #  endif
  265. #  ifdef STACK_GROWS_DOWN
  266.             (objectPtr > stackObjectPtr);
  267. #  else
  268.             (objectPtr > stackObjectPtr - STACK_THRESHOLD);
  269. #  endif
  270.         }
  271. #endif // USE_HEAPOBJ_LIST
  272.         // surely not in heap
  273.         if ( inStack )
  274.             m_Counter.Set(eCounterNotInHeap);
  275.         else
  276.             m_Counter.Set(eCounterInHeap);
  277.     }
  278. }
  279. CObject::CObject(void)
  280. {
  281.     InitCounter();
  282. }
  283. CObject::CObject(const CObject& /*src*/)
  284. {
  285.     InitCounter();
  286. }
  287. #ifdef _DEBUG
  288. # define ObjFatal Fatal
  289. #else
  290. # define ObjFatal Critical
  291. #endif
  292. CObject::~CObject(void)
  293. {
  294.     TCount count = m_Counter.Get();
  295.     if ( count == TCount(eCounterInHeap)  ||
  296.          count == TCount(eCounterNotInHeap) ) {
  297.         // reference counter is zero -> ok
  298.     }
  299.     else if ( ObjectStateValid(count) ) {
  300.         _ASSERT(ObjectStateReferenced(count));
  301.         // referenced object
  302.         ERR_POST(ObjFatal << "CObject::~CObject: "
  303.                  "Referenced CObject may not be deleted");
  304.     }
  305.     else if ( count == eCounterDeleted ) {
  306.         // deleted object
  307.         ERR_POST(ObjFatal << "CObject::~CObject: "
  308.                  "CObject is already deleted");
  309.     }
  310.     else {
  311.         // bad object
  312.         ERR_POST(ObjFatal << "CObject::~CObject: "
  313.                  "CObject is corrupted");
  314.     }
  315.     // mark object as deleted
  316.     m_Counter.Set(eCounterDeleted);
  317. }
  318. void CObject::CheckReferenceOverflow(TCount count) const
  319. {
  320.     if ( ObjectStateValid(count) ) {
  321.         // counter overflow
  322.         NCBI_THROW(CObjectException, eRefOverflow,
  323.                    "CObject's reference counter overflow");
  324.     }
  325.     else if ( count == eCounterDeleted ) {
  326.         // deleted object
  327.         NCBI_THROW(CObjectException, eDeleted,
  328.                    "CObject is already deleted");
  329.     }
  330.     else {
  331.         // bad object
  332.         NCBI_THROW(CObjectException, eCorrupted,
  333.                    "CObject is corrupted");
  334.     }
  335. }
  336. void CObject::RemoveLastReference(void) const
  337. {
  338.     TCount count = m_Counter.Get();
  339.     if ( ObjectStateCanBeDeleted(count) ) {
  340.         if ( count == TCount(eCounterInHeap) ) {
  341.             // last reference to heap object -> delete
  342.             delete this;
  343.             return;
  344.         }
  345.     }
  346.     else {
  347.         if ( ObjectStateValid(count) ) {
  348.             // last reference to non heap object -> do nothing
  349.             return;
  350.         }
  351.     }
  352.     // Error here
  353.     // restore original value
  354.     m_Counter.Add(eCounterStep);
  355.     _ASSERT(!ObjectStateValid(count + eCounterStep));
  356.     // bad object
  357.     ERR_POST(ObjFatal << "CObject::RemoveLastReference: "
  358.              "Unreferenced CObject may not be released");
  359. }
  360. void CObject::ReleaseReference(void) const
  361. {
  362.     TCount count = m_Counter.Add(-eCounterStep) + eCounterStep;
  363.     if ( ObjectStateReferenced(count) ) {
  364.         return;
  365.     }
  366.     m_Counter.Add(eCounterStep); // undo
  367.     // error
  368.     if ( !ObjectStateValid(count) ) {
  369.         NCBI_THROW(CObjectException, eCorrupted,
  370.                    "CObject is corrupted");
  371.     } else {
  372.         NCBI_THROW(CObjectException, eNoRef,
  373.                    "Unreferenced CObject may not be released");
  374.     }
  375. }
  376. void CObject::DoNotDeleteThisObject(void)
  377. {
  378.     bool is_valid;
  379.     {{
  380.         CFastMutexGuard LOCK(sm_ObjectMutex);
  381.         TCount count = m_Counter.Get();
  382.         is_valid = ObjectStateValid(count);
  383.         if (is_valid  &&  !ObjectStateReferenced(count)) {
  384.             m_Counter.Set(eCounterNotInHeap);
  385.             return;
  386.         }
  387.     }}
  388.     
  389.     if ( is_valid ) {
  390.         NCBI_THROW(CObjectException, eRefUnref,
  391.                    "Referenced CObject cannot be made unreferenced one");
  392.     }
  393.     else {
  394.         NCBI_THROW(CObjectException, eCorrupted,
  395.                    "CObject is corrupted");
  396.     }
  397. }
  398. void CObject::DoDeleteThisObject(void)
  399. {
  400.     {{
  401.         CFastMutexGuard LOCK(sm_ObjectMutex);
  402.         TCount count = m_Counter.Get();
  403.         if ( ObjectStateValid(count) ) {
  404.             if ( !(count & eStateBitsInHeap) ) {
  405.                 m_Counter.Add(eStateBitsInHeap);
  406.             }
  407.             return;
  408.         }
  409.     }}
  410.     NCBI_THROW(CObjectException, eCorrupted,
  411.                "CObject is corrupted");
  412. }
  413. static bool s_EnvFlag(const char* env_var_name)
  414. {
  415.     const char* value = getenv(env_var_name);
  416.     return value  &&  (*value == 'Y'  ||  *value == 'y' || *value == '1');
  417. }
  418.                         
  419. void CObjectException::x_InitErrCode(CException::EErrCode err_code)
  420. {
  421.     CCoreException::x_InitErrCode(err_code);
  422.     static bool abort_on_throw = s_EnvFlag("NCBI_ABORT_ON_COBJECT_THROW");
  423.     if ( abort_on_throw ) {
  424.         Abort();
  425.     }
  426. }
  427. void CObject::DebugDump(CDebugDumpContext ddc, unsigned int /*depth*/) const
  428. {
  429.     ddc.SetFrame("CObject");
  430.     ddc.Log("address",  dynamic_cast<const CDebugDumpable*>(this), 0);
  431. //    ddc.Log("memory starts at", dynamic_cast<const void*>(this));
  432. //    ddc.Log("onHeap", CanBeDeleted());
  433. }
  434. void CObject::ThrowNullPointerException(void)
  435. {
  436.     static bool abort_on_null = s_EnvFlag("NCBI_ABORT_ON_NULL");
  437.     if ( abort_on_null ) {
  438.         Abort();
  439.     }
  440.     NCBI_THROW(CCoreException, eNullPtr, "Attempt to access NULL pointer.");
  441. }
  442. END_NCBI_SCOPE
  443. #if 0
  444. struct SAllocHeader
  445. {
  446.     unsigned magic;
  447.     unsigned seq_number;
  448.     size_t   size;
  449.     void*    ptr;
  450. };
  451. struct SAllocFooter
  452. {
  453.     void*    ptr;
  454.     size_t   size;
  455.     unsigned seq_number;
  456.     unsigned magic;
  457. };
  458. static const size_t kAllocSizeBefore = sizeof(SAllocHeader)+8;
  459. static const size_t kAllocSizeAfter = sizeof(SAllocFooter)+8;
  460. static const char kAllocFillBefore1 = 0xaa;
  461. static const char kAllocFillBefore2 = 0xbb;
  462. static const char kAllocFillInside = 0xcc;
  463. static const char kAllocFillAfter = 0xdd;
  464. static const char kAllocFillFree = 0xee;
  465. static const unsigned kAllocMagicHeader = 0x89abcdef;
  466. static const unsigned kAllocMagicFooter = 0xfedcba98;
  467. static std::bad_alloc bad_alloc_instance;
  468. DEFINE_STATIC_FAST_MUTEX(s_alloc_mutex);
  469. static NCBI_NS_NCBI::CAtomicCounter seq_number;
  470. static const size_t kLogSize = 64 * 1024;
  471. struct SAllocLog {
  472.     unsigned seq_number;
  473.     enum EType {
  474.         eEmpty = 0,
  475.         eInit,
  476.         eNew,
  477.         eNewArr,
  478.         eDelete,
  479.         eDeleteArr
  480.     };
  481.     char   type;
  482.     char   completed;
  483.     size_t size;
  484.     void*  ptr;
  485. };
  486. static SAllocLog alloc_log[kLogSize];
  487. static inline SAllocHeader* get_header(void* ptr)
  488. {
  489.     return (SAllocHeader*) ((char*) ptr-kAllocSizeBefore);
  490. }
  491. static inline void* get_guard_before(SAllocHeader* header)
  492. {
  493.     return (char*) header + sizeof(SAllocHeader);
  494. }
  495. static inline size_t get_guard_before_size()
  496. {
  497.     return kAllocSizeBefore - sizeof(SAllocHeader);
  498. }
  499. static inline size_t get_extra_size(size_t size)
  500. {
  501.     return (-size) & 7;
  502. }
  503. static inline size_t get_guard_after_size(size_t size)
  504. {
  505.     return kAllocSizeAfter - sizeof(SAllocFooter) + get_extra_size(size);
  506. }
  507. static inline void* get_ptr(SAllocHeader* header)
  508. {
  509.     return (char*) header + kAllocSizeBefore;
  510. }
  511. static inline void* get_guard_after(SAllocFooter* footer, size_t size)
  512. {
  513.     return (char*)footer-get_guard_after_size(size);
  514. }
  515. static inline SAllocFooter* get_footer(SAllocHeader* header, size_t size)
  516. {
  517.     return (SAllocFooter*)((char*)get_ptr(header)+size+get_guard_after_size(size));
  518. }
  519. static inline size_t get_total_size(size_t size)
  520. {
  521.     return size+get_extra_size(size) + (kAllocSizeBefore+kAllocSizeAfter);
  522. }
  523. static inline SAllocLog& start_log(unsigned number, SAllocLog::EType type)
  524. {
  525.     SAllocLog& slot = alloc_log[number % kLogSize];
  526.     slot.type = SAllocLog::eInit;
  527.     slot.completed = false;
  528.     slot.seq_number = number;
  529.     slot.ptr = 0;
  530.     slot.size = 0;
  531.     slot.type = type;
  532.     return slot;
  533. }
  534. static inline
  535. void memchk(const void* ptr, char byte, size_t size)
  536. {
  537.     for ( const char* mem = (const char*)ptr; size && *mem == byte; ++mem, --size ) {
  538.     }
  539.     if ( size ) {
  540.         std::abort();
  541.     }
  542. }
  543. static inline
  544. void* alloc_mem(size_t size, bool array) throw()
  545. {
  546.     unsigned number = seq_number.Add(1);
  547.     SAllocLog& log = start_log(number, array? SAllocLog::eNewArr: SAllocLog::eNew);
  548.     log.size = size;
  549.     SAllocHeader* header;
  550.     {{
  551.         NCBI_NS_NCBI::CFastMutexGuard guard(s_alloc_mutex);
  552.         header = (SAllocHeader*)std::malloc(get_total_size(size));
  553.     }}
  554.     if ( !header ) {
  555.         log.completed = true;
  556.         return 0;
  557.     }
  558.     SAllocFooter* footer = get_footer(header, size);
  559.     header->magic = kAllocMagicHeader;
  560.     footer->magic = kAllocMagicFooter;
  561.     header->seq_number = footer->seq_number = number;
  562.     header->size = footer->size = size;
  563.     header->ptr = footer->ptr = log.ptr = get_ptr(header);
  564.     std::memset(get_guard_before(header),
  565.                 array? kAllocFillBefore2: kAllocFillBefore1,
  566.                 get_guard_before_size());
  567.     std::memset(get_guard_after(footer, size),
  568.                 kAllocFillAfter,
  569.                 get_guard_after_size(size));
  570.     std::memset(get_ptr(header), kAllocFillInside, size);
  571.     log.completed = true;
  572.     return get_ptr(header);
  573. }
  574. static inline
  575. void free_mem(void* ptr, bool array)
  576. {
  577.     unsigned number = seq_number.Add(1);
  578.     SAllocLog& log =
  579.         start_log(number, array ? SAllocLog::eDeleteArr: SAllocLog::eDelete);
  580.     if ( ptr ) {
  581.         log.ptr = ptr;
  582.         
  583.         SAllocHeader* header = get_header(ptr);
  584.         if ( header->magic != kAllocMagicHeader ||
  585.              header->seq_number >= number ||
  586.              header->ptr != get_ptr(header) ) {
  587.             abort();
  588.         }
  589.         size_t size = log.size = header->size;
  590.         SAllocFooter* footer = get_footer(header, size);
  591.         if ( footer->magic      != kAllocMagicFooter ||
  592.              footer->seq_number != header->seq_number ||
  593.              footer->ptr        != get_ptr(header) ||
  594.              footer->size       != size ) {
  595.             abort();
  596.         }
  597.         
  598.         memchk(get_guard_before(header),
  599.                array? kAllocFillBefore2: kAllocFillBefore1,
  600.                get_guard_before_size());
  601.         memchk(get_guard_after(footer, size),
  602.                kAllocFillAfter,
  603.                get_guard_after_size(size));
  604.         std::memset(header, kAllocFillFree, get_total_size(size));
  605.         {{
  606.             NCBI_NS_NCBI::CFastMutexGuard guard(s_alloc_mutex);
  607.             std::free(header);
  608.         }}
  609.     }
  610.     log.completed = true;
  611. }
  612. void* operator new(size_t size) throw(std::bad_alloc)
  613. {
  614.     void* ret = alloc_mem(size, false);
  615.     if ( !ret )
  616.         throw bad_alloc_instance;
  617.     return ret;
  618. }
  619. void* operator new(size_t size, const std::nothrow_t&) throw()
  620. {
  621.     return alloc_mem(size, false);
  622. }
  623. void* operator new[](size_t size) throw(std::bad_alloc)
  624. {
  625.     void* ret = alloc_mem(size, true);
  626.     if ( !ret )
  627.         throw bad_alloc_instance;
  628.     return ret;
  629. }
  630. void* operator new[](size_t size, const std::nothrow_t&) throw()
  631. {
  632.     return alloc_mem(size, true);
  633. }
  634. void operator delete(void* ptr) throw()
  635. {
  636.     free_mem(ptr, false);
  637. }
  638. void  operator delete(void* ptr, const std::nothrow_t&) throw()
  639. {
  640.     free_mem(ptr, false);
  641. }
  642. void  operator delete[](void* ptr) throw()
  643. {
  644.     free_mem(ptr, true);
  645. }
  646. void  operator delete[](void* ptr, const std::nothrow_t&) throw()
  647. {
  648.     free_mem(ptr, true);
  649. }
  650. #endif
  651. /*
  652.  * ===========================================================================
  653.  * $Log: ncbiobj.cpp,v $
  654.  * Revision 1000.5  2004/06/01 19:09:16  gouriano
  655.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.45
  656.  *
  657.  * Revision 1.45  2004/05/14 13:59:27  gorelenk
  658.  * Added include of ncbi_pch.hpp
  659.  *
  660.  * Revision 1.44  2004/04/05 15:58:43  vakatov
  661.  * CObject::InitCounter() -- ATTENTION:  this code can cause UMR -- it's okay
  662.  *
  663.  * Revision 1.43  2004/02/19 16:44:19  vasilche
  664.  * Modified debug new/delete code for 64 bit builds.
  665.  *
  666.  * Revision 1.42  2004/02/17 21:08:19  vasilche
  667.  * Added code to debug memory allocation problems (currently commented out).
  668.  *
  669.  * Revision 1.41  2003/12/17 20:10:07  vasilche
  670.  * Avoid throwing exceptions from destructors.
  671.  * Display Fatal message in Debug mode and Critical message in Release mode.
  672.  *
  673.  * Revision 1.40  2003/09/17 15:58:29  vasilche
  674.  * Allow debug abort when:
  675.  * CObjectException is thrown - env var NCBI_ABORT_ON_COBJECT_THROW=[Yy1],
  676.  * CNullPointerException is thrown - env var NCBI_ABORT_ON_NULL=[Yy1].
  677.  * Allow quit abort in debug mode and coredump in release mode:
  678.  * env var DIAG_SILENT_ABORT=[Yy1Nn0].
  679.  *
  680.  * Revision 1.39  2003/09/17 15:20:46  vasilche
  681.  * Moved atomic counter swap functions to separate file.
  682.  * Added CRef<>::AtomicResetFrom(), CRef<>::AtomicReleaseTo() methods.
  683.  *
  684.  * Revision 1.38  2003/08/12 12:06:58  siyan
  685.  * Changed name of implementation for AddReferenceOverflow(). It is now
  686.  * CheckReferenceOverflow().
  687.  *
  688.  * Revision 1.37  2003/07/17 23:01:32  vasilche
  689.  * Added matching operator delete.
  690.  *
  691.  * Revision 1.36  2003/07/17 20:01:07  vasilche
  692.  * Added inplace operator new().
  693.  *
  694.  * Revision 1.35  2003/03/06 19:40:52  ucko
  695.  * InitCounter: read m_Value directly rather than going through Get(), which
  696.  * would end up spinning forever if it came across NCBI_COUNTER_RESERVED_VALUE.
  697.  *
  698.  * Revision 1.34  2002/11/27 12:53:45  dicuccio
  699.  * Added CObject::ThrowNullPointerException() to get around some inlining issues.
  700.  *
  701.  * Revision 1.33  2002/09/20 13:52:46  vasilche
  702.  * Renamed sm_Mutex -> sm_AtomicCounterMutex
  703.  *
  704.  * Revision 1.32  2002/09/19 20:05:43  vasilche
  705.  * Safe initialization of static mutexes
  706.  *
  707.  * Revision 1.31  2002/08/28 17:05:50  vasilche
  708.  * Remove virtual inheritance, fixed heap detection
  709.  *
  710.  * Revision 1.30  2002/07/15 18:17:24  gouriano
  711.  * renamed CNcbiException and its descendents
  712.  *
  713.  * Revision 1.29  2002/07/11 14:18:27  gouriano
  714.  * exceptions replaced by CNcbiException-type ones
  715.  *
  716.  * Revision 1.28  2002/05/29 21:17:57  gouriano
  717.  * minor change in debug dump
  718.  *
  719.  * Revision 1.27  2002/05/28 17:59:55  gouriano
  720.  * minor modification od DebugDump
  721.  *
  722.  * Revision 1.26  2002/05/24 14:12:10  ucko
  723.  * Provide CAtomicCounter::sm_Mutex if necessary.
  724.  *
  725.  * Revision 1.25  2002/05/23 22:24:23  ucko
  726.  * Use low-level atomic operations for reference counts
  727.  *
  728.  * Revision 1.24  2002/05/17 14:27:12  gouriano
  729.  * added DebugDump base class and function to CObject
  730.  *
  731.  * Revision 1.23  2002/05/14 21:12:11  gouriano
  732.  * DebugDump() moved into a separate class
  733.  *
  734.  * Revision 1.22  2002/05/14 14:44:24  gouriano
  735.  * added DebugDump function to CObject
  736.  *
  737.  * Revision 1.21  2002/05/10 20:53:12  gouriano
  738.  * more stack/heap tests
  739.  *
  740.  * Revision 1.20  2002/05/10 19:42:31  gouriano
  741.  * object on stack vs on heap - do it more accurately
  742.  *
  743.  * Revision 1.19  2002/04/11 21:08:03  ivanov
  744.  * CVS log moved to end of the file
  745.  *
  746.  * Revision 1.18  2001/08/20 18:35:10  ucko
  747.  * Clarified InitCounter's treatment of statically allocated objects.
  748.  *
  749.  * Revision 1.17  2001/08/20 15:59:43  ucko
  750.  * Test more accurately whether CObjects were created on the stack.
  751.  *
  752.  * Revision 1.16  2001/05/17 15:04:59  lavr
  753.  * Typos corrected
  754.  *
  755.  * Revision 1.15  2001/04/03 18:08:54  grichenk
  756.  * Converted eCounterNotInHeap to TCounter(eCounterNotInHeap)
  757.  *
  758.  * Revision 1.14  2001/03/26 21:22:52  vakatov
  759.  * Minor cosmetics
  760.  *
  761.  * Revision 1.13  2001/03/13 22:43:50  vakatov
  762.  * Made "CObject" MT-safe
  763.  * + CObject::DoDeleteThisObject()
  764.  *
  765.  * Revision 1.12  2000/12/26 22:00:19  vasilche
  766.  * Fixed error check for case CObject constructor never called.
  767.  *
  768.  * Revision 1.11  2000/11/01 21:20:55  vasilche
  769.  * Fixed missing new[] and delete[] on MSVC.
  770.  *
  771.  * Revision 1.10  2000/11/01 20:37:16  vasilche
  772.  * Fixed detection of heap objects.
  773.  * Removed ECanDelete enum and related constructors.
  774.  * Disabled sync_with_stdio ad the beginning of AppMain.
  775.  *
  776.  * Revision 1.9  2000/10/17 17:59:08  vasilche
  777.  * Detected misuse of CObject constructors will be reported via ERR_POST
  778.  * and will not throw exception.
  779.  *
  780.  * Revision 1.8  2000/10/13 16:26:30  vasilche
  781.  * Added heuristic for detection of CObject allocation in heap.
  782.  *
  783.  * Revision 1.7  2000/08/15 19:41:41  vasilche
  784.  * Changed reference counter to allow detection of more errors.
  785.  *
  786.  * Revision 1.6  2000/06/16 16:29:51  vasilche
  787.  * Added SetCanDelete() method to allow to change CObject 'in heap' status
  788.  * immediately after creation.
  789.  *
  790.  * Revision 1.5  2000/06/07 19:44:22  vasilche
  791.  * Removed unneeded THROWS declaration - they lead to encreased code size.
  792.  *
  793.  * Revision 1.4  2000/03/29 15:50:41  vasilche
  794.  * Added const version of CRef - CConstRef.
  795.  * CRef and CConstRef now accept classes inherited from CObject.
  796.  *
  797.  * Revision 1.3  2000/03/08 17:47:30  vasilche
  798.  * Simplified error check.
  799.  *
  800.  * Revision 1.2  2000/03/08 14:18:22  vasilche
  801.  * Fixed throws instructions.
  802.  *
  803.  * Revision 1.1  2000/03/07 14:03:15  vasilche
  804.  * Added CObject class as base for reference counted objects.
  805.  * Added CRef templace for reference to CObject descendant.
  806.  *
  807.  * ===========================================================================
  808.  */