OSDN Git Service

libjava:
[pf3gnuchains/gcc-fork.git] / boehm-gc / tests / test_cpp.cc
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