os/ossrv/genericopenlibs/cppstdlib/stl/test/eh/nc_alloc.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/************************************************************************************************
sl@0
     2
 NC_ALLOC.CPP
sl@0
     3
sl@0
     4
 * Portions Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
sl@0
     5
 *
sl@0
     6
 * Copyright (c) 1997
sl@0
     7
 * Mark of the Unicorn, Inc.
sl@0
     8
 *
sl@0
     9
 * Permission to use, copy, modify, distribute and sell this software
sl@0
    10
 * and its documentation for any purpose is hereby granted without fee,
sl@0
    11
 * provided that the above copyright notice appear in all copies and
sl@0
    12
 * that both that copyright notice and this permission notice appear
sl@0
    13
 * in supporting documentation.  Mark of the Unicorn makes no
sl@0
    14
 * representations about the suitability of this software for any
sl@0
    15
 * purpose.  It is provided "as is" without express or implied warranty.
sl@0
    16
sl@0
    17
************************************************************************************************/
sl@0
    18
sl@0
    19
#include "nc_alloc.h"
sl@0
    20
#include <string>
sl@0
    21
sl@0
    22
#if defined (EH_NEW_HEADERS)
sl@0
    23
#  include <new>
sl@0
    24
#  include <cassert>
sl@0
    25
#  include <cstdlib>
sl@0
    26
#else
sl@0
    27
#  include <assert.h>
sl@0
    28
#  include <stdlib.h>
sl@0
    29
#  include <new.h>
sl@0
    30
#endif
sl@0
    31
sl@0
    32
#if defined (EH_NEW_IOSTREAMS)
sl@0
    33
#  include <iostream>
sl@0
    34
#else
sl@0
    35
#  include <iostream.h>
sl@0
    36
#endif
sl@0
    37
sl@0
    38
long alloc_count = 0;
sl@0
    39
long object_count = 0;
sl@0
    40
long TestController::possible_failure_count = 0;
sl@0
    41
const char* TestController::current_test = "<unknown>";
sl@0
    42
const char* TestController::current_test_category = "no category";
sl@0
    43
const char* TestController::current_container = 0;
sl@0
    44
bool  TestController::nc_verbose = true;
sl@0
    45
bool  TestController::never_fail = false;
sl@0
    46
bool  TestController::track_allocations = false;
sl@0
    47
bool  TestController::leak_detection_enabled = false;
sl@0
    48
sl@0
    49
TestController gTestController;
sl@0
    50
sl@0
    51
//************************************************************************************************
sl@0
    52
void TestController::maybe_fail(long) {
sl@0
    53
  if (never_fail || Failure_threshold() == kNotInExceptionTest)
sl@0
    54
    return;
sl@0
    55
sl@0
    56
  // throw if allocation would satisfy the threshold
sl@0
    57
  if (possible_failure_count++ >= Failure_threshold()) {
sl@0
    58
    // what about doing some standard new_handler() behavior here (to test it!) ???
sl@0
    59
sl@0
    60
    // reset and simulate an out-of-memory failure
sl@0
    61
    Failure_threshold() = kNotInExceptionTest;
sl@0
    62
#ifndef EH_NO_EXCEPTIONS
sl@0
    63
    throw EH_STD::bad_alloc();
sl@0
    64
#endif
sl@0
    65
  }
sl@0
    66
}
sl@0
    67
sl@0
    68
#if defined (EH_HASHED_CONTAINERS_IMPLEMENTED)
sl@0
    69
#  if defined (__SGI_STL)
sl@0
    70
#    if defined (EH_NEW_HEADERS)
sl@0
    71
#      include <hash_set>
sl@0
    72
#    else
sl@0
    73
#      include <hash_set.h>
sl@0
    74
#    endif
sl@0
    75
#  elif defined (__MSL__)
sl@0
    76
#    include <hashset.h>
sl@0
    77
#  else
sl@0
    78
#    error what do I include to get hash_set?
sl@0
    79
#  endif
sl@0
    80
#else
sl@0
    81
#  if defined (EH_NEW_HEADERS)
sl@0
    82
#    include <set>
sl@0
    83
#  else
sl@0
    84
#    include <set.h>
sl@0
    85
#  endif
sl@0
    86
#endif
sl@0
    87
sl@0
    88
#if !defined (EH_HASHED_CONTAINERS_IMPLEMENTED)
sl@0
    89
typedef EH_STD::set<void*, EH_STD::less<void*> > allocation_set;
sl@0
    90
#else
sl@0
    91
sl@0
    92
USING_CSTD_NAME(size_t)
sl@0
    93
