diff -r 000000000000 -r e4d67989cc36 genericopenlibs/cppstdlib/stl/test/eh/nc_alloc.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/genericopenlibs/cppstdlib/stl/test/eh/nc_alloc.cpp Tue Feb 02 02:01:42 2010 +0200 @@ -0,0 +1,386 @@ +/************************************************************************************************ + NC_ALLOC.CPP + + * Portions Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. + * + * Copyright (c) 1997 + * Mark of the Unicorn, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Mark of the Unicorn makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + +************************************************************************************************/ + +#include "nc_alloc.h" +#include + +#if defined (EH_NEW_HEADERS) +# include +# include +# include +#else +# include +# include +# include +#endif + +#if defined (EH_NEW_IOSTREAMS) +# include +#else +# include +#endif + +long alloc_count = 0; +long object_count = 0; +long TestController::possible_failure_count = 0; +const char* TestController::current_test = ""; +const char* TestController::current_test_category = "no category"; +const char* TestController::current_container = 0; +bool TestController::nc_verbose = true; +bool TestController::never_fail = false; +bool TestController::track_allocations = false; +bool TestController::leak_detection_enabled = false; + +TestController gTestController; + +//************************************************************************************************ +void TestController::maybe_fail(long) { + if (never_fail || Failure_threshold() == kNotInExceptionTest) + return; + + // throw if allocation would satisfy the threshold + if (possible_failure_count++ >= Failure_threshold()) { + // what about doing some standard new_handler() behavior here (to test it!) ??? + + // reset and simulate an out-of-memory failure + Failure_threshold() = kNotInExceptionTest; +#ifndef EH_NO_EXCEPTIONS + throw EH_STD::bad_alloc(); +#endif + } +} + +#if defined (EH_HASHED_CONTAINERS_IMPLEMENTED) +# if defined (__SGI_STL) +# if defined (EH_NEW_HEADERS) +# include +# else +# include +# endif +# elif defined (__MSL__) +# include +# else +# error what do I include to get hash_set? +# endif +#else +# if defined (EH_NEW_HEADERS) +# include +# else +# include +# endif +#endif + +#if !defined (EH_HASHED_CONTAINERS_IMPLEMENTED) +typedef EH_STD::set > allocation_set; +#else + +USING_CSTD_NAME(size_t) + +struct hash_void { + size_t operator()(void* x) const { return (size_t)x; } +}; + +typedef EH_STD::hash_set > allocation_set; +#endif + +static allocation_set& alloc_set() { + static allocation_set s; + return s; +} + +// Prevents infinite recursion during allocation +static bool using_alloc_set = false; + +#if !defined (NO_FAST_ALLOCATOR) +// +// FastAllocator -- speeds up construction of TestClass objects when +// TESTCLASS_DEEP_DATA is enabled, and speeds up tracking of allocations +// when the suite is run with the -t option. +// +class FastAllocator { +public: + //FastAllocator() : mFree(0), mUsed(0) {} + static void *Allocate(size_t s) { + void *result = 0; + + if (s <= sizeof(Block)) { + if (mFree != 0) { + result = mFree; + mFree = mFree->next; + } + else if (mBlocks != 0 && mUsed < kBlockCount) { + result = (void*)&mBlocks[mUsed++]; + } + } + return result; + } + + static bool Free(void* p) { + Block* b = (Block*)p; + if (mBlocks == 0 || b < mBlocks || b >= mBlocks + kBlockCount) + return false; + b->next = mFree; + mFree = b; + return true; + } + + struct Block; + friend struct Block; + + enum { + // Number of fast allocation blocks to create. + kBlockCount = 1500, + + // You may need to adjust this number for your platform. + // A good choice will speed tests. A bad choice will still work. + kMinBlockSize = 48 + }; + + struct Block { + union { + Block *next; + double dummy; // fbp - force alignment + char dummy2[kMinBlockSize]; + }; + }; + + static Block* mBlocks; + static Block *mFree; + static size_t mUsed; +}; + +FastAllocator::Block *FastAllocator::mBlocks = +(FastAllocator::Block*)EH_CSTD::calloc( sizeof(FastAllocator::Block), FastAllocator::kBlockCount ); +FastAllocator::Block *FastAllocator::mFree; +size_t FastAllocator::mUsed; + + +static FastAllocator gFastAllocator; +#endif + +inline char* AllocateBlock(size_t s) { +#if !defined (NO_FAST_ALLOCATOR) + char * const p = (char*)gFastAllocator.Allocate( s ); + if (p != 0) + return p; +#endif + + return (char*)EH_CSTD::malloc(s); +} + +static void* OperatorNew( size_t s ) { + if (!using_alloc_set) { + simulate_possible_failure(); + ++alloc_count; + } + + char *p = AllocateBlock(s); + + if (gTestController.TrackingEnabled() && + gTestController.LeakDetectionEnabled() && + !using_alloc_set) { + using_alloc_set = true; + bool inserted = alloc_set().insert(p).second; + EH_ASSERT(inserted); + using_alloc_set = false; + } + + return p; +} +#if 0 //sandeep +void* _STLP_CALL operator new(size_t s) +#ifdef EH_DELETE_HAS_THROW_SPEC +throw(EH_STD::bad_alloc) +#endif +{ return OperatorNew( s ); } + +#ifdef EH_USE_NOTHROW +void* _STLP_CALL operator new(size_t size, const EH_STD::nothrow_t&) throw() { + try { + return OperatorNew( size ); + } + catch (...) { + return 0; + } +} +#endif + +#if defined (EH_VECTOR_OPERATOR_NEW) +void* _STLP_CALL operator new[](size_t size ) throw(EH_STD::bad_alloc) { + return OperatorNew( size ); +} + +# ifdef EH_USE_NOTHROW +void* _STLP_CALL operator new[](size_t size, const EH_STD::nothrow_t&) throw() { + try { + return OperatorNew(size); + } + catch (...) { + return 0; + } +} +# endif + +void _STLP_CALL operator delete[](void* ptr) throw() +{ operator delete( ptr ); } +#endif + +#if defined (EH_DELETE_HAS_THROW_SPEC) +void _STLP_CALL operator delete(void* s) throw() +#else +void _STLP_CALL operator delete(void* s) +#endif +{ + if ( s != 0 ) { + if ( !using_alloc_set ) { + --alloc_count; + + if ( gTestController.TrackingEnabled() && gTestController.LeakDetectionEnabled() ) { + using_alloc_set = true; + allocation_set::iterator p = alloc_set().find( (char*)s ); + EH_ASSERT( p != alloc_set().end() ); + alloc_set().erase( p ); + using_alloc_set = false; + } + } +# if ! defined (NO_FAST_ALLOCATOR) + if ( !gFastAllocator.Free( s ) ) +# endif + EH_CSTD::free(s); + } +} +#endif //sandeep + + +/*=================================================================================== + ClearAllocationSet (private helper) + + EFFECTS: Empty the set of allocated blocks. +====================================================================================*/ +void TestController::ClearAllocationSet() { + if (!using_alloc_set) { + using_alloc_set = true; + alloc_set().clear(); + using_alloc_set = false; + } +} + + +bool TestController::ReportLeaked() { + EndLeakDetection(); + + if (using_alloc_set) + EH_ASSERT( alloc_count == static_cast(alloc_set().size()) ); + + if (alloc_count != 0 || object_count != 0) { + EH_STD::cerr<<"\nEH TEST FAILURE !\n"; + PrintTestName(true); + if (alloc_count) + EH_STD::cerr << "ERROR : " << alloc_count << " outstanding allocations.\n"; + if (object_count) + EH_STD::cerr << "ERROR : " << object_count << " non-destroyed objects.\n"; + alloc_count = object_count = 0; + return true; + } + return false; +} + + + +/*=================================================================================== + PrintTestName + + EFFECTS: Prints information about the current test. If err is false, ends with + an ellipsis, because the test is ongoing. If err is true an error is being + reported, and the output ends with an endl. +====================================================================================*/ + +void TestController::PrintTestName(bool err) { + if (current_container) + EH_STD::cerr<<"["<