~ubuntu-branches/ubuntu/intrepid/ecl/intrepid

« back to all changes in this revision

Viewing changes to src/gc/include/gc_cpp.h

  • Committer: Bazaar Package Importer
  • Author(s): Peter Van Eynde
  • Date: 2006-05-17 02:46:26 UTC
  • Revision ID: james.westby@ubuntu.com-20060517024626-lljr08ftv9g9vefl
Tags: upstream-0.9h-20060510
ImportĀ upstreamĀ versionĀ 0.9h-20060510

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifndef GC_CPP_H
 
2
#define GC_CPP_H
 
3
/****************************************************************************
 
4
Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
 
5
 
 
6
THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
 
7
OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
 
8
 
 
9
Permission is hereby granted to use or copy this program for any
 
10
purpose, provided the above notices are retained on all copies.
 
11
Permission to modify the code and to distribute modified code is
 
12
granted, provided the above notices are retained, and a notice that
 
13
the code was modified is included with the above copyright notice.
 
14
****************************************************************************
 
15
 
 
16
C++ Interface to the Boehm Collector
 
17
 
 
18
    John R. Ellis and Jesse Hull 
 
19
 
 
20
This interface provides access to the Boehm collector.  It provides
 
21
basic facilities similar to those described in "Safe, Efficient
 
22
Garbage Collection for C++", by John R. Elis and David L. Detlefs
 
23
(ftp://ftp.parc.xerox.com/pub/ellis/gc).
 
24
 
 
25
All heap-allocated objects are either "collectable" or
 
26
"uncollectable".  Programs must explicitly delete uncollectable
 
27
objects, whereas the garbage collector will automatically delete
 
28
collectable objects when it discovers them to be inaccessible.
 
29
Collectable objects may freely point at uncollectable objects and vice
 
30
versa.
 
31
 
 
32
Objects allocated with the built-in "::operator new" are uncollectable.
 
33
 
 
34
Objects derived from class "gc" are collectable.  For example:
 
35
 
 
36
    class A: public gc {...};
 
37
    A* a = new A;       // a is collectable. 
 
38
 
 
39
Collectable instances of non-class types can be allocated using the GC
 
40
(or UseGC) placement:
 
41
 
 
42
    typedef int A[ 10 ];
 
43
    A* a = new (GC) A;
 
44
 
 
45
Uncollectable instances of classes derived from "gc" can be allocated
 
46
using the NoGC placement:
 
47
 
 
48
    class A: public gc {...};
 
49
    A* a = new (NoGC) A;   // a is uncollectable.
 
50
 
 
51
Both uncollectable and collectable objects can be explicitly deleted
 
52
with "delete", which invokes an object's destructors and frees its
 
53
storage immediately.
 
54
 
 
55
A collectable object may have a clean-up function, which will be
 
56
invoked when the collector discovers the object to be inaccessible.
 
57
An object derived from "gc_cleanup" or containing a member derived
 
58
from "gc_cleanup" has a default clean-up function that invokes the
 
59
object's destructors.  Explicit clean-up functions may be specified as
 
60
an additional placement argument:
 
61
 
 
62
    A* a = ::new (GC, MyCleanup) A;
 
63
 
 
64
An object is considered "accessible" by the collector if it can be
 
65
reached by a path of pointers from static variables, automatic
 
66
variables of active functions, or from some object with clean-up
 
67
enabled; pointers from an object to itself are ignored.
 
68
 
 
69
Thus, if objects A and B both have clean-up functions, and A points at
 
70
B, B is considered accessible.  After A's clean-up is invoked and its
 
71
storage released, B will then become inaccessible and will have its
 
72
clean-up invoked.  If A points at B and B points to A, forming a
 
73
cycle, then that's considered a storage leak, and neither will be
 
74
collectable.  See the interface gc.h for low-level facilities for
 
75
handling such cycles of objects with clean-up.
 
76
 
 
77
The collector cannot guarantee that it will find all inaccessible
 
78
objects.  In practice, it finds almost all of them.
 
79
 
 
80
 
 
81
Cautions:
 
82
 
 
83
1. Be sure the collector has been augmented with "make c++".
 
84
 
 
85
2.  If your compiler supports the new "operator new[]" syntax, then
 
86
add -DGC_OPERATOR_NEW_ARRAY to the Makefile.
 
87
 
 
88
If your compiler doesn't support "operator new[]", beware that an
 
89
array of type T, where T is derived from "gc", may or may not be
 
90
allocated as a collectable object (it depends on the compiler).  Use
 
91
the explicit GC placement to make the array collectable.  For example:
 
92
 
 
93
    class A: public gc {...};
 
94
    A* a1 = new A[ 10 ];        // collectable or uncollectable?
 
95
    A* a2 = new (GC) A[ 10 ];   // collectable
 
96
 
 
97
3. The destructors of collectable arrays of objects derived from
 
98
"gc_cleanup" will not be invoked properly.  For example:
 
99
 
 
100
    class A: public gc_cleanup {...};
 
101
    A* a = new (GC) A[ 10 ];    // destructors not invoked correctly
 
102
 
 
103
Typically, only the destructor for the first element of the array will
 
104
be invoked when the array is garbage-collected.  To get all the
 
105
destructors of any array executed, you must supply an explicit
 
106
clean-up function:
 
107
 
 
108
    A* a = new (GC, MyCleanUp) A[ 10 ];
 
109
 
 
110
(Implementing clean-up of arrays correctly, portably, and in a way
 
111
that preserves the correct exception semantics requires a language
 
112
extension, e.g. the "gc" keyword.)
 
113
 
 
114
4. Compiler bugs:
 
115
 
 
116
* Solaris 2's CC (SC3.0) doesn't implement t->~T() correctly, so the
 
117
destructors of classes derived from gc_cleanup won't be invoked.
 
118
You'll have to explicitly register a clean-up function with
 
119
new-placement syntax.
 
120
 
 
121
* Evidently cfront 3.0 does not allow destructors to be explicitly
 
122
invoked using the ANSI-conforming syntax t->~T().  If you're using
 
123
cfront 3.0, you'll have to comment out the class gc_cleanup, which
 
124
uses explicit invocation.
 
125
 
 
126
5. GC name conflicts:
 
127
 
 
128
Many other systems seem to use the identifier "GC" as an abbreviation
 
129
for "Graphics Context".  Since version 5.0, GC placement has been replaced
 
130
by UseGC.  GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined.
 
131
 
 
132
****************************************************************************/
 
