#include "gc_cpp.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __GNUC__
# include "new_gc_alloc.h"
#else
# include "gc_alloc.h"
#endif
extern "C" {
#include "private/gc_priv.h"
}
#ifdef MSWIN32
# include <windows.h>
#endif
#ifdef GC_NAME_CONFLICT
# define USE_GC UseGC
struct foo * GC;
#else
# define USE_GC GC
#endif
#define my_assert( e ) \
if (! (e)) { \
GC_printf1( "Assertion failure in " __FILE__ ", line %d: " #e "\n", \
__LINE__ ); \
exit( 1 ); }
class A {public:
A( int iArg ): i( iArg ) {}
void Test( int iArg ) {
my_assert( i == iArg );}
int i;};
class B: public gc, public A {public:
B( int j ): A( j ) {}
~B() {
my_assert( deleting );}
static void Deleting( int on ) {
deleting = on;}
static int deleting;};
int B::deleting = 0;
class C: public gc_cleanup, public A {public:
C( int levelArg ): A( levelArg ), level( levelArg ) {
nAllocated++;
if (level > 0) {
left = new C( level - 1 );
right = new C( level - 1 );}
else {
left = right = 0;}}
~C() {
this->A::Test( level );
nFreed++;
my_assert( level == 0 ?
left == 0 && right == 0 :
level == left->level + 1 && level == right->level + 1 );
left = right = 0;
level = -123456;}
static void Test() {
my_assert( nFreed <= nAllocated && nFreed >= .8 * nAllocated );}
static int nFreed;
static int nAllocated;
int level;
C* left;
C* right;};
int C::nFreed = 0;
int C::nAllocated = 0;
class D: public gc {public:
D( int iArg ): i( iArg ) {
nAllocated++;}
static void CleanUp( void* obj, void* data ) {
D* self = (D*) obj;
nFreed++;
my_assert( self->i == (int) (long) data );}
static void Test() {
my_assert( nFreed >= .8 * nAllocated );}
int i;
static int nFreed;
static int nAllocated;};
int D::nFreed = 0;
int D::nAllocated = 0;
class E: public gc_cleanup {public:
E() {
nAllocated++;}
~E() {
nFreed++;}
static int nFreed;
static int nAllocated;};
int E::nFreed = 0;
int E::nAllocated = 0;
class F: public E {public:
F() {
nAllocated++;}
~F() {
nFreed++;}
static void Test() {
my_assert( nFreed >= .8 * nAllocated );
my_assert( 2 * nFreed == E::nFreed );}
E e;
static int nFreed;
static int nAllocated;};
int F::nFreed = 0;
int F::nAllocated = 0;
long Disguise( void* p ) {
return ~ (long) p;}
void* Undisguise( long i ) {
return (void*) ~ i;}
#ifdef MSWIN32
int APIENTRY WinMain(
HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int cmdShow )
{
int argc;
char* argv[ 3 ];
for (argc = 1; argc < sizeof( argv ) / sizeof( argv[ 0 ] ); argc++) {
argv[ argc ] = strtok( argc == 1 ? cmd : 0, " \t" );
if (0 == argv[ argc ]) break;}
#else
# ifdef MACOS
int main() {
# else
int main( int argc, char* argv[] ) {
# endif
#endif
# if defined(MACOS) // MacOS
char* argv_[] = {"test_cpp", "10"}; argv = argv_; argc = sizeof(argv_)/sizeof(argv_[0]); # endif
int i, iters, n;
# if !defined(MACOS)
# ifdef __GNUC__
int *x = (int *)gc_alloc::allocate(sizeof(int));
# else
int *x = (int *)alloc::allocate(sizeof(int));
# endif
*x = 29;
x -= 3;
# endif
if (argc != 2 || (0 >= (n = atoi( argv[ 1 ] )))) {
GC_printf0( "usage: test_cpp number-of-iterations\n" );
exit( 1 );}
for (iters = 1; iters <= n; iters++) {
GC_printf1( "Starting iteration %d\n", iters );
long as[ 1000 ];
long bs[ 1000 ];
for (i = 0; i < 1000; i++) {
as[ i ] = Disguise( new (NoGC) A( i ) );
bs[ i ] = Disguise( new (NoGC) B( i ) );}
for (i = 0; i < 1000; i++) {
C* c = new C( 2 );
C c1( 2 );
D* d = ::new (USE_GC, D::CleanUp, (void*)(long)i) D( i );
F* f = new F;
if (0 == i % 10) delete c;}
for (i = 0; i < 1000000; i++) {
A* a = new (USE_GC) A( i );
B* b = new B( i );
b = new (USE_GC) B( i );
if (0 == i % 10) {
B::Deleting( 1 );
delete b;
B::Deleting( 0 );}
# ifdef FINALIZE_ON_DEMAND
GC_invoke_finalizers();
# endif
}
for (i = 0; i < 1000; i++) {
A* a = (A*) Undisguise( as[ i ] );
B* b = (B*) Undisguise( bs[ i ] );
a->Test( i );
delete a;
b->Test( i );
B::Deleting( 1 );
delete b;
B::Deleting( 0 );
# ifdef FINALIZE_ON_DEMAND
GC_invoke_finalizers();
# endif
}
C::Test();
D::Test();
F::Test();}
# if !defined(__GNUC__) && !defined(MACOS)
my_assert (29 == x[3]);
# endif
GC_printf0( "The test appears to have succeeded.\n" );
return( 0 );}