ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

nc_alloc.cpp
Go to the documentation of this file.
00001 /************************************************************************************************
00002  NC_ALLOC.CPP
00003 
00004  * Copyright (c) 1997
00005  * Mark of the Unicorn, Inc.
00006  *
00007  * Permission to use, copy, modify, distribute and sell this software
00008  * and its documentation for any purpose is hereby granted without fee,
00009  * provided that the above copyright notice appear in all copies and
00010  * that both that copyright notice and this permission notice appear
00011  * in supporting documentation.  Mark of the Unicorn makes no
00012  * representations about the suitability of this software for any
00013  * purpose.  It is provided "as is" without express or implied warranty.
00014 
00015 ************************************************************************************************/
00016 
00017 #include "nc_alloc.h"
00018 #include <string>
00019 
00020 #if defined (EH_NEW_HEADERS)
00021 #  include <new>
00022 #  include <cassert>
00023 #  include <cstdlib>
00024 #else
00025 #  include <assert.h>
00026 #  include <stdlib.h>
00027 #  include <new.h>
00028 #endif
00029 
00030 #if defined (EH_NEW_IOSTREAMS)
00031 #  include <iostream>
00032 #else
00033 #  include <iostream.h>
00034 #endif
00035 
00036 long alloc_count = 0;
00037 long object_count = 0;
00038 long TestController::possible_failure_count = 0;
00039 const char* TestController::current_test = "<unknown>";
00040 const char* TestController::current_test_category = "no category";
00041 const char* TestController::current_container = 0;
00042 bool  TestController::nc_verbose = true;
00043 bool  TestController::never_fail = false;
00044 bool  TestController::track_allocations = false;
00045 bool  TestController::leak_detection_enabled = false;
00046 TestController gTestController;
00047 
00048 //************************************************************************************************
00049 void TestController::maybe_fail(long) {
00050   if (never_fail || Failure_threshold() == kNotInExceptionTest)
00051     return;
00052 
00053   // throw if allocation would satisfy the threshold
00054   if (possible_failure_count++ >= Failure_threshold()) {
00055     // what about doing some standard new_handler() behavior here (to test it!) ???
00056 
00057     // reset and simulate an out-of-memory failure
00058     Failure_threshold() = kNotInExceptionTest;
00059 #ifndef EH_NO_EXCEPTIONS
00060     throw EH_STD::bad_alloc();
00061 #endif
00062   }
00063 }
00064 
00065 #if defined (EH_HASHED_CONTAINERS_IMPLEMENTED)
00066 #  if defined (__SGI_STL)
00067 #    if defined (EH_NEW_HEADERS)
00068 #      include <hash_set>
00069 #    else
00070 #      include <hash_set.h>
00071 #    endif
00072 #  elif defined (__MSL__)
00073 #    include <hashset.h>
00074 #  else
00075 #    error what do I include to get hash_set?
00076 #  endif
00077 #else
00078 #  if defined (EH_NEW_HEADERS)
00079 #    include <set>
00080 #  else
00081 #    include <set.h>
00082 #  endif
00083 #endif
00084 
00085 #if !defined (EH_HASHED_CONTAINERS_IMPLEMENTED)
00086 typedef EH_STD::set<void*, EH_STD::less<void*> > allocation_set;
00087 #else
00088 
00089 USING_CSTD_NAME(size_t)
00090 
00091 struct hash_void {
00092   size_t operator()(void* x) const { return (size_t)x; }
00093 };
00094 
00095 typedef EH_STD::hash_set<void*, ::hash_void, EH_STD::equal_to<void*> > allocation_set;
00096 #endif
00097 
00098 static allocation_set& alloc_set() {
00099   static allocation_set s;
00100   return s;
00101 }
00102 
00103 // Prevents infinite recursion during allocation
00104 static bool using_alloc_set = false;
00105 
00106 #if !defined (NO_FAST_ALLOCATOR)
00107 //
00108 //  FastAllocator -- speeds up construction of TestClass objects when
00109 // TESTCLASS_DEEP_DATA is enabled, and speeds up tracking of allocations
00110 // when the suite is run with the -t option.
00111 //
00112 class FastAllocator {
00113 public:
00114   //FastAllocator() : mFree(0), mUsed(0) {}
00115   static void *Allocate(size_t s) {
00116     void *result = 0;
00117 
00118     if (s <= sizeof(Block)) {
00119       if (mFree != 0) {
00120         result = mFree;
00121         mFree = mFree->next;
00122       }
00123       else if (mBlocks != 0 && mUsed < kBlockCount) {
00124         result =  (void*)&mBlocks[mUsed++];
00125       }
00126     }
00127     return result;
00128   }
00129 
00130   static bool Free(void* p) {
00131     Block* b = (Block*)p;
00132     if (mBlocks == 0 || b < mBlocks || b >= mBlocks + kBlockCount)
00133       return false;
00134     b->next = mFree;
00135     mFree = b;
00136     return true;
00137   }
00138 
00139   struct Block;
00140   friend struct Block;
00141 
00142   enum {
00143     // Number of fast allocation blocks to create.
00144     kBlockCount = 1500,
00145 
00146     // You may need to adjust this number for your platform.
00147     // A good choice will speed tests. A bad choice will still work.
00148     kMinBlockSize = 48
00149   };
00150 
00151   struct Block {
00152     union {
00153       Block *next;
00154       double dummy; // fbp - force alignment
00155       char dummy2[kMinBlockSize];
00156     };
00157   };
00158 
00159   static Block* mBlocks;
00160   static Block *mFree;
00161   static size_t mUsed;
00162 };
00163 
00164 FastAllocator::Block *FastAllocator::mBlocks =
00165 (FastAllocator::Block*)EH_CSTD::calloc( sizeof(FastAllocator::Block), FastAllocator::kBlockCount );
00166 FastAllocator::Block *FastAllocator::mFree;
00167 size_t FastAllocator::mUsed;
00168 
00169 
00170 static FastAllocator gFastAllocator;
00171 #endif
00172 
00173 inline char* AllocateBlock(size_t s) {
00174 #if !defined (NO_FAST_ALLOCATOR)
00175   char * const p = (char*)gFastAllocator.Allocate( s );
00176   if (p != 0)
00177     return p;
00178 #endif
00179 
00180   return (char*)EH_CSTD::malloc(s);
00181 }
00182 
00183 static void* OperatorNew( size_t s ) {
00184   if (!using_alloc_set) {
00185     simulate_possible_failure();
00186     ++alloc_count;
00187   }
00188 
00189   char *p = AllocateBlock(s);
00190 
00191   if (gTestController.TrackingEnabled() &&
00192       gTestController.LeakDetectionEnabled() &&
00193       !using_alloc_set) {
00194     using_alloc_set = true;
00195     bool inserted = alloc_set().insert(p).second;
00196     // Suppress warning about unused variable.
00197     inserted; 
00198     EH_ASSERT(inserted);
00199     using_alloc_set = false;
00200   }
00201 
00202   return p;
00203 }
00204 
00205 void* _STLP_CALL operator new(size_t s)
00206 #ifdef EH_DELETE_HAS_THROW_SPEC
00207 throw(EH_STD::bad_alloc)
00208 #endif
00209 { return OperatorNew( s ); }
00210 
00211 #ifdef EH_USE_NOTHROW
00212 void* _STLP_CALL operator new(size_t size, const EH_STD::nothrow_t&) throw() {
00213   try {
00214     return OperatorNew( size );
00215   }
00216   catch (...) {
00217     return 0;
00218   }
00219 }
00220 #endif
00221 
00222 #if 1 /* defined (EH_VECTOR_OPERATOR_NEW) */
00223 void* _STLP_CALL operator new[](size_t size ) throw(EH_STD::bad_alloc) {
00224   return OperatorNew( size );
00225 }
00226 
00227 #  ifdef EH_USE_NOTHROW
00228 void* _STLP_CALL operator new[](size_t size, const EH_STD::nothrow_t&) throw() {
00229   try {
00230     return OperatorNew(size);
00231   }
00232   catch (...) {
00233     return 0;
00234   }
00235 }
00236 #  endif
00237 
00238 void _STLP_CALL operator delete[](void* ptr) throw()
00239 { operator delete( ptr ); }
00240 #endif
00241 
00242 #if defined (EH_DELETE_HAS_THROW_SPEC)
00243 void _STLP_CALL operator delete(void* s) throw()
00244 #else
00245 void _STLP_CALL operator delete(void* s)
00246 #endif
00247 {
00248   if ( s != 0 ) {
00249     if ( !using_alloc_set ) {
00250       --alloc_count;
00251 
00252       if ( gTestController.TrackingEnabled() && gTestController.LeakDetectionEnabled() ) {
00253         using_alloc_set = true;
00254         allocation_set::iterator p = alloc_set().find( (char*)s );
00255         EH_ASSERT( p != alloc_set().end() );
00256         alloc_set().erase( p );
00257         using_alloc_set = false;
00258       }
00259     }
00260 # if ! defined (NO_FAST_ALLOCATOR)
00261     if ( !gFastAllocator.Free( s ) )
00262 # endif
00263       EH_CSTD::free(s);
00264   }
00265 }
00266 
00267 
00268 /*===================================================================================
00269   ClearAllocationSet  (private helper)
00270 
00271   EFFECTS:  Empty the set of allocated blocks.
00272 ====================================================================================*/
00273 void TestController::ClearAllocationSet() {
00274   if (!using_alloc_set) {
00275     using_alloc_set = true;
00276     alloc_set().clear();
00277     using_alloc_set = false;
00278   }
00279 }
00280 
00281 
00282 bool TestController::ReportLeaked() {
00283   EndLeakDetection();
00284 
00285   EH_ASSERT( !using_alloc_set || (alloc_count == static_cast<int>(alloc_set().size())) );
00286 
00287   if (alloc_count != 0 || object_count != 0) {
00288     EH_STD::cerr<<"\nEH TEST FAILURE !\n";
00289     PrintTestName(true);
00290     if (alloc_count)
00291       EH_STD::cerr << "ERROR : " << alloc_count << " outstanding allocations.\n";
00292     if (object_count)
00293       EH_STD::cerr << "ERROR : " << object_count << " non-destroyed objects.\n";
00294     alloc_count = object_count = 0;
00295     return true;
00296   }
00297   return false;
00298 }
00299 
00300 
00301 
00302 /*===================================================================================
00303   PrintTestName
00304 
00305   EFFECTS: Prints information about the current test. If err is false, ends with
00306     an ellipsis, because the test is ongoing. If err is true an error is being
00307     reported, and the output ends with an endl.
00308 ====================================================================================*/
00309 
00310 void TestController::PrintTestName(bool err) {
00311   if (current_container)
00312     EH_STD::cerr<<"["<<current_container<<"] :";
00313   EH_STD::cerr<<"testing "<<current_test <<" (" << current_test_category <<")";
00314   if (err)
00315     EH_STD::cerr<<EH_STD::endl;
00316   else
00317     EH_STD::cerr<<" ... ";
00318 }
00319 
00320 void TestController::ReportSuccess(int count) {
00321   if (nc_verbose)
00322     EH_STD::cerr<<(count+1)<<" try successful"<<EH_STD::endl;
00323 }
00324 
00325 long& TestController::Failure_threshold() {
00326   static long failure_threshold = kNotInExceptionTest;
00327   return failure_threshold;
00328 }

Generated on Sat May 26 2012 04:34:04 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.