133
 
 
134
#include "gc.h"
 
135
 
 
136
#ifndef THINK_CPLUS
 
137
#  define GC_cdecl
 
138
#else
 
139
#  define GC_cdecl _cdecl
 
140
#endif
 
141
 
 
142
#if ! defined( GC_NO_OPERATOR_NEW_ARRAY ) \
 
143
    && !defined(_ENABLE_ARRAYNEW) /* Digimars */ \
 
144
    && (defined(__BORLANDC__) && (__BORLANDC__ < 0x450) \
 
145
        || (defined(__GNUC__) && \
 
146
            (__GNUC__ < 2 || __GNUC__ == 2 && __GNUC_MINOR__ < 6)) \
 
147
        || (defined(__WATCOMC__) && __WATCOMC__ < 1050))
 
148
#   define GC_NO_OPERATOR_NEW_ARRAY
 
149
#endif
 
150
 
 
151
#if !defined(GC_NO_OPERATOR_NEW_ARRAY) && !defined(GC_OPERATOR_NEW_ARRAY)
 
152
#   define GC_OPERATOR_NEW_ARRAY
 
153
#endif
 
154
 
 
155
#if    ! defined ( __BORLANDC__ )  /* Confuses the Borland compiler. */ \
 
156
    && ! defined ( __sgi )
 
157
#  define GC_PLACEMENT_DELETE
 
158
#endif
 
159
 
 
160
enum GCPlacement {UseGC,
 
161
#ifndef GC_NAME_CONFLICT
 
162
                  GC=UseGC,
 
163
#endif
 
164
                  NoGC, PointerFreeGC};
 
