version 1.1, 1999/12/03 07:39:10 |
version 1.5, 2003/06/24 05:11:40 |
Line 16 the code was modified is included with the above copyr |
|
Line 16 the code was modified is included with the above copyr |
|
C++ Interface to the Boehm Collector |
C++ Interface to the Boehm Collector |
|
|
John R. Ellis and Jesse Hull |
John R. Ellis and Jesse Hull |
Last modified on Mon Jul 24 15:43:42 PDT 1995 by ellis |
|
|
|
This interface provides access to the Boehm collector. It provides |
This interface provides access to the Boehm collector. It provides |
basic facilities similar to those described in "Safe, Efficient |
basic facilities similar to those described in "Safe, Efficient |
Garbage Collection for C++", by John R. Elis and David L. Detlefs |
Garbage Collection for C++", by John R. Elis and David L. Detlefs |
(ftp.parc.xerox.com:/pub/ellis/gc). |
(ftp://ftp.parc.xerox.com/pub/ellis/gc). |
|
|
All heap-allocated objects are either "collectable" or |
All heap-allocated objects are either "collectable" or |
"uncollectable". Programs must explicitly delete uncollectable |
"uncollectable". Programs must explicitly delete uncollectable |
Line 38 Objects derived from class "gc" are collectable. For |
|
Line 37 Objects derived from class "gc" are collectable. For |
|
A* a = new A; // a is collectable. |
A* a = new A; // a is collectable. |
|
|
Collectable instances of non-class types can be allocated using the GC |
Collectable instances of non-class types can be allocated using the GC |
placement: |
(or UseGC) placement: |
|
|
typedef int A[ 10 ]; |
typedef int A[ 10 ]; |
A* a = new (GC) A; |
A* a = new (GC) A; |
|
|
1. Be sure the collector has been augmented with "make c++". |
1. Be sure the collector has been augmented with "make c++". |
|
|
2. If your compiler supports the new "operator new[]" syntax, then |
2. If your compiler supports the new "operator new[]" syntax, then |
add -DOPERATOR_NEW_ARRAY to the Makefile. |
add -DGC_OPERATOR_NEW_ARRAY to the Makefile. |
|
|
If your compiler doesn't support "operator new[]", beware that an |
If your compiler doesn't support "operator new[]", beware that an |
array of type T, where T is derived from "gc", may or may not be |
array of type T, where T is derived from "gc", may or may not be |
Line 124 invoked using the ANSI-conforming syntax t->~T(). If |
|
Line 123 invoked using the ANSI-conforming syntax t->~T(). If |
|
cfront 3.0, you'll have to comment out the class gc_cleanup, which |
cfront 3.0, you'll have to comment out the class gc_cleanup, which |
uses explicit invocation. |
uses explicit invocation. |
|
|
|
5. GC name conflicts: |
|
|
|
Many other systems seem to use the identifier "GC" as an abbreviation |
|
for "Graphics Context". Since version 5.0, GC placement has been replaced |
|
by UseGC. GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined. |
|
|
****************************************************************************/ |
****************************************************************************/ |
|
|
#include "gc.h" |
#include "gc.h" |
|
|
#ifndef THINK_CPLUS |
#ifndef THINK_CPLUS |
#define _cdecl |
# define GC_cdecl |
|
#else |
|
# define GC_cdecl _cdecl |
#endif |
#endif |
|
|
#if ! defined( OPERATOR_NEW_ARRAY ) \ |
#if ! defined( GC_NO_OPERATOR_NEW_ARRAY ) \ |
&& (__BORLANDC__ >= 0x450 || (__GNUC__ >= 2 && __GNUC_MINOR__ >= 6) \ |
&& !defined(_ENABLE_ARRAYNEW) /* Digimars */ \ |
|| __WATCOMC__ >= 1050) |
&& (defined(__BORLANDC__) && (__BORLANDC__ < 0x450) \ |
# define OPERATOR_NEW_ARRAY |
|| (defined(__GNUC__) && \ |
|
(__GNUC__ < 2 || __GNUC__ == 2 && __GNUC_MINOR__ < 6)) \ |
|
|| (defined(__WATCOMC__) && __WATCOMC__ < 1050)) |
|
# define GC_NO_OPERATOR_NEW_ARRAY |
#endif |
#endif |
|
|
enum GCPlacement {GC, NoGC, PointerFreeGC}; |
#if !defined(GC_NO_OPERATOR_NEW_ARRAY) && !defined(GC_OPERATOR_NEW_ARRAY) |
|
# define GC_OPERATOR_NEW_ARRAY |
|
#endif |
|
|
|
enum GCPlacement {UseGC, |
|
#ifndef GC_NAME_CONFLICT |
|
GC=UseGC, |
|
#endif |
|
NoGC, PointerFreeGC}; |
|
|
class gc {public: |
class gc {public: |
inline void* operator new( size_t size ); |
inline void* operator new( size_t size ); |
inline void* operator new( size_t size, GCPlacement gcp ); |
inline void* operator new( size_t size, GCPlacement gcp ); |
|
inline void* operator new( size_t size, void *p ); |
|
/* Must be redefined here, since the other overloadings */ |
|
/* hide the global definition. */ |
inline void operator delete( void* obj ); |
inline void operator delete( void* obj ); |
|
# ifndef __BORLANDC__ /* Confuses the Borland compiler. */ |
|
inline void operator delete( void*, void* ); |
|
# endif |
|
|
#ifdef OPERATOR_NEW_ARRAY |
#ifdef GC_OPERATOR_NEW_ARRAY |
inline void* operator new[]( size_t size ); |
inline void* operator new[]( size_t size ); |
inline void* operator new[]( size_t size, GCPlacement gcp ); |
inline void* operator new[]( size_t size, GCPlacement gcp ); |
|
inline void* operator new[]( size_t size, void *p ); |
inline void operator delete[]( void* obj ); |
inline void operator delete[]( void* obj ); |
#endif /* OPERATOR_NEW_ARRAY */ |
# ifndef __BORLANDC__ |
|
inline void gc::operator delete[]( void*, void* ); |
|
# endif |
|
#endif /* GC_OPERATOR_NEW_ARRAY */ |
}; |
}; |
/* |
/* |
Instances of classes derived from "gc" will be allocated in the |
Instances of classes derived from "gc" will be allocated in the |
Line 160 class gc_cleanup: virtual public gc {public: |
|
Line 188 class gc_cleanup: virtual public gc {public: |
|
inline gc_cleanup(); |
inline gc_cleanup(); |
inline virtual ~gc_cleanup(); |
inline virtual ~gc_cleanup(); |
private: |
private: |
inline static void _cdecl cleanup( void* obj, void* clientData );}; |
inline static void GC_cdecl cleanup( void* obj, void* clientData );}; |
/* |
/* |
Instances of classes derived from "gc_cleanup" will be allocated |
Instances of classes derived from "gc_cleanup" will be allocated |
in the collected heap by default. When the collector discovers an |
in the collected heap by default. When the collector discovers an |
Line 170 class gc_cleanup: virtual public gc {public: |
|
Line 198 class gc_cleanup: virtual public gc {public: |
|
|
|
extern "C" {typedef void (*GCCleanUpFunc)( void* obj, void* clientData );} |
extern "C" {typedef void (*GCCleanUpFunc)( void* obj, void* clientData );} |
|
|
|
#ifdef _MSC_VER |
|
// Disable warning that "no matching operator delete found; memory will |
|
// not be freed if initialization throws an exception" |
|
# pragma warning(disable:4291) |
|
#endif |
|
|
inline void* operator new( |
inline void* operator new( |
size_t size, |
size_t size, |
GCPlacement gcp, |
GCPlacement gcp, |
Line 189 inline void* operator new( |
|
Line 223 inline void* operator new( |
|
classes derived from "gc_cleanup" or containing members derived |
classes derived from "gc_cleanup" or containing members derived |
from "gc_cleanup". */ |
from "gc_cleanup". */ |
|
|
#ifdef OPERATOR_NEW_ARRAY |
|
|
|
|
#ifdef _MSC_VER |
|
/** This ensures that the system default operator new[] doesn't get |
|
* undefined, which is what seems to happen on VC++ 6 for some reason |
|
* if we define a multi-argument operator new[]. |
|
* There seems to be really redirect new in this environment without |
|
* including this everywhere. |
|
*/ |
|
void *operator new[]( size_t size ); |
|
|
|
void operator delete[](void* obj); |
|
|
|
void* operator new( size_t size); |
|
|
|
void operator delete(void* obj); |
|
|
|
// This new operator is used by VC++ in case of Debug builds ! |
|
void* operator new( size_t size, |
|
int ,//nBlockUse, |
|
const char * szFileName, |
|
int nLine ); |
|
#endif /* _MSC_VER */ |
|
|
|
|
|
#ifdef GC_OPERATOR_NEW_ARRAY |
|
|
inline void* operator new[]( |
inline void* operator new[]( |
size_t size, |
size_t size, |
GCPlacement gcp, |
GCPlacement gcp, |
Line 199 inline void* operator new[]( |
|
Line 257 inline void* operator new[]( |
|
/* |
/* |
The operator new for arrays, identical to the above. */ |
The operator new for arrays, identical to the above. */ |
|
|
#endif /* OPERATOR_NEW_ARRAY */ |
#endif /* GC_OPERATOR_NEW_ARRAY */ |
|
|
/**************************************************************************** |
/**************************************************************************** |
|
|
Line 211 inline void* gc::operator new( size_t size ) { |
|
Line 269 inline void* gc::operator new( size_t size ) { |
|
return GC_MALLOC( size );} |
return GC_MALLOC( size );} |
|
|
inline void* gc::operator new( size_t size, GCPlacement gcp ) { |
inline void* gc::operator new( size_t size, GCPlacement gcp ) { |
if (gcp == GC) |
if (gcp == UseGC) |
return GC_MALLOC( size ); |
return GC_MALLOC( size ); |
else if (gcp == PointerFreeGC) |
else if (gcp == PointerFreeGC) |
return GC_MALLOC_ATOMIC( size ); |
return GC_MALLOC_ATOMIC( size ); |
else |
else |
return GC_MALLOC_UNCOLLECTABLE( size );} |
return GC_MALLOC_UNCOLLECTABLE( size );} |
|
|
|
inline void* gc::operator new( size_t size, void *p ) { |
|
return p;} |
|
|
inline void gc::operator delete( void* obj ) { |
inline void gc::operator delete( void* obj ) { |
GC_FREE( obj );} |
GC_FREE( obj );} |
|
|
|
#ifndef __BORLANDC__ |
|
inline void gc::operator delete( void*, void* ) {} |
|
#endif |
|
|
#ifdef OPERATOR_NEW_ARRAY |
#ifdef GC_OPERATOR_NEW_ARRAY |
|
|
inline void* gc::operator new[]( size_t size ) { |
inline void* gc::operator new[]( size_t size ) { |
return gc::operator new( size );} |
return gc::operator new( size );} |
Line 230 inline void* gc::operator new[]( size_t size ) { |
|
Line 294 inline void* gc::operator new[]( size_t size ) { |
|
inline void* gc::operator new[]( size_t size, GCPlacement gcp ) { |
inline void* gc::operator new[]( size_t size, GCPlacement gcp ) { |
return gc::operator new( size, gcp );} |
return gc::operator new( size, gcp );} |
|
|
|
inline void* gc::operator new[]( size_t size, void *p ) { |
|
return p;} |
|
|
inline void gc::operator delete[]( void* obj ) { |
inline void gc::operator delete[]( void* obj ) { |
gc::operator delete( obj );} |
gc::operator delete( obj );} |
|
|
|
#ifndef __BORLANDC__ |
|
inline void gc::operator delete[]( void*, void* ) {} |
|
#endif |
|
|
#endif /* OPERATOR_NEW_ARRAY */ |
#endif /* GC_OPERATOR_NEW_ARRAY */ |
|
|
|
|
inline gc_cleanup::~gc_cleanup() { |
inline gc_cleanup::~gc_cleanup() { |
GC_REGISTER_FINALIZER_IGNORE_SELF( GC_base(this), 0, 0, 0, 0 );} |
GC_register_finalizer_ignore_self( GC_base(this), 0, 0, 0, 0 );} |
|
|
inline void gc_cleanup::cleanup( void* obj, void* displ ) { |
inline void gc_cleanup::cleanup( void* obj, void* displ ) { |
((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup();} |
((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup();} |
Line 246 inline gc_cleanup::gc_cleanup() { |
|
Line 317 inline gc_cleanup::gc_cleanup() { |
|
GC_finalization_proc oldProc; |
GC_finalization_proc oldProc; |
void* oldData; |
void* oldData; |
void* base = GC_base( (void *) this ); |
void* base = GC_base( (void *) this ); |
if (0 == base) return; |
if (0 != base) { |
GC_REGISTER_FINALIZER_IGNORE_SELF( |
// Don't call the debug version, since this is a real base address. |
base, cleanup, (void*) ((char*) this - (char*) base), |
GC_register_finalizer_ignore_self( |
|
base, (GC_finalization_proc)cleanup, (void*) ((char*) this - (char*) base), |
&oldProc, &oldData ); |
&oldProc, &oldData ); |
if (0 != oldProc) { |
if (0 != oldProc) { |
GC_REGISTER_FINALIZER_IGNORE_SELF( base, oldProc, oldData, 0, 0 );}} |
GC_register_finalizer_ignore_self( base, oldProc, oldData, 0, 0 );}}} |
|
|
inline void* operator new( |
inline void* operator new( |
size_t size, |
size_t size, |
Line 261 inline void* operator new( |
|
Line 333 inline void* operator new( |
|
{ |
{ |
void* obj; |
void* obj; |
|
|
if (gcp == GC) { |
if (gcp == UseGC) { |
obj = GC_MALLOC( size ); |
obj = GC_MALLOC( size ); |
if (cleanup != 0) |
if (cleanup != 0) |
GC_REGISTER_FINALIZER_IGNORE_SELF( |
GC_REGISTER_FINALIZER_IGNORE_SELF( |
Line 273 inline void* operator new( |
|
Line 345 inline void* operator new( |
|
return obj;} |
return obj;} |
|
|
|
|
#ifdef OPERATOR_NEW_ARRAY |
#ifdef GC_OPERATOR_NEW_ARRAY |
|
|
inline void* operator new[]( |
inline void* operator new[]( |
size_t size, |
size_t size, |
Line 283 inline void* operator new[]( |
|
Line 355 inline void* operator new[]( |
|
{ |
{ |
return ::operator new( size, gcp, cleanup, clientData );} |
return ::operator new( size, gcp, cleanup, clientData );} |
|
|
#endif /* OPERATOR_NEW_ARRAY */ |
#endif /* GC_OPERATOR_NEW_ARRAY */ |
|
|
|
|
#endif /* GC_CPP_H */ |
#endif /* GC_CPP_H */ |