collectable. See the interface gc.h for low-level facilities for
handling such cycles of objects with clean-up.
-The collector cannot guarrantee that it will find all inaccessible
+The collector cannot guarantee that it will find all inaccessible
objects. In practice, it finds almost all of them.
1. Be sure the collector has been augmented with "make c++".
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
array of type T, where T is derived from "gc", may or may not be
#include "gc.h"
#ifndef THINK_CPLUS
-#define _cdecl
+# define GC_cdecl
+#else
+# define GC_cdecl _cdecl
#endif
-#if ! defined( OPERATOR_NEW_ARRAY ) \
- && (__BORLANDC__ >= 0x450 || (__GNUC__ >= 2 && __GNUC_MINOR__ >= 6) \
- || __WATCOMC__ >= 1050)
-# define OPERATOR_NEW_ARRAY
+#if ! defined( GC_NO_OPERATOR_NEW_ARRAY ) \
+ && !defined(_ENABLE_ARRAYNEW) /* Digimars */ \
+ && (defined(__BORLANDC__) && (__BORLANDC__ < 0x450) \
+ || (defined(__GNUC__) && \
+ (__GNUC__ < 2 || __GNUC__ == 2 && __GNUC_MINOR__ < 6)) \
+ || (defined(__WATCOMC__) && __WATCOMC__ < 1050))
+# define GC_NO_OPERATOR_NEW_ARRAY
+#endif
+
+#if !defined(GC_NO_OPERATOR_NEW_ARRAY) && !defined(GC_OPERATOR_NEW_ARRAY)
+# define GC_OPERATOR_NEW_ARRAY
+#endif
+
+#if ! defined ( __BORLANDC__ ) /* Confuses the Borland compiler. */ \
+ && ! defined ( __sgi )
+# define GC_PLACEMENT_DELETE
#endif
enum GCPlacement {UseGC,
class gc {public:
inline void* operator new( size_t size );
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 );
+# ifdef GC_PLACEMENT_DELETE
+ 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, GCPlacement gcp );
+ inline void* operator new[]( size_t size, void *p );
inline void operator delete[]( void* obj );
-#endif /* OPERATOR_NEW_ARRAY */
+# ifdef GC_PLACEMENT_DELETE
+ inline void gc::operator delete[]( void*, void* );
+# endif
+#endif /* GC_OPERATOR_NEW_ARRAY */
};
/*
Instances of classes derived from "gc" will be allocated in the
inline gc_cleanup();
inline virtual ~gc_cleanup();
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
in the collected heap by default. When the collector discovers an
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(
size_t size,
GCPlacement gcp,
classes derived from "gc_cleanup" or containing members derived
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[](
size_t size,
/*
The operator new for arrays, identical to the above. */
-#endif /* OPERATOR_NEW_ARRAY */
+#endif /* GC_OPERATOR_NEW_ARRAY */
/****************************************************************************
else
return GC_MALLOC_UNCOLLECTABLE( size );}
+inline void* gc::operator new( size_t size, void *p ) {
+ return p;}
+
inline void gc::operator delete( void* obj ) {
GC_FREE( obj );}
+#ifdef GC_PLACEMENT_DELETE
+ 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 ) {
return gc::operator new( size );}
inline void* gc::operator new[]( size_t size, GCPlacement 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 ) {
gc::operator delete( obj );}
+
+#ifdef GC_PLACEMENT_DELETE
+ inline void gc::operator delete[]( void*, void* ) {}
+#endif
-#endif /* OPERATOR_NEW_ARRAY */
+#endif /* GC_OPERATOR_NEW_ARRAY */
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 ) {
((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup();}
void* oldData;
void* base = GC_base( (void *) this );
if (0 != base) {
- GC_REGISTER_FINALIZER_IGNORE_SELF(
+ // Don't call the debug version, since this is a real base address.
+ GC_register_finalizer_ignore_self(
base, (GC_finalization_proc)cleanup, (void*) ((char*) this - (char*) base),
&oldProc, &oldData );
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(
size_t size,
return obj;}
-#ifdef OPERATOR_NEW_ARRAY
+#ifdef GC_OPERATOR_NEW_ARRAY
inline void* operator new[](
size_t size,
{
return ::operator new( size, gcp, cleanup, clientData );}
-#endif /* OPERATOR_NEW_ARRAY */
+#endif /* GC_OPERATOR_NEW_ARRAY */
#endif /* GC_CPP_H */