home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / stlpt453.zip / STLport-4.5.3 / test / eh / nc_alloc.cpp < prev    next >
C/C++ Source or Header  |  2001-01-26  |  9KB  |  375 lines

  1. /************************************************************************************************
  2.  NC_ALLOC.CPP
  3.  
  4.  * Copyright (c) 1997
  5.  * Mark of the Unicorn, Inc.
  6.  *
  7.  * Permission to use, copy, modify, distribute and sell this software
  8.  * and its documentation for any purpose is hereby granted without fee,
  9.  * provided that the above copyright notice appear in all copies and
  10.  * that both that copyright notice and this permission notice appear
  11.  * in supporting documentation.  Mark of the Unicorn makes no
  12.  * representations about the suitability of this software for any
  13.  * purpose.  It is provided "as is" without express or implied warranty.
  14.  
  15. ************************************************************************************************/
  16.  
  17. #include "nc_alloc.h"
  18. #include <string>
  19.  
  20. #if defined (EH_NEW_HEADERS)
  21. # include <new>
  22. # include <cassert>
  23. # include <cstdlib>
  24. #else
  25. # include <assert.h>
  26. # include <stdlib.h>
  27. # include <new.h>
  28. #endif
  29.  
  30. #if defined (EH_NEW_IOSTREAMS)
  31. # include <iostream>
  32. #else
  33. # include <iostream.h>
  34. #endif
  35.  
  36. long alloc_count = 0;
  37. long object_count = 0;
  38. long TestController::possible_failure_count = 0;
  39. const char* TestController::current_test = "<unknown>";
  40. const char* TestController::current_test_category = "no category";
  41. const char* TestController::current_container = 0;
  42. bool  TestController::nc_verbose = true;
  43. bool  TestController::never_fail = false;
  44. bool  TestController::track_allocations = false;
  45. bool  TestController::leak_detection_enabled = false;
  46. TestController gTestController;
  47.  
  48. //************************************************************************************************
  49. void TestController::maybe_fail(long)
  50. {
  51.     if ( never_fail || Failure_threshold() == kNotInExceptionTest )
  52.         return;
  53.  
  54.     // throw if allocation would satisfy the threshold
  55.     if ( possible_failure_count++ >= Failure_threshold() )
  56.     {
  57.  
  58.         // what about doing some standard new_handler() behavior here (to test it!) ???
  59.  
  60.         // reset and simulate an out-of-memory failure
  61.         Failure_threshold() = kNotInExceptionTest;
  62. # ifndef EH_NO_EXCEPTIONS
  63.         throw EH_STD::bad_alloc();
  64. # endif
  65.     }
  66. }
  67.  
  68. # if defined( EH_HASHED_CONTAINERS_IMPLEMENTED )
  69.  
  70. #  if defined (__SGI_STL )
  71.  
  72. #   if defined (EH_NEW_HEADERS)
  73. #    include <hash_set>
  74. #   else
  75. #    include <hash_set.h>
  76. #   endif
  77. #  elif defined (__MSL__)
  78. #   include <hashset.h>
  79. #  else
  80. #   error what do I include to get hash_set?
  81. #  endif
  82.  
  83. # else
  84.  
  85. #  if defined (EH_NEW_HEADERS)
  86. #   include <set>
  87. #  else
  88. #  include <set.h>
  89. #  endif
  90. # endif
  91.  
  92. # if !defined( EH_HASHED_CONTAINERS_IMPLEMENTED )
  93. typedef EH_STD::set<void*, EH_STD::less<void*> > allocation_set;
  94. #else
  95.  
  96. USING_CSTD_NAME(size_t)
  97.  
  98. struct hash_void
  99. {
  100.   size_t operator()(void* x) const { return (size_t)x; }
  101. };
  102.  
  103. typedef std::hash_set<void*, ::hash_void, std::equal_to<void*> > allocation_set;
  104. # endif
  105.  
  106. static allocation_set& alloc_set()
  107. {
  108.     static allocation_set s;
  109.     return s;
  110. }
  111.  
  112. // Prevents infinite recursion during allocation
  113. static bool using_alloc_set = false;
  114.  
  115. # if !defined (NO_FAST_ALLOCATOR)
  116. //
  117. //    FastAllocator -- speeds up construction of TestClass objects when
  118. // TESTCLASS_DEEP_DATA is enabled, and speeds up tracking of allocations
  119. // when the suite is run with the -t option.
  120. //
  121. class FastAllocator
  122. {
  123. public:
  124. //    FastAllocator() : mFree(0), mUsed(0) {}
  125.     
  126.     static void *Allocate( size_t s )
  127.     {
  128.       void *result = 0;
  129.  
  130.         if ( s <= sizeof( Block ) )
  131.         {
  132.             if ( mFree != 0 )
  133.             {
  134.                 result = mFree;
  135.                 mFree = mFree->next;
  136.             }
  137.             else if ( mBlocks != 0 && mUsed < kBlockCount )
  138.             {
  139.                 result =  (void*)&mBlocks[mUsed++];
  140.             }
  141.         }
  142.          return result;
  143.     }
  144.     
  145.     static bool Free( void* p )
  146.     {
  147.         Block* b = (Block*)p;
  148.         if ( mBlocks == 0 || b < mBlocks || b >= mBlocks + kBlockCount )
  149.             return false;
  150.         b->next = mFree;
  151.         mFree = b;
  152.         return true;
  153.     }
  154.     
  155.     struct Block;
  156.     friend struct Block;
  157.     
  158.     enum
  159.     {
  160.         // Number of fast allocation blocks to create.
  161.         kBlockCount = 1500,
  162.         
  163.         // You may need to adjust this number for your platform.
  164.         // A good choice will speed tests. A bad choice will still work.
  165.         kMinBlockSize = 48
  166.     };
  167.     
  168.     struct Block
  169.     {
  170.         union { 
  171.                     Block *next;
  172.                     double dummy; // fbp - force alignment
  173.                     char dummy2[kMinBlockSize];
  174.                 };
  175.     };
  176.     
  177.     static Block* mBlocks;
  178.     static Block *mFree;
  179.     static size_t mUsed;
  180. };
  181.  
  182. FastAllocator::Block *FastAllocator::mBlocks = 
  183. (FastAllocator::Block*)EH_CSTD::calloc( sizeof(FastAllocator::Block), FastAllocator::kBlockCount );
  184. FastAllocator::Block *FastAllocator::mFree;
  185. size_t FastAllocator::mUsed;
  186.  
  187.  
  188. static FastAllocator gFastAllocator;
  189. # endif
  190.  
  191. inline char* AllocateBlock( size_t s )
  192. {
  193. # if !defined (NO_FAST_ALLOCATOR)    
  194.     char * const p = (char*)gFastAllocator.Allocate( s );
  195.     if ( p != 0 )
  196.         return p;
  197. # endif    
  198.  
  199.     return (char*)EH_CSTD::malloc(s);
  200. }
  201.  
  202. static void* OperatorNew( size_t s )
  203. {
  204.     if ( !using_alloc_set )
  205.     {
  206.         simulate_possible_failure();
  207.         alloc_count++;
  208.     }
  209.     
  210.     char *p = AllocateBlock(s);
  211.     
  212.     if ( gTestController.TrackingEnabled()
  213.         && gTestController.LeakDetectionEnabled()
  214.         && !using_alloc_set )
  215.     {
  216.         using_alloc_set = true;
  217.         EH_ASSERT( alloc_set().find( p ) == alloc_set().end() );
  218.         alloc_set().insert( p );
  219.         using_alloc_set = false;
  220.     }
  221.  
  222.     return p;
  223. }
  224.  
  225. void* _STLP_CALL operator new(size_t s) 
  226. #ifdef EH_DELETE_HAS_THROW_SPEC
  227. throw(EH_STD::bad_alloc)
  228. #endif
  229. {
  230.     return OperatorNew( s );
  231. }
  232.  
  233. #ifdef EH_USE_NOTHROW
  234. void* _STLP_CALL operator new(size_t size, const EH_STD::nothrow_t&) throw()
  235. {
  236.     try
  237.     {
  238.         return OperatorNew( size );
  239.     }
  240.     catch(...)
  241.     {
  242.         return 0;
  243.     }
  244. }
  245. #endif
  246.  
  247. # if defined (EH_VECTOR_OPERATOR_NEW)
  248. void* _STLP_CALL operator new[](size_t size ) throw(EH_STD::bad_alloc)
  249. {
  250.     return OperatorNew( size );
  251. }
  252.  
  253. #ifdef EH_USE_NOTHROW
  254. void* _STLP_CALL operator new[](size_t size, const EH_STD::nothrow_t&) throw()
  255. {
  256.     try
  257.     {
  258.         return OperatorNew( size );
  259.     }
  260.     catch(...)
  261.     {
  262.         return 0;
  263.     }
  264. }
  265. #endif
  266.  
  267. void _STLP_CALL operator delete[](void* ptr) throw()
  268. {
  269.     operator delete( ptr );
  270. }
  271. # endif
  272.  
  273. # if defined (EH_DELETE_HAS_THROW_SPEC)
  274. void _STLP_CALL operator delete(void* s) throw()
  275. # else
  276. void _STLP_CALL operator delete(void* s)
  277. # endif
  278. {
  279.     if ( s != 0 )
  280.     {
  281.         if ( !using_alloc_set )
  282.         {
  283.             alloc_count--;
  284.  
  285.             if ( gTestController.TrackingEnabled() && gTestController.LeakDetectionEnabled() )
  286.             {
  287.                 using_alloc_set = true;
  288.                 allocation_set::iterator p = alloc_set().find( (char*)s );
  289.                 EH_ASSERT( p != alloc_set().end() );
  290.                 alloc_set().erase( p );
  291.                 using_alloc_set = false;
  292.             }
  293.         }
  294. # if ! defined (NO_FAST_ALLOCATOR)    
  295.         if ( !gFastAllocator.Free( s ) )
  296. # endif   
  297.             EH_CSTD::free(s);
  298.     }
  299. }
  300.  
  301.  
  302. /*===================================================================================
  303.     ClearAllocationSet  (private helper)
  304.  
  305.     EFFECTS:  Empty the set of allocated blocks.
  306. ====================================================================================*/
  307. void TestController::ClearAllocationSet()
  308. {
  309.     if ( !using_alloc_set )
  310.     {
  311.         using_alloc_set = true;
  312.         alloc_set().clear();
  313.         using_alloc_set = false;
  314.     }
  315. }
  316.  
  317.  
  318. bool TestController::ReportLeaked()
  319. {
  320.  
  321.   EndLeakDetection();
  322.     
  323.   if (using_alloc_set)
  324.       EH_ASSERT( alloc_count == static_cast<int>(alloc_set().size()) );
  325.  
  326.     if ( alloc_count!=0 || object_count!=0 )
  327.     {
  328.         EH_STD::cerr<<"\nEH TEST FAILURE !\n";
  329.         PrintTestName(true);
  330.         if (alloc_count)
  331.             EH_STD::cerr<<"ERROR : "<<alloc_count<<" outstanding allocations.\n";
  332.         if (object_count)
  333.           EH_STD::cerr<<"ERROR : "<<object_count<<" non-destroyed objects.\n";
  334.     alloc_count = object_count = 0;
  335.  
  336.     return true;
  337.  
  338.     }
  339.     return false;
  340.  
  341. }
  342.  
  343.  
  344.  
  345. /*===================================================================================
  346.     PrintTestName
  347.  
  348.     EFFECTS: Prints information about the current test. If err is false, ends with
  349.         an ellipsis, because the test is ongoing. If err is true an error is being
  350.         reported, and the output ends with an endl.
  351. ====================================================================================*/
  352.  
  353. void
  354. TestController::PrintTestName(bool err) {
  355.     if (current_container)
  356.         EH_STD::cerr<<"["<<current_container<<"] :";
  357.     EH_STD::cerr<<"testing "<<current_test <<" (" << current_test_category <<")";
  358.     if (err)
  359.         EH_STD::cerr<<EH_STD::endl;
  360.     else
  361.         EH_STD::cerr<<" ... ";
  362. }
  363.  
  364. void TestController::ReportSuccess(int count) {
  365.     if (nc_verbose)
  366.         EH_STD::cerr<<(count+1)<<" try successful"<<EH_STD::endl;
  367. }
  368.  
  369. long& TestController::Failure_threshold()
  370. {
  371.     static long failure_threshold = kNotInExceptionTest;
  372.     return failure_threshold;
  373. }
  374.  
  375.