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