referenceCount.I 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. // Filename: referenceCount.I
  2. // Created by: drose (23Oct98)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
  8. //
  9. // All use of this software is subject to the terms of the Panda 3d
  10. // Software license. You should have received a copy of this license
  11. // along with this source code; you will also find a current copy of
  12. // the license at http://www.panda3d.org/license.txt .
  13. //
  14. // To contact the maintainers of this program write to
  15. // [email protected] .
  16. //
  17. ////////////////////////////////////////////////////////////////////
  18. template<class Base>
  19. TypeHandle RefCountProxy<Base>::_type_handle;
  20. template<class Base>
  21. TypeHandle RefCountObj<Base>::_type_handle;
  22. ////////////////////////////////////////////////////////////////////
  23. // Function: ReferenceCount::Constructor
  24. // Access: Protected
  25. // Description: The ReferenceCount constructor is protected because
  26. // you almost never want to create just a ReferenceCount
  27. // object by itself, and it's probably a mistake if you
  28. // try.
  29. //
  30. // ReferenceCount doesn't store any useful information
  31. // in its own right; its only purpose is to add
  32. // reference-counting to some other class via
  33. // inheritance.
  34. ////////////////////////////////////////////////////////////////////
  35. INLINE ReferenceCount::
  36. ReferenceCount() {
  37. _ref_count = 0;
  38. #ifdef DO_MEMORY_USAGE
  39. MemoryUsage::record_pointer(this);
  40. #endif
  41. }
  42. ////////////////////////////////////////////////////////////////////
  43. // Function: ReferenceCount::Copy Constructor
  44. // Access: Protected
  45. // Description: The copies of reference-counted objects do not
  46. // themselves inherit the reference count!
  47. //
  48. // This copy constructor is protected because you almost
  49. // never want to create just a ReferenceCount object by
  50. // itself, and it's probably a mistake if you try.
  51. ////////////////////////////////////////////////////////////////////
  52. INLINE ReferenceCount::
  53. ReferenceCount(const ReferenceCount &) {
  54. _ref_count = 0;
  55. #ifdef DO_MEMORY_USAGE
  56. MemoryUsage::record_pointer(this);
  57. #endif
  58. }
  59. ////////////////////////////////////////////////////////////////////
  60. // Function: ReferenceCount::Copy Assignment Operator
  61. // Access: Protected
  62. // Description: The copies of reference-counted objects do not
  63. // themselves inherit the reference count!
  64. //
  65. // This copy assignment operator is protected because
  66. // you almost never want to copy just a ReferenceCount
  67. // object by itself, and it's probably a mistake if you
  68. // try.
  69. ////////////////////////////////////////////////////////////////////
  70. INLINE void ReferenceCount::
  71. operator = (const ReferenceCount &) {
  72. nassertv(this != NULL);
  73. // If this assertion fails, our own pointer was recently deleted.
  74. // Yikes!
  75. nassertv(_ref_count != -100);
  76. }
  77. ////////////////////////////////////////////////////////////////////
  78. // Function: ReferenceCount::Destructor
  79. // Access: Protected
  80. // Description: The ReferenceCount destructor is protected to
  81. // discourage users from accidentally trying to delete a
  82. // ReferenceCount pointer directly. This is almost
  83. // always a bad idea, since the destructor is not
  84. // virtual, and you've almost certainly got some pointer
  85. // to something that inherits from ReferenceCount, not
  86. // just a plain old ReferenceCount object.
  87. ////////////////////////////////////////////////////////////////////
  88. INLINE ReferenceCount::
  89. ~ReferenceCount() {
  90. nassertv(this != NULL);
  91. // If this assertion fails, we're trying to delete an object that
  92. // was just deleted. Probably you've accidentally made a bitwise
  93. // copy of a PointerTo, by forgetting to write a copy constructor
  94. // for a class that contains PointerTo's.
  95. nassertv(_ref_count != -100);
  96. // If this assertion fails, the reference counts are all screwed
  97. // up altogether. Maybe some errant code stomped all over memory
  98. // somewhere.
  99. nassertv(_ref_count >= 0);
  100. // If this assertion fails, someone tried to delete this object
  101. // while its reference count was still positive. Maybe you tried
  102. // to point a PointerTo at a static object (a local variable,
  103. // instead of one allocated via new)? The test below against 0x7f
  104. // is supposed to check for that, but it's a pretty hokey test.
  105. // Another possibility is you inadvertently omitted a copy
  106. // constructor for a ReferenceCount object, and then bitwise
  107. // copied a dynamically allocated value--reference count and
  108. // all--onto a locally allocated one.
  109. nassertv(_ref_count == 0);
  110. #ifndef NDEBUG
  111. // Ok, all clear to delete. Now set the reference count to -100,
  112. // so we'll have a better chance of noticing if we happen to have
  113. // a stray pointer to it still out there.
  114. _ref_count = -100;
  115. #endif
  116. #ifdef DO_MEMORY_USAGE
  117. MemoryUsage::remove_pointer(this);
  118. #endif
  119. }
  120. ////////////////////////////////////////////////////////////////////
  121. // Function: ReferenceCount::get_ref_count
  122. // Access: Public
  123. // Description: Returns the current reference count.
  124. ////////////////////////////////////////////////////////////////////
  125. INLINE int ReferenceCount::
  126. get_ref_count() const {
  127. #ifndef NDEBUG
  128. test_ref_count_integrity();
  129. #endif
  130. return _ref_count;
  131. }
  132. ////////////////////////////////////////////////////////////////////
  133. // Function: ReferenceCount::ref
  134. // Access: Public
  135. // Description: Explicitly increments the reference count. User code
  136. // should avoid using ref() and unref() directly, which
  137. // can result in missed reference counts. Instead, let
  138. // a PointerTo object manage the reference counting
  139. // automatically.
  140. //
  141. // This function is const, even though it changes the
  142. // object, because generally fiddling with an object's
  143. // reference count isn't considered part of fiddling
  144. // with the object. An object might be const in other
  145. // ways, but we still need to accurately count the
  146. // number of references to it.
  147. //
  148. // The return value is the new reference count.
  149. ////////////////////////////////////////////////////////////////////
  150. INLINE int ReferenceCount::
  151. ref() const {
  152. nassertr(this != NULL, 0);
  153. // If this assertion fails, we're trying to ref a pointer that was
  154. // just deleted. Probably you used a real pointer instead of a
  155. // PointerTo at some point, and the object was deleted when the
  156. // PointerTo went out of scope. Either that, or you forgot to
  157. // define a copy constructor for a class that contains
  158. // PointerTo's.
  159. nassertr(_ref_count != -100, 0);
  160. // If this assertion fails, the reference counts are all screwed
  161. // up altogether. Maybe some errant code stomped all over memory
  162. // somewhere.
  163. nassertr(_ref_count >= 0, 0);
  164. return AtomicAdjust::inc(((ReferenceCount *)this)->_ref_count);
  165. }
  166. ////////////////////////////////////////////////////////////////////
  167. // Function: ReferenceCount::unref
  168. // Access: Public
  169. // Description: Explicitly decrements the reference count. Note that
  170. // the object will not be implicitly deleted by unref()
  171. // simply because the reference count drops to zero.
  172. // (Having a member function delete itself is
  173. // problematic; plus, we don't have a virtual destructor
  174. // anyway.) However, see the helper function
  175. // unref_delete().
  176. //
  177. // User code should avoid using ref() and unref()
  178. // directly, which can result in missed reference
  179. // counts. Instead, let a PointerTo object manage the
  180. // reference counting automatically.
  181. //
  182. // This function is const, even though it changes the
  183. // object, because generally fiddling with an object's
  184. // reference count isn't considered part of fiddling
  185. // with the object. An object might be const in other
  186. // ways, but we still need to accurately count the
  187. // number of references to it.
  188. //
  189. // The return value is the new reference count.
  190. ////////////////////////////////////////////////////////////////////
  191. INLINE int ReferenceCount::
  192. unref() const {
  193. nassertr(this != NULL, false);
  194. // If this assertion fails, we're trying to unref a pointer that
  195. // was just deleted. Probably you used a real pointer instead of
  196. // a PointerTo at some point, and the object was deleted when the
  197. // PointerTo went out of scope. Either that, or you forgot to
  198. // define a copy constructor for a class that contains
  199. // PointerTo's.
  200. nassertr(_ref_count != -100, false);
  201. // If this assertion fails, the reference counts are all screwed
  202. // up altogether. Maybe some errant code stomped all over memory
  203. // somewhere.
  204. nassertr(_ref_count >= 0, false);
  205. // If this assertion fails, you tried to unref an object with a
  206. // zero reference count. Are you using ref() and unref()
  207. // directly? Are you sure you can't use PointerTo's?
  208. nassertr(_ref_count > 0, false);
  209. return AtomicAdjust::dec(((ReferenceCount *)this)->_ref_count);
  210. }
  211. ////////////////////////////////////////////////////////////////////
  212. // Function: ReferenceCount::test_ref_count_integrity
  213. // Access: Public
  214. // Description: Does some easy checks to make sure that the reference
  215. // count isn't completely bogus.
  216. ////////////////////////////////////////////////////////////////////
  217. INLINE void ReferenceCount::
  218. test_ref_count_integrity() const {
  219. #ifndef NDEBUG
  220. nassertv(this != NULL);
  221. // If this assertion fails, we're trying to access a pointer that
  222. // was just deleted. Probably you used a real pointer instead of
  223. // a PointerTo at some point, and the object was deleted when the
  224. // PointerTo went out of scope. Either that, or you forgot to
  225. // define a copy constructor for a class that contains
  226. // PointerTo's.
  227. nassertv(_ref_count != -100);
  228. // If this assertion fails, the reference counts are all screwed
  229. // up altogether. Maybe some errant code stomped all over memory
  230. // somewhere.
  231. nassertv(_ref_count >= 0);
  232. #endif
  233. }
  234. ////////////////////////////////////////////////////////////////////
  235. // Function: unref_delete
  236. // Description: This global helper function will unref the given
  237. // ReferenceCount object, and if the reference count
  238. // reaches zero, automatically delete it. It can't be a
  239. // member function because it's usually a bad idea to
  240. // delete an object from within its own member function.
  241. // It's a template function so the destructor doesn't
  242. // have to be virtual.
  243. ////////////////////////////////////////////////////////////////////
  244. template<class RefCountType>
  245. INLINE void
  246. unref_delete(RefCountType *ptr) {
  247. if (((ReferenceCount *)ptr)->unref() == 0) {
  248. #ifndef NDEBUG
  249. if (get_leak_memory()) {
  250. // In leak-memory mode, we don't actually delete the pointer,
  251. // although we do call the destructor explicitly. This has
  252. // exactly the same effect as deleting it, without actually
  253. // freeing up the memory it uses.
  254. // Furthermore, if we have never-destruct set, we don't even
  255. // call the destructor.
  256. if (!get_never_destruct()) {
  257. ptr->~RefCountType();
  258. }
  259. return;
  260. }
  261. #endif
  262. delete ptr;
  263. }
  264. }
  265. ////////////////////////////////////////////////////////////////////
  266. // Function: RefCountProxy::Constructor
  267. // Access: Public
  268. // Description:
  269. ////////////////////////////////////////////////////////////////////
  270. template<class Base>
  271. INLINE RefCountProxy<Base>::
  272. RefCountProxy() {
  273. }
  274. ////////////////////////////////////////////////////////////////////
  275. // Function: RefCountProxy::Copy Constructor
  276. // Access: Public
  277. // Description:
  278. ////////////////////////////////////////////////////////////////////
  279. template<class Base>
  280. INLINE RefCountProxy<Base>::
  281. RefCountProxy(const Base &copy) : _base(copy) {
  282. }
  283. ////////////////////////////////////////////////////////////////////
  284. // Function: RefCountProxy::Base Typecast Operator
  285. // Access: Public
  286. // Description:
  287. ////////////////////////////////////////////////////////////////////
  288. template<class Base>
  289. INLINE RefCountProxy<Base>::
  290. operator Base &() {
  291. return _base;
  292. }
  293. ////////////////////////////////////////////////////////////////////
  294. // Function: RefCountProxy::Base Typecast Operator
  295. // Access: Public
  296. // Description:
  297. ////////////////////////////////////////////////////////////////////
  298. template<class Base>
  299. INLINE RefCountProxy<Base>::
  300. operator const Base &() const {
  301. return _base;
  302. }
  303. ////////////////////////////////////////////////////////////////////
  304. // Function: RefCountProxy::init_type
  305. // Access: Public
  306. // Description:
  307. ////////////////////////////////////////////////////////////////////
  308. template<class Base>
  309. void RefCountProxy<Base>::
  310. init_type() {
  311. do_init_type(Base);
  312. register_type(_type_handle,
  313. "RefCountProxy<" + get_type_handle(Base).get_name() + ">",
  314. get_type_handle(Base));
  315. }
  316. ////////////////////////////////////////////////////////////////////
  317. // Function: RefCountObj::Constructor
  318. // Access: Public
  319. // Description:
  320. ////////////////////////////////////////////////////////////////////
  321. template<class Base>
  322. INLINE RefCountObj<Base>::
  323. RefCountObj() {
  324. }
  325. ////////////////////////////////////////////////////////////////////
  326. // Function: RefCountObj::Copy Constructor
  327. // Access: Public
  328. // Description:
  329. ////////////////////////////////////////////////////////////////////
  330. template<class Base>
  331. INLINE RefCountObj<Base>::
  332. RefCountObj(const Base &copy) : Base(copy) {
  333. }
  334. ////////////////////////////////////////////////////////////////////
  335. // Function: RefCountObj::init_type
  336. // Access: Public
  337. // Description:
  338. ////////////////////////////////////////////////////////////////////
  339. template<class Base>
  340. void RefCountObj<Base>::
  341. init_type() {
  342. #ifdef HAVE_RTTI
  343. // If we have RTTI, we can determine the name of the base type.
  344. string base_name = typeid(Base).name();
  345. #else
  346. string base_name = "unknown";
  347. #endif
  348. TypeHandle base_type = register_dynamic_type(base_name);
  349. ReferenceCount::init_type();
  350. _type_handle =
  351. register_dynamic_type("RefCountObj<" + base_name + ">",
  352. base_type, ReferenceCount::get_class_type());
  353. }