Synopsis - Cross-Reference

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