gc_cpp.h 15 KB

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