sl@0
    94
struct hash_void {
sl@0
    95
  size_t operator()(void* x) const { return (size_t)x; }
sl@0
    96
};
sl@0
    97
sl@0
    98
typedef EH_STD::hash_set<void*, ::hash_void, EH_STD::equal_to<void*> > allocation_set;
sl@0
    99
#endif
sl@0
   100
sl@0
   101
static allocation_set& alloc_set() {
sl@0
   102
  static allocation_set s;
sl@0
   103
  return s;
sl@0
   104
}
sl@0
   105
sl@0
   106
// Prevents infinite recursion during allocation
sl@0
   107
static bool using_alloc_set = false;
sl@0
   108
sl@0
   109
#if !defined (NO_FAST_ALLOCATOR)
sl@0
   110
//
sl@0
   111
//  FastAllocator -- speeds up construction of TestClass objects when
sl@0
   112
// TESTCLASS_DEEP_DATA is enabled, and speeds up tracking of allocations
sl@0
   113
// when the suite is run with the -t option.
sl@0
   114
//
sl@0
   115
class FastAllocator {
sl@0
   116
public:
sl@0
   117
  //FastAllocator() : mFree(0), mUsed(0) {}
sl@0
   118
  static void *Allocate(size_t s) {
sl@0
   119
    void *result = 0;
sl@0
   120
sl@0
   121
    if (s <= sizeof(Block)) {
sl@0
   122
      if (mFree != 0) {
sl@0
   123
        result = mFree;
sl@0
   124
        mFree = mFree->next;
sl@0
   125
      }
sl@0
   126
      else if (mBlocks != 0 && mUsed < kBlockCount) {
sl@0
   127
        result =  (void*)&mBlocks[mUsed++];
sl@0
   128
      }
sl@0
   129
    }
sl@0
   130
    return result;
sl@0
   131
  }
sl@0
   132
sl@0
   133
  static bool Free(void* p) {
sl@0
   134
    Block* b = (Block*)p;
sl@0
   135
    if (mBlocks == 0 || b < mBlocks || b >= mBlocks + kBlockCount)
sl@0
   136
      return false;
sl@0
   137
    b->next = mFree;
sl@0
   138
    mFree = b;
sl@0
   139
    return true;
sl@0
   140
  }
sl@0
   141
sl@0
   142
  struct Block;
sl@0
   143
  friend struct Block;
sl@0
   144
sl@0
   145
  enum {
sl@0
   146
    // Number of fast allocation blocks to create.
sl@0
   147
    kBlockCount = 1500,
sl@0
   148
sl@0
   149
    // You may need to adjust this number for your platform.
sl@0
   150
    // A good choice will speed tests. A bad choice will still work.
sl@0
   151
    kMinBlockSize = 48
sl@0
   152
  };
sl@0
   153
sl@0
   154
  struct Block {
sl@0
   155
    union {
sl@0
   156
      Block *next;
sl@0
   157
      double dummy; // fbp - force alignment
sl@0
   158
      char dummy2[kMinBlockSize];
sl@0
   159
    };
sl@0
   160
  };
sl@0
   161
sl@0
   162
  static Block* mBlocks;
sl@0
   163
  static Block *mFree;
sl@0
   164
  static size_t mUsed;
sl@0
   165
};
sl@0
   166
sl@0
   167
FastAllocator::Block *FastAllocator::mBlocks =
sl@0
   168
(FastAllocator::Block*)EH_CSTD::calloc( sizeof(FastAllocator::Block), FastAllocator::kBlockCount );
sl@0
   169
FastAllocator::Block *FastAllocator::mFree;
sl@0
   170
size_t FastAllocator::mUsed;
sl@0
   171
sl@0
   172
sl@0
   173
static FastAllocator gFastAllocator;
sl@0
   174
#endif
sl@0
   175
sl@0
   176
inline char* AllocateBlock(size_t s) {
sl@0
   177
#if !defined (NO_FAST_ALLOCATOR)
sl@0
   178
  char * const p = (char*)gFastAllocator.Allocate( s );
sl@0
   179
  if (p != 0)
sl@0
   180
    return p;
sl@0
   181
#endif
sl@0
   182
sl@0
   183
  return (char*)EH_CSTD::malloc(s);
sl@0
   184
}
sl@0
   185
sl@0
   186
