/libs/headers/gc/gc_cpp.h

http://github.com/nddrylliog/ooc · C++ Header · 398 lines · 167 code · 51 blank · 180 comment · 29 complexity · 35d6dd56ba86a96c20ed3e5f31faa069 MD5 · raw file

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