root/gc/tests/test_cpp.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. A
  2. Test
  3. B
  4. Deleting
  5. C
  6. level
  7. Test
  8. D
  9. CleanUp
  10. Test
  11. E
  12. F
  13. Test
  14. Disguise
  15. Undisguise
  16. WinMain
  17. main
  18. main

   1 /****************************************************************************
   2 Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
   3  
   4 THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
   5 OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
   6  
   7 Permission is hereby granted to use or copy this program for any
   8 purpose, provided the above notices are retained on all copies.
   9 Permission to modify the code and to distribute modified code is
  10 granted, provided the above notices are retained, and a notice that
  11 the code was modified is included with the above copyright notice.
  12 ****************************************************************************
  13 Last modified on Mon Jul 10 21:06:03 PDT 1995 by ellis
  14      modified on December 20, 1994 7:27 pm PST by boehm
  15 
  16 usage: test_cpp number-of-iterations
  17 
  18 This program tries to test the specific C++ functionality provided by
  19 gc_c++.h that isn't tested by the more general test routines of the
  20 collector.
  21 
  22 A recommended value for number-of-iterations is 10, which will take a
  23 few minutes to complete.
  24 
  25 ***************************************************************************/
  26 
  27 #include "gc_cpp.h"
  28 #include <stdio.h>
  29 #include <stdlib.h>
  30 #include <string.h>
  31 #define USE_STD_ALLOCATOR
  32 #ifdef USE_STD_ALLOCATOR
  33 #   include "gc_allocator.h"
  34 #elif __GNUC__
  35 #   include "new_gc_alloc.h"
  36 #else
  37 #   include "gc_alloc.h"
  38 #endif
  39 extern "C" {
  40 #include "private/gc_priv.h"
  41 }
  42 #ifdef MSWIN32
  43 #   include <windows.h>
  44 #endif
  45 #ifdef GC_NAME_CONFLICT
  46 #   define USE_GC UseGC
  47     struct foo * GC;
  48 #else
  49 #   define USE_GC GC
  50 #endif
  51 
  52 
  53 #define my_assert( e ) \
  54     if (! (e)) { \
  55         GC_printf1( "Assertion failure in " __FILE__ ", line %d: " #e "\n", \
  56                     __LINE__ ); \
  57         exit( 1 ); }
  58 
  59 
  60 class A {public:
  61     /* An uncollectable class. */
  62 
  63     A( int iArg ): i( iArg ) {}
  64     void Test( int iArg ) {
  65         my_assert( i == iArg );} 
  66     int i;};
  67 
  68 
  69 class B: public gc, public A {public:
  70     /* A collectable class. */
  71 
  72     B( int j ): A( j ) {}
  73     ~B() {
  74         my_assert( deleting );}
  75     static void Deleting( int on ) {
  76         deleting = on;}
  77     static int deleting;};
  78 
  79 int B::deleting = 0;
  80 
  81 
  82 class C: public gc_cleanup, public A {public:
  83     /* A collectable class with cleanup and virtual multiple inheritance. */
  84 
  85     C( int levelArg ): A( levelArg ), level( levelArg ) {
  86         nAllocated++;
  87         if (level > 0) {
  88             left = new C( level - 1 );
  89             right = new C( level - 1 );}
  90         else {
  91             left = right = 0;}}
  92     ~C() {
  93         this->A::Test( level );
  94         nFreed++;
  95         my_assert( level == 0 ? 
  96                    left == 0 && right == 0 :
  97                    level == left->level + 1 && level == right->level + 1 );
  98         left = right = 0;
  99         level = -123456;}
 100     static void Test() {
 101         my_assert( nFreed <= nAllocated && nFreed >= .8 * nAllocated );}
 102 
 103     static int nFreed;
 104     static int nAllocated;
 105     int level;
 106     C* left;
 107     C* right;};
 108 
 109 int C::nFreed = 0;
 110 int C::nAllocated = 0;
 111 
 112 
 113 class D: public gc {public:
 114     /* A collectable class with a static member function to be used as
 115     an explicit clean-up function supplied to ::new. */
 116 
 117     D( int iArg ): i( iArg ) {
 118         nAllocated++;}
 119     static void CleanUp( void* obj, void* data ) {
 120         D* self = (D*) obj;
 121         nFreed++;
 122         my_assert( self->i == (int) (long) data );}
 123     static void Test() {
 124         my_assert( nFreed >= .8 * nAllocated );}
 125        
 126     int i;
 127     static int nFreed;
 128     static int nAllocated;};
 129 
 130 int D::nFreed = 0;
 131 int D::nAllocated = 0;
 132 
 133 
 134 class E: public gc_cleanup {public:
 135     /* A collectable class with clean-up for use by F. */
 136 
 137     E() {
 138         nAllocated++;}
 139     ~E() {
 140         nFreed++;}
 141 
 142     static int nFreed;
 143     static int nAllocated;};
 144     
 145 int E::nFreed = 0;
 146 int E::nAllocated = 0;
 147    
 148 
 149 class F: public E {public:
 150     /* A collectable class with clean-up, a base with clean-up, and a
 151     member with clean-up. */
 152 
 153     F() {
 154         nAllocated++;}
 155     ~F() {
 156         nFreed++;}
 157     static void Test() {
 158         my_assert( nFreed >= .8 * nAllocated );
 159         my_assert( 2 * nFreed == E::nFreed );}
 160        
 161     E e;
 162     static int nFreed;
 163     static int nAllocated;};
 164     
 165 int F::nFreed = 0;
 166 int F::nAllocated = 0;
 167    
 168 
 169 long Disguise( void* p ) {
 170     return ~ (long) p;}
 171 
 172 void* Undisguise( long i ) {
 173     return (void*) ~ i;}
 174 
 175 
 176 #ifdef MSWIN32
 177 int APIENTRY WinMain(
 178     HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int cmdShow ) 
 179 {
 180     int argc;
 181     char* argv[ 3 ];
 182 
 183     for (argc = 1; argc < sizeof( argv ) / sizeof( argv[ 0 ] ); argc++) {
 184         argv[ argc ] = strtok( argc == 1 ? cmd : 0, " \t" );
 185         if (0 == argv[ argc ]) break;}
 186 
 187 #else
 188 # ifdef MACOS
 189     int main() {
 190 # else
 191     int main( int argc, char* argv[] ) {
 192 # endif
 193 #endif
 194 
 195    GC_INIT();
 196 
 197 #  if defined(MACOS)                        // MacOS
 198     char* argv_[] = {"test_cpp", "10"};     //   doesn't
 199     argv = argv_;                           //     have a
 200     argc = sizeof(argv_)/sizeof(argv_[0]);  //       commandline
 201 #  endif 
 202     int i, iters, n;
 203 #   ifdef USE_STD_ALLOCATOR
 204       int *x = gc_allocator<int>().allocate(1);
 205       int **xptr = traceable_allocator<int *>().allocate(1);
 206 #   else 
 207 #     ifdef __GNUC__
 208           int *x = (int *)gc_alloc::allocate(sizeof(int));
 209 #     else
 210           int *x = (int *)alloc::allocate(sizeof(int));
 211 #     endif
 212 #   endif
 213     *x = 29;
 214 #   ifdef USE_STD_ALLOCATOR
 215       *xptr = x;
 216       x = 0;
 217 #   endif
 218     if (argc != 2 || (0 >= (n = atoi( argv[ 1 ] )))) {
 219         GC_printf0( "usage: test_cpp number-of-iterations\nAssuming 10 iters\n" );
 220         n = 10;}
 221         
 222     for (iters = 1; iters <= n; iters++) {
 223         GC_printf1( "Starting iteration %d\n", iters );
 224 
 225             /* Allocate some uncollectable As and disguise their pointers.
 226             Later we'll check to see if the objects are still there.  We're
 227             checking to make sure these objects really are uncollectable. */
 228         long as[ 1000 ];
 229         long bs[ 1000 ];
 230         for (i = 0; i < 1000; i++) {
 231             as[ i ] = Disguise( new (NoGC) A( i ) );
 232             bs[ i ] = Disguise( new (NoGC) B( i ) );}
 233 
 234             /* Allocate a fair number of finalizable Cs, Ds, and Fs.
 235             Later we'll check to make sure they've gone away. */
 236         for (i = 0; i < 1000; i++) {
 237             C* c = new C( 2 );
 238             C c1( 2 );           /* stack allocation should work too */
 239             D* d = ::new (USE_GC, D::CleanUp, (void*)(long)i) D( i );
 240             F* f = new F;
 241             if (0 == i % 10) delete c;}
 242 
 243             /* Allocate a very large number of collectable As and Bs and
 244             drop the references to them immediately, forcing many
 245             collections. */
 246         for (i = 0; i < 1000000; i++) {
 247             A* a = new (USE_GC) A( i );
 248             B* b = new B( i );
 249             b = new (USE_GC) B( i );
 250             if (0 == i % 10) {
 251                 B::Deleting( 1 );
 252                 delete b;
 253                 B::Deleting( 0 );}
 254 #           ifdef FINALIZE_ON_DEMAND
 255               GC_invoke_finalizers();
 256 #           endif
 257             }
 258 
 259             /* Make sure the uncollectable As and Bs are still there. */
 260         for (i = 0; i < 1000; i++) {
 261             A* a = (A*) Undisguise( as[ i ] );
 262             B* b = (B*) Undisguise( bs[ i ] );
 263             a->Test( i );
 264             delete a;
 265             b->Test( i );
 266             B::Deleting( 1 );
 267             delete b;
 268             B::Deleting( 0 );
 269 #           ifdef FINALIZE_ON_DEMAND
 270                  GC_invoke_finalizers();
 271 #           endif
 272 
 273             }
 274 
 275             /* Make sure most of the finalizable Cs, Ds, and Fs have
 276             gone away. */
 277         C::Test();
 278         D::Test();
 279         F::Test();}
 280 
 281 #   ifdef USE_STD_ALLOCATOR
 282       x = *xptr;
 283 #   endif
 284     my_assert (29 == x[0]);
 285     GC_printf0( "The test appears to have succeeded.\n" );
 286     return( 0 );}
 287     
 288 

/* [<][>][^][v][top][bottom][index][help] */