nc_alloc.cpp

来自「stl的源码」· C++ 代码 · 共 329 行

CPP
329
字号
/************************************************************************************************ NC_ALLOC.CPP * Copyright (c) 1997 * Mark of the Unicorn, Inc. * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation.  Mark of the Unicorn makes no * representations about the suitability of this software for any * purpose.  It is provided "as is" without express or implied warranty.************************************************************************************************/#include "nc_alloc.h"#include <string>#if defined (EH_NEW_HEADERS)#  include <new>#  include <cassert>#  include <cstdlib>#else#  include <assert.h>#  include <stdlib.h>#  include <new.h>#endif#if defined (EH_NEW_IOSTREAMS)#  include <iostream>#else#  include <iostream.h>#endiflong alloc_count = 0;long object_count = 0;long TestController::possible_failure_count = 0;const char* TestController::current_test = "<unknown>";const char* TestController::current_test_category = "no category";const char* TestController::current_container = 0;bool  TestController::nc_verbose = true;bool  TestController::never_fail = false;bool  TestController::track_allocations = false;bool  TestController::leak_detection_enabled = false;TestController gTestController;//************************************************************************************************void TestController::maybe_fail(long) {  if (never_fail || Failure_threshold() == kNotInExceptionTest)    return;  // throw if allocation would satisfy the threshold  if (possible_failure_count++ >= Failure_threshold()) {    // what about doing some standard new_handler() behavior here (to test it!) ???    // reset and simulate an out-of-memory failure    Failure_threshold() = kNotInExceptionTest;#ifndef EH_NO_EXCEPTIONS    throw EH_STD::bad_alloc();#endif  }}#if defined (EH_HASHED_CONTAINERS_IMPLEMENTED)#  if defined (__SGI_STL)#    if defined (EH_NEW_HEADERS)#      include <hash_set>#    else#      include <hash_set.h>#    endif#  elif defined (__MSL__)#    include <hashset.h>#  else#    error what do I include to get hash_set?#  endif#else#  if defined (EH_NEW_HEADERS)#    include <set>#  else#    include <set.h>#  endif#endif#if !defined (EH_HASHED_CONTAINERS_IMPLEMENTED)typedef EH_STD::set<void*, EH_STD::less<void*> > allocation_set;#elseUSING_CSTD_NAME(size_t)struct hash_void {  size_t operator()(void* x) const { return (size_t)x; }};typedef EH_STD::hash_set<void*, ::hash_void, EH_STD::equal_to<void*> > allocation_set;#endifstatic allocation_set& alloc_set() {  static allocation_set s;  return s;}// Prevents infinite recursion during allocationstatic bool using_alloc_set = false;#if !defined (NO_FAST_ALLOCATOR)////  FastAllocator -- speeds up construction of TestClass objects when// TESTCLASS_DEEP_DATA is enabled, and speeds up tracking of allocations// when the suite is run with the -t option.//class FastAllocator {public:  //FastAllocator() : mFree(0), mUsed(0) {}  static void *Allocate(size_t s) {    void *result = 0;    if (s <= sizeof(Block)) {      if (mFree != 0) {        result = mFree;        mFree = mFree->next;      }      else if (mBlocks != 0 && mUsed < kBlockCount) {        result =  (void*)&mBlocks[mUsed++];      }    }    return result;  }  static bool Free(void* p) {    Block* b = (Block*)p;    if (mBlocks == 0 || b < mBlocks || b >= mBlocks + kBlockCount)      return false;    b->next = mFree;    mFree = b;    return true;  }  struct Block;  friend struct Block;  enum {    // Number of fast allocation blocks to create.    kBlockCount = 1500,    // You may need to adjust this number for your platform.    // A good choice will speed tests. A bad choice will still work.    kMinBlockSize = 48  };  struct Block {    union {      Block *next;      double dummy; // fbp - force alignment      char dummy2[kMinBlockSize];    };  };  static Block* mBlocks;  static Block *mFree;  static size_t mUsed;};FastAllocator::Block *FastAllocator::mBlocks =(FastAllocator::Block*)EH_CSTD::calloc( sizeof(FastAllocator::Block), FastAllocator::kBlockCount );FastAllocator::Block *FastAllocator::mFree;size_t FastAllocator::mUsed;static FastAllocator gFastAllocator;#endifinline char* AllocateBlock(size_t s) {#if !defined (NO_FAST_ALLOCATOR)  char * const p = (char*)gFastAllocator.Allocate( s );  if (p != 0)    return p;#endif  return (char*)EH_CSTD::malloc(s);}static void* OperatorNew( size_t s ) {  if (!using_alloc_set) {    simulate_possible_failure();    ++alloc_count;  }  char *p = AllocateBlock(s);  if (gTestController.TrackingEnabled() &&      gTestController.LeakDetectionEnabled() &&      !using_alloc_set) {    using_alloc_set = true;    bool inserted = alloc_set().insert(p).second;    // Suppress warning about unused variable.    inserted;     EH_ASSERT(inserted);    using_alloc_set = false;  }  return p;}void* _STLP_CALL operator new(size_t s)#ifdef EH_DELETE_HAS_THROW_SPECthrow(EH_STD::bad_alloc)#endif{ return OperatorNew( s ); }#ifdef EH_USE_NOTHROWvoid* _STLP_CALL operator new(size_t size, const EH_STD::nothrow_t&) throw() {  try {    return OperatorNew( size );  }  catch (...) {    return 0;  }}#endif#if 1 /* defined (EH_VECTOR_OPERATOR_NEW) */void* _STLP_CALL operator new[](size_t size ) throw(EH_STD::bad_alloc) {  return OperatorNew( size );}#  ifdef EH_USE_NOTHROWvoid* _STLP_CALL operator new[](size_t size, const EH_STD::nothrow_t&) throw() {  try {    return OperatorNew(size);  }  catch (...) {    return 0;  }}#  endifvoid _STLP_CALL operator delete[](void* ptr) throw(){ operator delete( ptr ); }#endif#if defined (EH_DELETE_HAS_THROW_SPEC)void _STLP_CALL operator delete(void* s) throw()#elsevoid _STLP_CALL operator delete(void* s)#endif{  if ( s != 0 ) {    if ( !using_alloc_set ) {      --alloc_count;      if ( gTestController.TrackingEnabled() && gTestController.LeakDetectionEnabled() ) {        using_alloc_set = true;        allocation_set::iterator p = alloc_set().find( (char*)s );        EH_ASSERT( p != alloc_set().end() );        alloc_set().erase( p );        using_alloc_set = false;      }    }# if ! defined (NO_FAST_ALLOCATOR)    if ( !gFastAllocator.Free( s ) )# endif      EH_CSTD::free(s);  }}/*===================================================================================  ClearAllocationSet  (private helper)  EFFECTS:  Empty the set of allocated blocks.====================================================================================*/void TestController::ClearAllocationSet() {  if (!using_alloc_set) {    using_alloc_set = true;    alloc_set().clear();    using_alloc_set = false;  }}bool TestController::ReportLeaked() {  EndLeakDetection();  EH_ASSERT( !using_alloc_set || (alloc_count == static_cast<int>(alloc_set().size())) );  if (alloc_count != 0 || object_count != 0) {    EH_STD::cerr<<"\nEH TEST FAILURE !\n";    PrintTestName(true);    if (alloc_count)      EH_STD::cerr << "ERROR : " << alloc_count << " outstanding allocations.\n";    if (object_count)      EH_STD::cerr << "ERROR : " << object_count << " non-destroyed objects.\n";    alloc_count = object_count = 0;    return true;  }  return false;}/*===================================================================================  PrintTestName  EFFECTS: Prints information about the current test. If err is false, ends with    an ellipsis, because the test is ongoing. If err is true an error is being    reported, and the output ends with an endl.====================================================================================*/void TestController::PrintTestName(bool err) {  if (current_container)    EH_STD::cerr<<"["<<current_container<<"] :";  EH_STD::cerr<<"testing "<<current_test <<" (" << current_test_category <<")";  if (err)    EH_STD::cerr<<EH_STD::endl;  else    EH_STD::cerr<<" ... ";}void TestController::ReportSuccess(int count) {  if (nc_verbose)    EH_STD::cerr<<(count+1)<<" try successful"<<EH_STD::endl;}long& TestController::Failure_threshold() {  static long failure_threshold = kNotInExceptionTest;  return failure_threshold;}

⌨️ 快捷键说明

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