165
 
 
166
class gc {public:
 
167
    inline void* operator new( size_t size );
 
168
    inline void* operator new( size_t size, GCPlacement gcp );
 
169
    inline void* operator new( size_t size, void *p );
 
170
        /* Must be redefined here, since the other overloadings */
 
171
        /* hide the global definition.                          */
 
172
    inline void operator delete( void* obj );
 
173
#   ifdef GC_PLACEMENT_DELETE  
 
174
      inline void operator delete( void*, void* );
 
175
#   endif
 
176
 
 
177
#ifdef GC_OPERATOR_NEW_ARRAY
 
178
    inline void* operator new[]( size_t size );
 
179
    inline void* operator new[]( size_t size, GCPlacement gcp );
 
180
    inline void* operator new[]( size_t size, void *p );
 
181
    inline void operator delete[]( void* obj );
 
182
#   ifdef GC_PLACEMENT_DELETE
 
183
      inline void gc::operator delete[]( void*, void* );
 
184
#   endif
 
185
#endif /* GC_OPERATOR_NEW_ARRAY */
 
186
    };    
 
187
    /*
 
188
    Instances of classes derived from "gc" will be allocated in the 
 
189
    collected heap by default, unless an explicit NoGC placement is
 
190
    specified. */
 
191
 
 
192
class gc_cleanup: virtual public gc {public:
 
193
    inline gc_cleanup();
 
194
    inline virtual ~gc_cleanup();
 
195
private:
 
196
    inline static void GC_cdecl cleanup( void* obj, void* clientData );};
 
197
    /*
 
198
    Instances of classes derived from "gc_cleanup" will be allocated
 
199
    in the collected heap by default.  When the collector discovers an
 
200
    inaccessible object derived from "gc_cleanup" or containing a
 
201
    member derived from "gc_cleanup", its destructors will be
 
202
    invoked. */
 
203
 
 
204
extern "C" {typedef void (*GCCleanUpFunc)( void* obj, void* clientData );}
 
205
 
 
206
#ifdef _MSC_VER
 
207
  // Disable warning that "no matching operator delete found; memory will
 
208
  // not be freed if initialization throws an exception"
 
209
# pragma warning(disable:4291)
 
210
#endif
 
211
 
 
212
inline void* operator new( 
 
213
    size_t size, 
 
214
    GCPlacement gcp,
 
215
    GCCleanUpFunc cleanup = 0,
 
216
    void* clientData = 0 );
 
217
    /*
 
218
    Allocates a collectable or uncollected object, according to the
 
219
    value of "gcp".
 
220
 
 
221
    For collectable objects, if "cleanup" is non-null, then when the
 
222
    allocated object "obj" becomes inaccessible, the collector will
 
223
    invoke the function "cleanup( obj, clientData )" but will not
 
224
    invoke the object's destructors.  It is an error to explicitly
 
225
    delete an object allocated with a non-null "cleanup".
 
226
 
 
227
    It is an error to specify a non-null "cleanup" with NoGC or for
 
228
    classes derived from "gc_cleanup" or containing members derived
 
229
    from "gc_cleanup". */
 
230
 
 
231
 
 
232
#ifdef _MSC_VER
 
233
 /** This ensures that the system default operator new[] doesn't get
 
234
  *  undefined, which is what seems to happen on VC++ 6 for some reason
 
235
  *  if we define a multi-argument operator new[].
 
236
  *  There seems to be really redirect new in this environment without
 
237
  *  including this everywhere. 
 
238
  */
 
239
 void *operator new[]( size_t size );
 
240
 
 
241
 void operator delete[](void* obj);
 
242
 
 
243
 void* operator new( size_t size);
 
244
 
 
245
 void operator delete(void* obj);
 
246
 
 
247
 // This new operator is used by VC++ in case of Debug builds !
 
248
 void* operator new(  size_t size,
 
249
                      int ,//nBlockUse,
 
250
                      const char * szFileName,
 
251
                      int nLine );
 
252
#endif /* _MSC_VER */
 
253
 
 
254
 
 
255
#ifdef GC_OPERATOR_NEW_ARRAY
 
256
 
 
257
inline void* operator new[](
 
258
    size_t size, 
 
259
    GCPlacement gcp,
 
260
    GCCleanUpFunc cleanup = 0,
 
261
    void* clientData = 0 );
 
262
    /*
 
263
    The operator new for arrays, identical to the above. */
 
264
 
 
265
#endif /* GC_OPERATOR_NEW_ARRAY */
 
