Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygennc_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
1.7.6.1
|