genericopenlibs/cppstdlib/stl/test/eh/nc_alloc.cpp
changeset 0 e4d67989cc36
--- /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 <string>
+
+#if defined (EH_NEW_HEADERS)
+#  include <new>
+#  include <cassert>
+#  include <cstdlib>
+#else
+#  include <assert.h>
+#  include <stdlib.h>
+#  include <new.h>
+#endif
+
+#if defined (EH_NEW_IOSTREAMS)
+#  include <iostream>
+#else
+#  include <iostream.h>
+#endif
+
+long alloc_count = 0;
+long object_count = 0;
+long TestController::possible_failure_count = 0;
+const char* TestController::current_test = "<unknown>";
+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 <hash_set>
+#    else
+#      include <hash_set.h>
+#    endif
+#  elif defined (__MSL__)
+#    include <hashset.h>
+#  else
+#    error what do I include to get hash_set?
+#  endif
+#else
+#  if defined (EH_NEW_HEADERS)
+#    include <set>
+#  else
+#    include <set.h>
+#  endif
+#endif
+
+#if !defined (EH_HASHED_CONTAINERS_IMPLEMENTED)
+typedef EH_STD::set<void*, EH_STD::less<void*> > 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<void*, ::hash_void, EH_STD::equal_to<void*> > 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<int>(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<<"["<<current_container<<"] :";
+  EH_STD::cerr<<"testing "<<current_test <<" (" << current_test_category <<")";
+  if (err)
+    EH_STD::cerr<<EH_STD::endl;
+  else
+    EH_STD::cerr<<" ... ";
+}
+
+void TestController::ReportSuccess(int count) {
+  if (nc_verbose)
+    EH_STD::cerr<<(count+1)<<" try successful"<<EH_STD::endl;
+}
+
+long& TestController::Failure_threshold() {
+  static long failure_threshold = kNotInExceptionTest;
+  return failure_threshold;
+}
+#if 0 // enable non inline functions
+void TestController::TrackAllocations(bool track) {
+  track_allocations = track;
+}
+
+bool TestController::TrackingEnabled() {
+  return track_allocations;
+}
+
+ void TestController::SetFailureCountdown(long count) {
+  Failure_threshold() = count;
+  possible_failure_count = 0;
+}
+
+void TestController::CancelFailureCountdown() {
+  Failure_threshold() = kNotInExceptionTest;
+}
+
+void TestController::BeginLeakDetection() {
+  alloc_count = 0;
+  object_count = 0;
+  ClearAllocationSet();
+  leak_detection_enabled = true;
+}
+
+bool TestController::LeakDetectionEnabled() {
+  return leak_detection_enabled;
+}
+
+void TestController::EndLeakDetection() {
+  leak_detection_enabled = false;
+}
+
+void TestController::SetCurrentTestCategory(const char* str) {
+  current_test_category = str;
+  if (nc_verbose)
+    PrintTestName();
+}
+
+void TestController::SetCurrentContainer(const char* str) {
+  current_container=str;
+}
+
+void TestController::SetCurrentTestName(const char* str) {
+  current_test = str;
+}
+
+void TestController::SetVerbose(bool val) {
+  nc_verbose = val;
+}
+
+void TestController::TurnOffExceptions() {
+  never_fail = true;
+}
+#endif