266
 
 
267
/****************************************************************************
 
268
 
 
269
Inline implementation
 
270
 
 
271
****************************************************************************/
 
272
 
 
273
inline void* gc::operator new( size_t size ) {
 
274
    return GC_MALLOC( size );}
 
275
    
 
276
inline void* gc::operator new( size_t size, GCPlacement gcp ) {
 
277
    if (gcp == UseGC) 
 
278
        return GC_MALLOC( size );
 
279
    else if (gcp == PointerFreeGC)
 
280
        return GC_MALLOC_ATOMIC( size );
 
281
    else
 
282
        return GC_MALLOC_UNCOLLECTABLE( size );}
 
283
 
 
284
inline void* gc::operator new( size_t size, void *p ) {
 
285
    return p;}
 
286
 
 
287
inline void gc::operator delete( void* obj ) {
 
288
    GC_FREE( obj );}
 
289
    
 
290
#ifdef GC_PLACEMENT_DELETE
 
291
  inline void gc::operator delete( void*, void* ) {}
 
292
#endif
 
293
 
 
294
#ifdef GC_OPERATOR_NEW_ARRAY
 
295
 
 
296
inline void* gc::operator new[]( size_t size ) {
 
297
    return gc::operator new( size );}
 
298
    
 
299
inline void* gc::operator new[]( size_t size, GCPlacement gcp ) {
 
300
    return gc::operator new( size, gcp );}
 
301
 
 
302
inline void* gc::operator new[]( size_t size, void *p ) {
 
303
    return p;}
 
304
 
 
305
inline void gc::operator delete[]( void* obj ) {
 
306
    gc::operator delete( obj );}
 
307
 
 
308
#ifdef GC_PLACEMENT_DELETE
 
309
  inline void gc::operator delete[]( void*, void* ) {}
 
310
#endif
 
311
    
 
312
#endif /* GC_OPERATOR_NEW_ARRAY */
 
313
 
 
314
 
 
315
inline gc_cleanup::~gc_cleanup() {
 
316
    GC_register_finalizer_ignore_self( GC_base(this), 0, 0, 0, 0 );}
 
317
 
 
318
inline void gc_cleanup::cleanup( void* obj, void* displ ) {
 
319
    ((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup();}
 
320
 
 
321
inline gc_cleanup::gc_cleanup() {
 
322
    GC_finalization_proc oldProc;
 
323
    void* oldData;
 
324
    void* base = GC_base( (void *) this );
 
325
    if (0 != base)  {
 
326
      // Don't call the debug version, since this is a real base address.
 
327
      GC_register_finalizer_ignore_self( 
 
328
        base, (GC_finalization_proc)cleanup, (void*) ((char*) this - (char*) base), 
 
329
        &oldProc, &oldData );
 
330
      if (0 != oldProc) {
 
331
        GC_register_finalizer_ignore_self( base, oldProc, oldData, 0, 0 );}}}
 
332
 
 
333
inline void* operator new( 
 
334
    size_t size, 
 
335
    GCPlacement gcp,
 
336
    GCCleanUpFunc cleanup,
 
337
    void* clientData )
 
338
{
 
339
    void* obj;
 
340
 
 
341
    if (gcp == UseGC) {
 
342
        obj = GC_MALLOC( size );
 
343
        if (cleanup != 0) 
 
344
            GC_REGISTER_FINALIZER_IGNORE_SELF( 
 
345
                obj, cleanup, clientData, 0, 0 );}
 
346
    else if (gcp == PointerFreeGC) {
 
347
        obj = GC_MALLOC_ATOMIC( size );}
 
348
    else {
 
349
        obj = GC_MALLOC_UNCOLLECTABLE( size );};
 
350
    return obj;}
 
351
        
 
352
 
 
353
#ifdef GC_OPERATOR_NEW_ARRAY
 
354
 
 
355
inline void* operator new[]( 
 
356
    size_t size, 
 
357
    GCPlacement gcp,
 
358
    GCCleanUpFunc cleanup,
 
359
    void* clientData )
 
360
{
 
361
    return ::operator new( size, gcp, cleanup, clientData );}
 
362
 
 
363
#endif /* GC_OPERATOR_NEW_ARRAY */
 
364
 
 
365
 
 
366
#endif /* GC_CPP_H */
 
367