Back to index

plt-scheme  4.2.1
test_cpp.cc
Go to the documentation of this file.
00001 /****************************************************************************
00002 Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
00003  
00004 THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
00005 OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
00006  
00007 Permission is hereby granted to use or copy this program for any
00008 purpose, provided the above notices are retained on all copies.
00009 Permission to modify the code and to distribute modified code is
00010 granted, provided the above notices are retained, and a notice that
00011 the code was modified is included with the above copyright notice.
00012 ****************************************************************************
00013 Last modified on Mon Jul 10 21:06:03 PDT 1995 by ellis
00014      modified on December 20, 1994 7:27 pm PST by boehm
00015 
00016 usage: test_cpp number-of-iterations
00017 
00018 This program tries to test the specific C++ functionality provided by
00019 gc_c++.h that isn't tested by the more general test routines of the
00020 collector.
00021 
00022 A recommended value for number-of-iterations is 10, which will take a
00023 few minutes to complete.
00024 
00025 ***************************************************************************/
00026 
00027 #include "gc_cpp.h"
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #define USE_STD_ALLOCATOR
00032 #ifdef USE_STD_ALLOCATOR
00033 #   include "gc_allocator.h"
00034 #elif __GNUC__
00035 #   include "new_gc_alloc.h"
00036 #else
00037 #   include "gc_alloc.h"
00038 #endif
00039 extern "C" {
00040 #include "private/gc_priv.h"
00041 }
00042 #ifdef MSWIN32
00043 #   include <windows.h>
00044 #endif
00045 #ifdef GC_NAME_CONFLICT
00046 #   define USE_GC UseGC
00047     struct foo * GC;
00048 #else
00049 #   define USE_GC GC
00050 #endif
00051 
00052 
00053 #define my_assert( e ) \
00054     if (! (e)) { \
00055         GC_printf1( "Assertion failure in " __FILE__ ", line %d: " #e "\n", \
00056                     __LINE__ ); \
00057         exit( 1 ); }
00058 
00059 
00060 class A {public:
00061     /* An uncollectable class. */
00062 
00063     A( int iArg ): i( iArg ) {}
00064     void Test( int iArg ) {
00065         my_assert( i == iArg );} 
00066     int i;};
00067 
00068 
00069 class B: public gc, public A {public:
00070     /* A collectable class. */
00071 
00072     B( int j ): A( j ) {}
00073     ~B() {
00074         my_assert( deleting );}
00075     static void Deleting( int on ) {
00076         deleting = on;}
00077     static int deleting;};
00078 
00079 int B::deleting = 0;
00080 
00081 
00082 class C: public gc_cleanup, public A {public:
00083     /* A collectable class with cleanup and virtual multiple inheritance. */
00084 
00085     C( int levelArg ): A( levelArg ), level( levelArg ) {
00086         nAllocated++;
00087         if (level > 0) {
00088             left = new C( level - 1 );
00089             right = new C( level - 1 );}
00090         else {
00091             left = right = 0;}}
00092     ~C() {
00093         this->A::Test( level );
00094         nFreed++;
00095         my_assert( level == 0 ? 
00096                    left == 0 && right == 0 :
00097                    level == left->level + 1 && level == right->level + 1 );
00098         left = right = 0;
00099         level = -123456;}
00100     static void Test() {
00101         my_assert( nFreed <= nAllocated && nFreed >= .8 * nAllocated );}
00102 
00103     static int nFreed;
00104     static int nAllocated;
00105     int level;
00106     C* left;
00107     C* right;};
00108 
00109 int C::nFreed = 0;
00110 int C::nAllocated = 0;
00111 
00112 
00113 class D: public gc {public:
00114     /* A collectable class with a static member function to be used as
00115     an explicit clean-up function supplied to ::new. */
00116 
00117     D( int iArg ): i( iArg ) {
00118         nAllocated++;}
00119     static void CleanUp( void* obj, void* data ) {
00120         D* self = (D*) obj;
00121         nFreed++;
00122         my_assert( self->i == (int) (long) data );}
00123     static void Test() {
00124         my_assert( nFreed >= .8 * nAllocated );}
00125        
00126     int i;
00127     static int nFreed;
00128     static int nAllocated;};
00129 
00130 int D::nFreed = 0;
00131 int D::nAllocated = 0;
00132 
00133 
00134 class E: public gc_cleanup {public:
00135     /* A collectable class with clean-up for use by F. */
00136 
00137     E() {
00138         nAllocated++;}
00139     ~E() {
00140         nFreed++;}
00141 
00142     static int nFreed;
00143     static int nAllocated;};
00144     
00145 int E::nFreed = 0;
00146 int E::nAllocated = 0;
00147    
00148 
00149 class F: public E {public:
00150     /* A collectable class with clean-up, a base with clean-up, and a
00151     member with clean-up. */
00152 
00153     F() {
00154         nAllocated++;}
00155     ~F() {
00156         nFreed++;}
00157     static void Test() {
00158         my_assert( nFreed >= .8 * nAllocated );
00159         my_assert( 2 * nFreed == E::nFreed );}
00160        
00161     E e;
00162     static int nFreed;
00163     static int nAllocated;};
00164     
00165 int F::nFreed = 0;
00166 int F::nAllocated = 0;
00167    
00168 
00169 long Disguise( void* p ) {
00170     return ~ (long) p;}
00171 
00172 void* Undisguise( long i ) {
00173     return (void*) ~ i;}
00174 
00175 
00176 #ifdef MSWIN32
00177 int APIENTRY WinMain(
00178     HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int cmdShow ) 
00179 {
00180     int argc;
00181     char* argv[ 3 ];
00182 
00183     for (argc = 1; argc < sizeof( argv ) / sizeof( argv[ 0 ] ); argc++) {
00184         argv[ argc ] = strtok( argc == 1 ? cmd : 0, " \t" );
00185         if (0 == argv[ argc ]) break;}
00186 
00187 #else
00188 # ifdef MACOS
00189     int main() {
00190 # else
00191     int main( int argc, char* argv[] ) {
00192 # endif
00193 #endif
00194 
00195    GC_INIT();
00196 
00197 #  if defined(MACOS)                        // MacOS
00198     char* argv_[] = {"test_cpp", "10"};     //   doesn't
00199     argv = argv_;                           //     have a
00200     argc = sizeof(argv_)/sizeof(argv_[0]);  //       commandline
00201 #  endif 
00202     int i, iters, n;
00203 #   ifdef USE_STD_ALLOCATOR
00204       int *x = gc_allocator<int>().allocate(1);
00205       int **xptr = traceable_allocator<int *>().allocate(1);
00206 #   else 
00207 #     ifdef __GNUC__
00208           int *x = (int *)gc_alloc::allocate(sizeof(int));
00209 #     else
00210           int *x = (int *)alloc::allocate(sizeof(int));
00211 #     endif
00212 #   endif
00213     *x = 29;
00214 #   ifdef USE_STD_ALLOCATOR
00215       *xptr = x;
00216       x = 0;
00217 #   endif
00218     if (argc != 2 || (0 >= (n = atoi( argv[ 1 ] )))) {
00219         GC_printf0( "usage: test_cpp number-of-iterations\nAssuming 10 iters\n" );
00220         n = 10;}
00221         
00222     for (iters = 1; iters <= n; iters++) {
00223         GC_printf1( "Starting iteration %d\n", iters );
00224 
00225             /* Allocate some uncollectable As and disguise their pointers.
00226             Later we'll check to see if the objects are still there.  We're
00227             checking to make sure these objects really are uncollectable. */
00228         long as[ 1000 ];
00229         long bs[ 1000 ];
00230         for (i = 0; i < 1000; i++) {
00231             as[ i ] = Disguise( new (NoGC) A( i ) );
00232             bs[ i ] = Disguise( new (NoGC) B( i ) );}
00233 
00234             /* Allocate a fair number of finalizable Cs, Ds, and Fs.
00235             Later we'll check to make sure they've gone away. */
00236         for (i = 0; i < 1000; i++) {
00237             C* c = new C( 2 );
00238             C c1( 2 );           /* stack allocation should work too */
00239             D* d = ::new (USE_GC, D::CleanUp, (void*)(long)i) D( i );
00240             F* f = new F;
00241             if (0 == i % 10) delete c;}
00242 
00243             /* Allocate a very large number of collectable As and Bs and
00244             drop the references to them immediately, forcing many
00245             collections. */
00246         for (i = 0; i < 1000000; i++) {
00247             A* a = new (USE_GC) A( i );
00248             B* b = new B( i );
00249             b = new (USE_GC) B( i );
00250             if (0 == i % 10) {
00251                 B::Deleting( 1 );
00252                 delete b;
00253                 B::Deleting( 0 );}
00254 #          ifdef FINALIZE_ON_DEMAND
00255              GC_invoke_finalizers();
00256 #          endif
00257            }
00258 
00259             /* Make sure the uncollectable As and Bs are still there. */
00260         for (i = 0; i < 1000; i++) {
00261             A* a = (A*) Undisguise( as[ i ] );
00262             B* b = (B*) Undisguise( bs[ i ] );
00263             a->Test( i );
00264             delete a;
00265             b->Test( i );
00266             B::Deleting( 1 );
00267             delete b;
00268             B::Deleting( 0 );
00269 #          ifdef FINALIZE_ON_DEMAND
00270                GC_invoke_finalizers();
00271 #          endif
00272 
00273            }
00274 
00275             /* Make sure most of the finalizable Cs, Ds, and Fs have
00276             gone away. */
00277         C::Test();
00278         D::Test();
00279         F::Test();}
00280 
00281 #   ifdef USE_STD_ALLOCATOR
00282       x = *xptr;
00283 #   endif
00284     my_assert (29 == x[0]);
00285     GC_printf0( "The test appears to have succeeded.\n" );
00286     return( 0 );}
00287     
00288