os/ossrv/genericopenlibs/cppstdlib/stl/test/eh/nc_alloc.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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