diff options
| author | Dave Love | 2003-06-05 18:00:24 +0000 |
|---|---|---|
| committer | Dave Love | 2003-06-05 18:00:24 +0000 |
| commit | d0982fbddb5d9202766a24ace3313b281a0a2eff (patch) | |
| tree | e1b13c9ff11ae2359d1b1dd0ca33a9b9be197fd8 /gc/include/gc_cpp.h | |
| parent | 460ff54e9d7a1aca9043ac267025e17b7b299595 (diff) | |
| download | emacs-d0982fbddb5d9202766a24ace3313b281a0a2eff.tar.gz emacs-d0982fbddb5d9202766a24ace3313b281a0a2eff.zip | |
Not committed to branch, sorry.
Diffstat (limited to 'gc/include/gc_cpp.h')
| -rw-r--r-- | gc/include/gc_cpp.h | 362 |
1 files changed, 0 insertions, 362 deletions
diff --git a/gc/include/gc_cpp.h b/gc/include/gc_cpp.h deleted file mode 100644 index d789a3731e3..00000000000 --- a/gc/include/gc_cpp.h +++ /dev/null | |||
| @@ -1,362 +0,0 @@ | |||
| 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 guarrantee 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 | enum GCPlacement {UseGC, | ||
| 156 | #ifndef GC_NAME_CONFLICT | ||
| 157 | GC=UseGC, | ||
| 158 | #endif | ||
| 159 | NoGC, PointerFreeGC}; | ||
| 160 | |||
| 161 | class gc {public: | ||
| 162 | inline void* operator new( size_t size ); | ||
| 163 | inline void* operator new( size_t size, GCPlacement gcp ); | ||
| 164 | inline void* operator new( size_t size, void *p ); | ||
| 165 | /* Must be redefined here, since the other overloadings */ | ||
| 166 | /* hide the global definition. */ | ||
| 167 | inline void operator delete( void* obj ); | ||
| 168 | # ifndef __BORLANDC__ /* Confuses the Borland compiler. */ | ||
| 169 | inline void operator delete( void*, void* ); | ||
| 170 | # endif | ||
| 171 | |||
| 172 | #ifdef GC_OPERATOR_NEW_ARRAY | ||
| 173 | inline void* operator new[]( size_t size ); | ||
| 174 | inline void* operator new[]( size_t size, GCPlacement gcp ); | ||
| 175 | inline void* operator new[]( size_t size, void *p ); | ||
| 176 | inline void operator delete[]( void* obj ); | ||
| 177 | # ifndef __BORLANDC__ | ||
| 178 | inline void gc::operator delete[]( void*, void* ); | ||
| 179 | # endif | ||
| 180 | #endif /* GC_OPERATOR_NEW_ARRAY */ | ||
| 181 | }; | ||
| 182 | /* | ||
| 183 | Instances of classes derived from "gc" will be allocated in the | ||
| 184 | collected heap by default, unless an explicit NoGC placement is | ||
| 185 | specified. */ | ||
| 186 | |||
| 187 | class gc_cleanup: virtual public gc {public: | ||
| 188 | inline gc_cleanup(); | ||
| 189 | inline virtual ~gc_cleanup(); | ||
| 190 | private: | ||
| 191 | inline static void GC_cdecl cleanup( void* obj, void* clientData );}; | ||
| 192 | /* | ||
| 193 | Instances of classes derived from "gc_cleanup" will be allocated | ||
| 194 | in the collected heap by default. When the collector discovers an | ||
| 195 | inaccessible object derived from "gc_cleanup" or containing a | ||
| 196 | member derived from "gc_cleanup", its destructors will be | ||
| 197 | invoked. */ | ||
| 198 | |||
| 199 | extern "C" {typedef void (*GCCleanUpFunc)( void* obj, void* clientData );} | ||
| 200 | |||
| 201 | #ifdef _MSC_VER | ||
| 202 | // Disable warning that "no matching operator delete found; memory will | ||
| 203 | // not be freed if initialization throws an exception" | ||
| 204 | # pragma warning(disable:4291) | ||
| 205 | #endif | ||
| 206 | |||
| 207 | inline void* operator new( | ||
| 208 | size_t size, | ||
| 209 | GCPlacement gcp, | ||
| 210 | GCCleanUpFunc cleanup = 0, | ||
| 211 | void* clientData = 0 ); | ||
| 212 | /* | ||
| 213 | Allocates a collectable or uncollected object, according to the | ||
| 214 | value of "gcp". | ||
| 215 | |||
| 216 | For collectable objects, if "cleanup" is non-null, then when the | ||
| 217 | allocated object "obj" becomes inaccessible, the collector will | ||
| 218 | invoke the function "cleanup( obj, clientData )" but will not | ||
| 219 | invoke the object's destructors. It is an error to explicitly | ||
| 220 | delete an object allocated with a non-null "cleanup". | ||
| 221 | |||
| 222 | It is an error to specify a non-null "cleanup" with NoGC or for | ||
| 223 | classes derived from "gc_cleanup" or containing members derived | ||
| 224 | from "gc_cleanup". */ | ||
| 225 | |||
| 226 | |||
| 227 | #ifdef _MSC_VER | ||
| 228 | /** This ensures that the system default operator new[] doesn't get | ||
| 229 | * undefined, which is what seems to happen on VC++ 6 for some reason | ||
| 230 | * if we define a multi-argument operator new[]. | ||
| 231 | * There seems to be really redirect new in this environment without | ||
| 232 | * including this everywhere. | ||
| 233 | */ | ||
| 234 | void *operator new[]( size_t size ); | ||
| 235 | |||
| 236 | void operator delete[](void* obj); | ||
| 237 | |||
| 238 | void* operator new( size_t size); | ||
| 239 | |||
| 240 | void operator delete(void* obj); | ||
| 241 | |||
| 242 | // This new operator is used by VC++ in case of Debug builds ! | ||
| 243 | void* operator new( size_t size, | ||
| 244 | int ,//nBlockUse, | ||
| 245 | const char * szFileName, | ||
| 246 | int nLine ); | ||
| 247 | #endif /* _MSC_VER */ | ||
| 248 | |||
| 249 | |||
| 250 | #ifdef GC_OPERATOR_NEW_ARRAY | ||
| 251 | |||
| 252 | inline void* operator new[]( | ||
| 253 | size_t size, | ||
| 254 | GCPlacement gcp, | ||
| 255 | GCCleanUpFunc cleanup = 0, | ||
| 256 | void* clientData = 0 ); | ||
| 257 | /* | ||
| 258 | The operator new for arrays, identical to the above. */ | ||
| 259 | |||
| 260 | #endif /* GC_OPERATOR_NEW_ARRAY */ | ||
| 261 | |||
| 262 | /**************************************************************************** | ||
| 263 | |||
| 264 | Inline implementation | ||
| 265 | |||
| 266 | ****************************************************************************/ | ||
| 267 | |||
| 268 | inline void* gc::operator new( size_t size ) { | ||
| 269 | return GC_MALLOC( size );} | ||
| 270 | |||
| 271 | inline void* gc::operator new( size_t size, GCPlacement gcp ) { | ||
| 272 | if (gcp == UseGC) | ||
| 273 | return GC_MALLOC( size ); | ||
| 274 | else if (gcp == PointerFreeGC) | ||
| 275 | return GC_MALLOC_ATOMIC( size ); | ||
| 276 | else | ||
| 277 | return GC_MALLOC_UNCOLLECTABLE( size );} | ||
| 278 | |||
| 279 | inline void* gc::operator new( size_t size, void *p ) { | ||
| 280 | return p;} | ||
| 281 | |||
| 282 | inline void gc::operator delete( void* obj ) { | ||
| 283 | GC_FREE( obj );} | ||
| 284 | |||
| 285 | #ifndef __BORLANDC__ | ||
| 286 | inline void gc::operator delete( void*, void* ) {} | ||
| 287 | #endif | ||
| 288 | |||
| 289 | #ifdef GC_OPERATOR_NEW_ARRAY | ||
| 290 | |||
| 291 | inline void* gc::operator new[]( size_t size ) { | ||
| 292 | return gc::operator new( size );} | ||
| 293 | |||
| 294 | inline void* gc::operator new[]( size_t size, GCPlacement gcp ) { | ||
| 295 | return gc::operator new( size, gcp );} | ||
| 296 | |||
| 297 | inline void* gc::operator new[]( size_t size, void *p ) { | ||
| 298 | return p;} | ||
| 299 | |||
| 300 | inline void gc::operator delete[]( void* obj ) { | ||
| 301 | gc::operator delete( obj );} | ||
| 302 | |||
| 303 | #ifndef __BORLANDC__ | ||
| 304 | inline void gc::operator delete[]( void*, void* ) {} | ||
| 305 | #endif | ||
| 306 | |||
| 307 | #endif /* GC_OPERATOR_NEW_ARRAY */ | ||
| 308 | |||
| 309 | |||
| 310 | inline gc_cleanup::~gc_cleanup() { | ||
| 311 | GC_register_finalizer_ignore_self( GC_base(this), 0, 0, 0, 0 );} | ||
| 312 | |||
| 313 | inline void gc_cleanup::cleanup( void* obj, void* displ ) { | ||
| 314 | ((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup();} | ||
| 315 | |||
| 316 | inline gc_cleanup::gc_cleanup() { | ||
| 317 | GC_finalization_proc oldProc; | ||
| 318 | void* oldData; | ||
| 319 | void* base = GC_base( (void *) this ); | ||
| 320 | if (0 != base) { | ||
| 321 | // Don't call the debug version, since this is a real base address. | ||
| 322 | GC_register_finalizer_ignore_self( | ||
| 323 | base, (GC_finalization_proc)cleanup, (void*) ((char*) this - (char*) base), | ||
| 324 | &oldProc, &oldData ); | ||
| 325 | if (0 != oldProc) { | ||
| 326 | GC_register_finalizer_ignore_self( base, oldProc, oldData, 0, 0 );}}} | ||
| 327 | |||
| 328 | inline void* operator new( | ||
| 329 | size_t size, | ||
| 330 | GCPlacement gcp, | ||
| 331 | GCCleanUpFunc cleanup, | ||
| 332 | void* clientData ) | ||
| 333 | { | ||
| 334 | void* obj; | ||
| 335 | |||
| 336 | if (gcp == UseGC) { | ||
| 337 | obj = GC_MALLOC( size ); | ||
| 338 | if (cleanup != 0) | ||
| 339 | GC_REGISTER_FINALIZER_IGNORE_SELF( | ||
| 340 | obj, cleanup, clientData, 0, 0 );} | ||
| 341 | else if (gcp == PointerFreeGC) { | ||
| 342 | obj = GC_MALLOC_ATOMIC( size );} | ||
| 343 | else { | ||
| 344 | obj = GC_MALLOC_UNCOLLECTABLE( size );}; | ||
| 345 | return obj;} | ||
| 346 | |||
| 347 | |||
| 348 | #ifdef GC_OPERATOR_NEW_ARRAY | ||
| 349 | |||
| 350 | inline void* operator new[]( | ||
| 351 | size_t size, | ||
| 352 | GCPlacement gcp, | ||
| 353 | GCCleanUpFunc cleanup, | ||
| 354 | void* clientData ) | ||
| 355 | { | ||
| 356 | return ::operator new( size, gcp, cleanup, clientData );} | ||
| 357 | |||
| 358 | #endif /* GC_OPERATOR_NEW_ARRAY */ | ||
| 359 | |||
| 360 | |||
| 361 | #endif /* GC_CPP_H */ | ||
| 362 | |||