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