static void* OperatorNew( size_t s ) {
sl@0
   187
  if (!using_alloc_set) {
sl@0
   188
    simulate_possible_failure();
sl@0
   189
    ++alloc_count;
sl@0
   190
  }
sl@0
   191
sl@0
   192
  char *p = AllocateBlock(s);
sl@0
   193
sl@0
   194
  if (gTestController.TrackingEnabled() &&
sl@0
   195
      gTestController.LeakDetectionEnabled() &&
sl@0
   196
      !using_alloc_set) {
sl@0
   197
    using_alloc_set = true;
sl@0
   198
    bool inserted = alloc_set().insert(p).second;
sl@0
   199
    EH_ASSERT(inserted);
sl@0
   200
    using_alloc_set = false;
sl@0
   201
  }
sl@0
   202
sl@0
   203
  return p;
sl@0
   204
}
sl@0
   205
#if 0 //sandeep
sl@0
   206
void* _STLP_CALL operator new(size_t s)
sl@0
   207
#ifdef EH_DELETE_HAS_THROW_SPEC
sl@0
   208
throw(EH_STD::bad_alloc)
sl@0
   209
#endif
sl@0
   210
{ return OperatorNew( s ); }
sl@0
   211
sl@0
   212
#ifdef EH_USE_NOTHROW
sl@0
   213
void* _STLP_CALL operator new(size_t size, const EH_STD::nothrow_t&) throw() {
sl@0
   214
  try {
sl@0
   215
    return OperatorNew( size );
sl@0
   216
  }
sl@0
   217
  catch (...) {
sl@0
   218
    return 0;
sl@0
   219
  }
sl@0
   220
}
sl@0
   221
#endif
sl@0
   222
sl@0
   223
#if defined (EH_VECTOR_OPERATOR_NEW)
sl@0
   224
void* _STLP_CALL operator new[](size_t size ) throw(EH_STD::bad_alloc) {
sl@0
   225
  return OperatorNew( size );
sl@0
   226
}
sl@0
   227
sl@0
   228
#  ifdef EH_USE_NOTHROW
sl@0
   229
void* _STLP_CALL operator new[](size_t size, const EH_STD::nothrow_t&) throw() {
sl@0
   230
  try {
sl@0
   231
    return OperatorNew(size);
sl@0
   232
  }
sl@0
   233
  catch (...) {
sl@0
   234
    return 0;
sl@0
   235
  }
sl@0
   236
}
sl@0
   237
#  endif
sl@0
   238
sl@0
   239
void _STLP_CALL operator delete[](void* ptr) throw()
sl@0
   240
{ operator delete( ptr ); }
sl@0
   241
#endif
sl@0
   242
sl@0
   243
#if defined (EH_DELETE_HAS_THROW_SPEC)
sl@0
   244
void _STLP_CALL operator delete(void* s) throw()
sl@0
   245
#else
sl@0
   246
void _STLP_CALL operator delete(void* s)
sl@0
   247
#endif
sl@0
   248
{
sl@0
   249
  if ( s != 0 ) {
sl@0
   250
    if ( !using_alloc_set ) {
sl@0
   251
      --alloc_count;
sl@0
   252
sl@0
   253
      if ( gTestController.TrackingEnabled() && gTestController.LeakDetectionEnabled() ) {
sl@0
   254
        using_alloc_set = true;
sl@0
   255
        allocation_set::iterator p = alloc_set().find( (char*)s );
sl@0
   256
        EH_ASSERT( p != alloc_set().end() );
sl@0
   257
        alloc_set().erase( p );
sl@0
   258
        using_alloc_set = false;
sl@0
   259
      }
sl@0
   260
    }
sl@0
   261
# if ! defined (NO_FAST_ALLOCATOR)
sl@0
   262
    if ( !gFastAllocator.Free( s ) )
sl@0
   263
# endif
sl@0
   264
      EH_CSTD::free(s);
sl@0
   265
  }
sl@0
   266
}
sl@0
   267
#endif //sandeep
sl@0
   268
sl@0
   269
sl@0
   270
/*===================================================================================
sl@0
   271
  ClearAllocationSet  (private helper)
sl@0
   272
sl@0
   273
  EFFECTS:  Empty the set of allocated blocks.
sl@0
   274
====================================================================================*/
sl@0
   275
void TestController::ClearAllocationSet() {
sl@0
   276
  if (!using_alloc_set) {
sl@0
   277
    using_alloc_set = true;
sl@0
   278
    alloc_set().clear();
sl@0
   279
    using_alloc_set = false;
sl@0
   280
  }
sl@0
   281
}
sl@0
   282
sl@0
   283
sl@0
   284
