Back to index

lightning-sunbird  0.9+nobinonly
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 #ifndef __GNUC__
00032 #   include "gc_alloc.h"
00033 #endif
00034 extern "C" {
00035 #include "gc_priv.h"
00036 }
00037 #ifdef MSWIN32
00038 #   include <windows.h>
00039 #endif
00040 
00041 
00042 #define my_assert( e ) \
00043     if (! (e)) { \
00044         GC_printf1( "Assertion failure in " __FILE__ ", line %d: " #e "\n", \
00045                     __LINE__ ); \
00046         exit( 1 ); }
00047 
00048 
00049 class A {public:
00050     /* An uncollectable class. */
00051 
00052     A( int iArg ): i( iArg ) {}
00053     void Test( int iArg ) {
00054         my_assert( i == iArg );} 
00055     int i;};
00056 
00057 
00058 class B: public gc, public A {public:
00059     /* A collectable class. */
00060 
00061     B( int j ): A( j ) {}
00062     ~B() {
00063         my_assert( deleting );}
00064     static void Deleting( int on ) {
00065         deleting = on;}
00066     static int deleting;};
00067 
00068 int B::deleting = 0;
00069 
00070 
00071 class C: public gc_cleanup, public A {public:
00072     /* A collectable class with cleanup and virtual multiple inheritance. */
00073 
00074     C( int levelArg ): A( levelArg ), level( levelArg ) {
00075         nAllocated++;
00076         if (level > 0) {
00077             left = new C( level - 1 );
00078             right = new C( level - 1 );}
00079         else {
00080             left = right = 0;}}
00081     ~C() {
00082         this->A::Test( level );
00083         nFreed++;
00084         my_assert( level == 0 ? 
00085                    left == 0 && right == 0 :
00086                    level == left->level + 1 && level == right->level + 1 );
00087         left = right = 0;
00088         level = -123456;}
00089     static void Test() {
00090         my_assert( nFreed <= nAllocated && nFreed >= .8 * nAllocated );}
00091 
00092     static int nFreed;
00093     static int nAllocated;
00094     int level;
00095     C* left;
00096     C* right;};
00097 
00098 int C::nFreed = 0;
00099 int C::nAllocated = 0;
00100 
00101 
00102 class D: public gc {public:
00103     /* A collectable class with a static member function to be used as
00104     an explicit clean-up function supplied to ::new. */
00105 
00106     D( int iArg ): i( iArg ) {
00107         nAllocated++;}
00108     static void CleanUp( void* obj, void* data ) {
00109         D* self = (D*) obj;
00110         nFreed++;
00111         my_assert( self->i == (int) (long) data );}
00112     static void Test() {
00113         my_assert( nFreed >= .8 * nAllocated );}
00114        
00115     int i;
00116     static int nFreed;
00117     static int nAllocated;};
00118 
00119 int D::nFreed = 0;
00120 int D::nAllocated = 0;
00121 
00122 
00123 class E: public gc_cleanup {public:
00124     /* A collectable class with clean-up for use by F. */
00125 
00126     E() {
00127         nAllocated++;}
00128     ~E() {
00129         nFreed++;}
00130 
00131     static int nFreed;
00132     static int nAllocated;};
00133     
00134 int E::nFreed = 0;
00135 int E::nAllocated = 0;
00136    
00137 
00138 class F: public E {public:
00139     /* A collectable class with clean-up, a base with clean-up, and a
00140     member with clean-up. */
00141 
00142     F() {
00143         nAllocated++;}
00144     ~F() {
00145         nFreed++;}
00146     static void Test() {
00147         my_assert( nFreed >= .8 * nAllocated );
00148         my_assert( 2 * nFreed == E::nFreed );}
00149        
00150     E e;
00151     static int nFreed;
00152     static int nAllocated;};
00153     
00154 int F::nFreed = 0;
00155 int F::nAllocated = 0;
00156    
00157 
00158 long Disguise( void* p ) {
00159     return ~ (long) p;}
00160 
00161 void* Undisguise( long i ) {
00162     return (void*) ~ i;}
00163 
00164 
00165 #ifdef MSWIN32
00166 int APIENTRY WinMain(
00167     HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int cmdShow ) 
00168 {
00169     int argc;
00170     char* argv[ 3 ];
00171 
00172     for (argc = 1; argc < sizeof( argv ) / sizeof( argv[ 0 ] ); argc++) {
00173         argv[ argc ] = strtok( argc == 1 ? cmd : 0, " \t" );
00174         if (0 == argv[ argc ]) break;}
00175 
00176 #else
00177   int main( int argc, char* argv[] ) {
00178 #endif
00179 
00180 #  if defined(MACOS)                        // MacOS
00181     char* argv_[] = {"test_cpp", "10"};     //   doesn't
00182     argv = argv_;                           //     have a
00183     argc = sizeof(argv_)/sizeof(argv_[0]);  //       commandline
00184 #  endif 
00185     int i, iters, n;
00186 #   if !defined(__GNUC__) && !defined(MACOS)
00187       int *x = (int *)alloc::allocate(sizeof(int));
00188 
00189       *x = 29;
00190       x -= 3;
00191 #   endif
00192     if (argc != 2 || (0 >= (n = atoi( argv[ 1 ] )))) {
00193         GC_printf0( "usage: test_cpp number-of-iterations\n" );
00194         exit( 1 );}
00195         
00196     for (iters = 1; iters <= n; iters++) {
00197         GC_printf1( "Starting iteration %d\n", iters );
00198 
00199             /* Allocate some uncollectable As and disguise their pointers.
00200             Later we'll check to see if the objects are still there.  We're
00201             checking to make sure these objects really are uncollectable. */
00202         long as[ 1000 ];
00203         long bs[ 1000 ];
00204         for (i = 0; i < 1000; i++) {
00205             as[ i ] = Disguise( new (NoGC) A( i ) );
00206             bs[ i ] = Disguise( new (NoGC) B( i ) );}
00207 
00208             /* Allocate a fair number of finalizable Cs, Ds, and Fs.
00209             Later we'll check to make sure they've gone away. */
00210         for (i = 0; i < 1000; i++) {
00211             C* c = new C( 2 );
00212             C c1( 2 );           /* stack allocation should work too */
00213             D* d = ::new (GC, D::CleanUp, (void*) i) D( i );
00214             F* f = new F;
00215             if (0 == i % 10) delete c;}
00216 
00217             /* Allocate a very large number of collectable As and Bs and
00218             drop the references to them immediately, forcing many
00219             collections. */
00220         for (i = 0; i < 1000000; i++) {
00221             A* a = new (GC) A( i );
00222             B* b = new B( i );
00223             b = new (GC) B( i );
00224             if (0 == i % 10) {
00225                 B::Deleting( 1 );
00226                 delete b;
00227                 B::Deleting( 0 );}
00228 #          ifdef FINALIZE_ON_DEMAND
00229              GC_invoke_finalizers();
00230 #          endif
00231            }
00232 
00233             /* Make sure the uncollectable As and Bs are still there. */
00234         for (i = 0; i < 1000; i++) {
00235             A* a = (A*) Undisguise( as[ i ] );
00236             B* b = (B*) Undisguise( bs[ i ] );
00237             a->Test( i );
00238             delete a;
00239             b->Test( i );
00240             B::Deleting( 1 );
00241             delete b;
00242             B::Deleting( 0 );
00243 #          ifdef FINALIZE_ON_DEMAND
00244                GC_invoke_finalizers();
00245 #          endif
00246 
00247            }
00248 
00249             /* Make sure most of the finalizable Cs, Ds, and Fs have
00250             gone away. */
00251         C::Test();
00252         D::Test();
00253         F::Test();}
00254 
00255 #   if !defined(__GNUC__) && !defined(MACOS)
00256       my_assert (29 == x[3]);
00257 #   endif
00258     GC_printf0( "The test appears to have succeeded.\n" );
00259     return( 0 );}
00260     
00261