bool TestController::ReportLeaked() {
sl@0
   285
  EndLeakDetection();
sl@0
   286
sl@0
   287
  if (using_alloc_set)
sl@0
   288
    EH_ASSERT( alloc_count == static_cast<int>(alloc_set().size()) );
sl@0
   289
sl@0
   290
  if (alloc_count != 0 || object_count != 0) {
sl@0
   291
    EH_STD::cerr<<"\nEH TEST FAILURE !\n";
sl@0
   292
    PrintTestName(true);
sl@0
   293
    if (alloc_count)
sl@0
   294
      EH_STD::cerr << "ERROR : " << alloc_count << " outstanding allocations.\n";
sl@0
   295
    if (object_count)
sl@0
   296
      EH_STD::cerr << "ERROR : " << object_count << " non-destroyed objects.\n";
sl@0
   297
    alloc_count = object_count = 0;
sl@0
   298
    return true;
sl@0
   299
  }
sl@0
   300
  return false;
sl@0
   301
}
sl@0
   302
sl@0
   303
sl@0
   304
sl@0
   305
/*===================================================================================
sl@0
   306
  PrintTestName
sl@0
   307
sl@0
   308
  EFFECTS: Prints information about the current test. If err is false, ends with
sl@0
   309
    an ellipsis, because the test is ongoing. If err is true an error is being
sl@0
   310
    reported, and the output ends with an endl.
sl@0
   311
====================================================================================*/
sl@0
   312
sl@0
   313
void TestController::PrintTestName(bool err) {
sl@0
   314
  if (current_container)
sl@0
   315
    EH_STD::cerr<<"["<<current_container<<"] :";
sl@0
   316
  EH_STD::cerr<<"testing "<<current_test <<" (" << current_test_category <<")";
sl@0
   317
  if (err)
sl@0
   318
    EH_STD::cerr<<EH_STD::endl;
sl@0
   319
  else
sl@0
   320
    EH_STD::cerr<<" ... ";
sl@0
   321
}
sl@0
   322
sl@0
   323
void TestController::ReportSuccess(int count) {
sl@0
   324
  if (nc_verbose)
sl@0
   325
    EH_STD::cerr<<(count+1)<<" try successful"<<EH_STD::endl;
sl@0
   326
}
sl@0
   327
sl@0
   328
long& TestController::Failure_threshold() {
sl@0
   329
  static long failure_threshold = kNotInExceptionTest;
sl@0
   330
  return failure_threshold;
sl@0
   331
}
sl@0
   332
#if 0 // enable non inline functions
sl@0
   333
void TestController::TrackAllocations(bool track) {
sl@0
   334
  track_allocations = track;
sl@0
   335
}
sl@0
   336
sl@0
   337
bool TestController::TrackingEnabled() {
sl@0
   338
  return track_allocations;
sl@0
   339
}
sl@0
   340
sl@0
   341
 void TestController::SetFailureCountdown(long count) {
sl@0
   342
  Failure_threshold() = count;
sl@0
   343
  possible_failure_count = 0;
sl@0
   344
}
sl@0
   345
sl@0
   346
void TestController::CancelFailureCountdown() {
sl@0
   347
  Failure_threshold() = kNotInExceptionTest;
sl@0
   348
}
sl@0
   349
sl@0
   350
void TestController::BeginLeakDetection() {
sl@0
   351
  alloc_count = 0;
sl@0
   352
  object_count = 0;
sl@0
   353
  ClearAllocationSet();
sl@0
   354
  leak_detection_enabled = true;
sl@0
   355
}
sl@0
   356
sl@0
   357
bool TestController::LeakDetectionEnabled() {
sl@0
   358
  return leak_detection_enabled;
sl@0
   359
}
sl@0
   360
sl@0
   361
void TestController::EndLeakDetection() {
sl@0
   362
  leak_detection_enabled = false;
sl@0
   363
}
sl@0
   364
sl@0
   365
void TestController::SetCurrentTestCategory(const char* str) {
sl@0
   366
  current_test_category = str;
sl@0
   367
  if (nc_verbose)
sl@0
   368
    PrintTestName();
sl@0
   369
}
sl@0
   370
sl@0
   371
void TestController::SetCurrentContainer(const char* str) {
sl@0
   372
  current_container=str;
sl@0
   373
}
sl@0
   374
sl@0
   375
void TestController::SetCurrentTestName(const char* str) {
sl@0
   376
  current_test = str;
sl@0
   377
}
sl@0
   378
sl@0
   379
void TestController::SetVerbose(bool val) {
sl@0
   380
  nc_verbose = val;
sl@0
   381
}
sl@0
   382
sl@0
   383
void TestController::TurnOffExceptions() {
sl@0
   384
  never_fail = true;
sl@0
   385
}
sl@0
   386
#endif