referenceCount.I 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. // Filename: referenceCount.I
  2. // Created by: drose (23Oct98)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) 2001 - 2004, 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://etc.cmu.edu/panda3d/docs/license/ .
  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. _weak_list = (WeakReferenceList *)NULL;
  38. _ref_count = 0;
  39. #ifdef DO_MEMORY_USAGE
  40. MemoryUsage::record_pointer(this);
  41. #endif
  42. }
  43. ////////////////////////////////////////////////////////////////////
  44. // Function: ReferenceCount::Copy Constructor
  45. // Access: Protected
  46. // Description: The copies of reference-counted objects do not
  47. // themselves inherit the reference count!
  48. //
  49. // This copy constructor is protected because you almost
  50. // never want to create just a ReferenceCount object by
  51. // itself, and it's probably a mistake if you try.
  52. ////////////////////////////////////////////////////////////////////
  53. INLINE ReferenceCount::
  54. ReferenceCount(const ReferenceCount &) {
  55. _weak_list = (WeakReferenceList *)NULL;
  56. _ref_count = 0;
  57. #ifdef DO_MEMORY_USAGE
  58. MemoryUsage::record_pointer(this);
  59. #endif
  60. }
  61. ////////////////////////////////////////////////////////////////////
  62. // Function: ReferenceCount::Copy Assignment Operator
  63. // Access: Protected
  64. // Description: The copies of reference-counted objects do not
  65. // themselves inherit the reference count!
  66. //
  67. // This copy assignment operator is protected because
  68. // you almost never want to copy just a ReferenceCount
  69. // object by itself, and it's probably a mistake if you
  70. // try. Instead, this should only be called from a
  71. // derived class that implements this operator and then
  72. // calls up the inheritance chain.
  73. ////////////////////////////////////////////////////////////////////
  74. INLINE void ReferenceCount::
  75. operator = (const ReferenceCount &) {
  76. nassertv(this != NULL);
  77. // If this assertion fails, our own pointer was recently deleted.
  78. // Possibly you used a real pointer instead of a PointerTo at some
  79. // point, and the object was deleted when the PointerTo went out of
  80. // scope. Maybe you tried to create an automatic (local variable)
  81. // instance of a class that derives from ReferenceCount. Or maybe
  82. // your headers are out of sync, and you need to make clean in
  83. // direct or some higher tree.
  84. nassertv(_ref_count != -100);
  85. }
  86. ////////////////////////////////////////////////////////////////////
  87. // Function: ReferenceCount::Destructor
  88. // Access: Protected
  89. // Description: The ReferenceCount destructor is protected to
  90. // discourage users from accidentally trying to delete a
  91. // ReferenceCount pointer directly. This is almost
  92. // always a bad idea, since the destructor is not
  93. // virtual, and you've almost certainly got some pointer
  94. // to something that inherits from ReferenceCount, not
  95. // just a plain old ReferenceCount object.
  96. ////////////////////////////////////////////////////////////////////
  97. INLINE ReferenceCount::
  98. ~ReferenceCount() {
  99. nassertv(this != NULL);
  100. // If this assertion fails, we're trying to delete an object that
  101. // was just deleted. Possibly you used a real pointer instead of a
  102. // PointerTo at some point, and the object was deleted when the
  103. // PointerTo went out of scope. Maybe you tried to create an
  104. // automatic (local variable) instance of a class that derives from
  105. // ReferenceCount. Or maybe your headers are out of sync, and you
  106. // need to make clean in direct or some higher tree.
  107. nassertv(_ref_count != -100);
  108. // If this assertion fails, the reference counts are all screwed
  109. // up altogether. Maybe some errant code stomped all over memory
  110. // somewhere.
  111. nassertv(_ref_count >= 0);
  112. // If this assertion fails, someone tried to delete this object
  113. // while its reference count was still positive. Maybe you tried
  114. // to point a PointerTo at a static object (a local variable,
  115. // instead of one allocated via new)? The test below against 0x7f
  116. // is supposed to check for that, but it's a pretty hokey test.
  117. // Another possibility is you inadvertently omitted a copy
  118. // constructor for a ReferenceCount object, and then bitwise
  119. // copied a dynamically allocated value--reference count and
  120. // all--onto a locally allocated one.
  121. nassertv(_ref_count == 0);
  122. // Tell our weak reference holders that we're going away now.
  123. if (_weak_list != (WeakReferenceList *)NULL) {
  124. delete _weak_list;
  125. _weak_list = (WeakReferenceList *)NULL;
  126. }
  127. #ifndef NDEBUG
  128. // Ok, all clear to delete. Now set the reference count to -100,
  129. // so we'll have a better chance of noticing if we happen to have
  130. // a stray pointer to it still out there.
  131. _ref_count = -100;
  132. #endif
  133. #ifdef DO_MEMORY_USAGE
  134. MemoryUsage::remove_pointer(this);
  135. #endif
  136. }
  137. ////////////////////////////////////////////////////////////////////
  138. // Function: ReferenceCount::get_ref_count
  139. // Access: Public
  140. // Description: Returns the current reference count.
  141. ////////////////////////////////////////////////////////////////////
  142. INLINE int ReferenceCount::
  143. get_ref_count() const {
  144. #ifndef NDEBUG
  145. test_ref_count_integrity();
  146. #endif
  147. return _ref_count;
  148. }
  149. ////////////////////////////////////////////////////////////////////
  150. // Function: ReferenceCount::ref
  151. // Access: Public
  152. // Description: Explicitly increments the reference count. User code
  153. // should avoid using ref() and unref() directly, which
  154. // can result in missed reference counts. Instead, let
  155. // a PointerTo object manage the reference counting
  156. // automatically.
  157. //
  158. // This function is const, even though it changes the
  159. // object, because generally fiddling with an object's
  160. // reference count isn't considered part of fiddling
  161. // with the object. An object might be const in other
  162. // ways, but we still need to accurately count the
  163. // number of references to it.
  164. //
  165. // The return value is the new reference count.
  166. ////////////////////////////////////////////////////////////////////
  167. INLINE int ReferenceCount::
  168. ref() const {
  169. nassertr(this != NULL, 0);
  170. // If this assertion fails, we're trying to delete an object that
  171. // was just deleted. Possibly you used a real pointer instead of a
  172. // PointerTo at some point, and the object was deleted when the
  173. // PointerTo went out of scope. Maybe you tried to create an
  174. // automatic (local variable) instance of a class that derives from
  175. // ReferenceCount. Or maybe your headers are out of sync, and you
  176. // need to make clean in direct or some higher tree.
  177. nassertr(_ref_count != -100, 0);
  178. // If this assertion fails, the reference counts are all screwed
  179. // up altogether. Maybe some errant code stomped all over memory
  180. // somewhere.
  181. nassertr(_ref_count >= 0, 0);
  182. return AtomicAdjust::inc(((ReferenceCount *)this)->_ref_count);
  183. }
  184. ////////////////////////////////////////////////////////////////////
  185. // Function: ReferenceCount::unref
  186. // Access: Public
  187. // Description: Explicitly decrements the reference count. Note that
  188. // the object will not be implicitly deleted by unref()
  189. // simply because the reference count drops to zero.
  190. // (Having a member function delete itself is
  191. // problematic; plus, we don't have a virtual destructor
  192. // anyway.) However, see the helper function
  193. // unref_delete().
  194. //
  195. // User code should avoid using ref() and unref()
  196. // directly, which can result in missed reference
  197. // counts. Instead, let a PointerTo object manage the
  198. // reference counting automatically.
  199. //
  200. // This function is const, even though it changes the
  201. // object, because generally fiddling with an object's
  202. // reference count isn't considered part of fiddling
  203. // with the object. An object might be const in other
  204. // ways, but we still need to accurately count the
  205. // number of references to it.
  206. //
  207. // The return value is the new reference count.
  208. ////////////////////////////////////////////////////////////////////
  209. INLINE int ReferenceCount::
  210. unref() const {
  211. nassertr(this != NULL, false);
  212. // If this assertion fails, we're trying to delete an object that
  213. // was just deleted. Possibly you used a real pointer instead of a
  214. // PointerTo at some point, and the object was deleted when the
  215. // PointerTo went out of scope. Maybe you tried to create an
  216. // automatic (local variable) instance of a class that derives from
  217. // ReferenceCount. Or maybe your headers are out of sync, and you
  218. // need to make clean in direct or some higher tree.
  219. nassertr(_ref_count != -100, false);
  220. // If this assertion fails, the reference counts are all screwed
  221. // up altogether. Maybe some errant code stomped all over memory
  222. // somewhere.
  223. nassertr(_ref_count >= 0, false);
  224. // If this assertion fails, you tried to unref an object with a
  225. // zero reference count. Are you using ref() and unref()
  226. // directly? Are you sure you can't use PointerTo's?
  227. nassertr(_ref_count > 0, false);
  228. return AtomicAdjust::dec(((ReferenceCount *)this)->_ref_count);
  229. }
  230. ////////////////////////////////////////////////////////////////////
  231. // Function: ReferenceCount::test_ref_count_integrity
  232. // Access: Public
  233. // Description: Does some easy checks to make sure that the reference
  234. // count isn't completely bogus.
  235. ////////////////////////////////////////////////////////////////////
  236. INLINE void ReferenceCount::
  237. test_ref_count_integrity() const {
  238. #ifndef NDEBUG
  239. nassertv(this != NULL);
  240. // If this assertion fails, we're trying to delete an object that
  241. // was just deleted. Possibly you used a real pointer instead of a
  242. // PointerTo at some point, and the object was deleted when the
  243. // PointerTo went out of scope. Maybe you tried to create an
  244. // automatic (local variable) instance of a class that derives from
  245. // ReferenceCount. Or maybe your headers are out of sync, and you
  246. // need to make clean in direct or some higher tree.
  247. nassertv(_ref_count != -100);
  248. // If this assertion fails, the reference counts are all screwed
  249. // up altogether. Maybe some errant code stomped all over memory
  250. // somewhere.
  251. nassertv(_ref_count >= 0);
  252. #endif
  253. }
  254. ////////////////////////////////////////////////////////////////////
  255. // Function: ReferenceCount::has_weak_list
  256. // Access: Public
  257. // Description: Returns true if this particular ReferenceCount object
  258. // has a WeakReferenceList created, false otherwise. In
  259. // general, this will be true if there was ever a
  260. // WeakPointerTo created for this object (even if there
  261. // is not any for it now).
  262. ////////////////////////////////////////////////////////////////////
  263. INLINE bool ReferenceCount::
  264. has_weak_list() const {
  265. return _weak_list != (WeakReferenceList *)NULL;
  266. }
  267. ////////////////////////////////////////////////////////////////////
  268. // Function: ReferenceCount::get_weak_list
  269. // Access: Public
  270. // Description: Returns the WeakReferenceList associated with this
  271. // ReferenceCount object. If there has never been a
  272. // WeakReferenceList associated with this object,
  273. // creates one now.
  274. ////////////////////////////////////////////////////////////////////
  275. INLINE WeakReferenceList *ReferenceCount::
  276. get_weak_list() const {
  277. if (_weak_list == (WeakReferenceList *)NULL) {
  278. ((ReferenceCount *)this)->_weak_list = new WeakReferenceList;
  279. }
  280. return _weak_list;
  281. }
  282. ////////////////////////////////////////////////////////////////////
  283. // Function: ReferenceCount::weak_ref
  284. // Access: Public
  285. // Description: Adds the indicated PointerToVoid as a weak reference
  286. // to this object.
  287. ////////////////////////////////////////////////////////////////////
  288. INLINE void ReferenceCount::
  289. weak_ref(WeakPointerToVoid *ptv) {
  290. get_weak_list()->add_reference(ptv);
  291. }
  292. ////////////////////////////////////////////////////////////////////
  293. // Function: ReferenceCount::weak_unref
  294. // Access: Public
  295. // Description: Removes the indicated PointerToVoid as a weak reference
  296. // to this object. It must have previously been added
  297. // via a call to weak_ref().
  298. ////////////////////////////////////////////////////////////////////
  299. INLINE void ReferenceCount::
  300. weak_unref(WeakPointerToVoid *ptv) {
  301. nassertv(has_weak_list());
  302. _weak_list->clear_reference(ptv);
  303. }
  304. ////////////////////////////////////////////////////////////////////
  305. // Function: unref_delete
  306. // Description: This global helper function will unref the given
  307. // ReferenceCount object, and if the reference count
  308. // reaches zero, automatically delete it. It can't be a
  309. // member function because it's usually a bad idea to
  310. // delete an object from within its own member function.
  311. // It's a template function so the destructor doesn't
  312. // have to be virtual.
  313. ////////////////////////////////////////////////////////////////////
  314. template<class RefCountType>
  315. INLINE void
  316. unref_delete(RefCountType *ptr) {
  317. if (((ReferenceCount *)ptr)->unref() == 0) {
  318. #ifndef NDEBUG
  319. if (get_leak_memory()) {
  320. // In leak-memory mode, we don't actually delete the pointer,
  321. // although we do call the destructor explicitly. This has
  322. // exactly the same effect as deleting it, without actually
  323. // freeing up the memory it uses.
  324. // Furthermore, if we have never-destruct set, we don't even
  325. // call the destructor.
  326. if (!get_never_destruct()) {
  327. ptr->~RefCountType();
  328. }
  329. return;
  330. }
  331. #endif
  332. delete ptr;
  333. }
  334. }
  335. ////////////////////////////////////////////////////////////////////
  336. // Function: RefCountProxy::Constructor
  337. // Access: Public
  338. // Description:
  339. ////////////////////////////////////////////////////////////////////
  340. template<class Base>
  341. INLINE RefCountProxy<Base>::
  342. RefCountProxy() {
  343. }
  344. ////////////////////////////////////////////////////////////////////
  345. // Function: RefCountProxy::Copy Constructor
  346. // Access: Public
  347. // Description:
  348. ////////////////////////////////////////////////////////////////////
  349. template<class Base>
  350. INLINE RefCountProxy<Base>::
  351. RefCountProxy(const Base &copy) : _base(copy) {
  352. }
  353. ////////////////////////////////////////////////////////////////////
  354. // Function: RefCountProxy::Base Typecast Operator
  355. // Access: Public
  356. // Description:
  357. ////////////////////////////////////////////////////////////////////
  358. template<class Base>
  359. INLINE RefCountProxy<Base>::
  360. operator Base &() {
  361. return _base;
  362. }
  363. ////////////////////////////////////////////////////////////////////
  364. // Function: RefCountProxy::Base Typecast Operator
  365. // Access: Public
  366. // Description:
  367. ////////////////////////////////////////////////////////////////////
  368. template<class Base>
  369. INLINE RefCountProxy<Base>::
  370. operator const Base &() const {
  371. return _base;
  372. }
  373. ////////////////////////////////////////////////////////////////////
  374. // Function: RefCountProxy::init_type
  375. // Access: Public
  376. // Description:
  377. ////////////////////////////////////////////////////////////////////
  378. template<class Base>
  379. void RefCountProxy<Base>::
  380. init_type() {
  381. do_init_type(Base);
  382. register_type(_type_handle,
  383. "RefCountProxy<" + get_type_handle(Base).get_name() + ">",
  384. get_type_handle(Base));
  385. }
  386. ////////////////////////////////////////////////////////////////////
  387. // Function: RefCountObj::Constructor
  388. // Access: Public
  389. // Description:
  390. ////////////////////////////////////////////////////////////////////
  391. template<class Base>
  392. INLINE RefCountObj<Base>::
  393. RefCountObj() {
  394. }
  395. ////////////////////////////////////////////////////////////////////
  396. // Function: RefCountObj::Copy Constructor
  397. // Access: Public
  398. // Description:
  399. ////////////////////////////////////////////////////////////////////
  400. template<class Base>
  401. INLINE RefCountObj<Base>::
  402. RefCountObj(const Base &copy) : Base(copy) {
  403. }
  404. ////////////////////////////////////////////////////////////////////
  405. // Function: RefCountObj::init_type
  406. // Access: Public
  407. // Description:
  408. ////////////////////////////////////////////////////////////////////
  409. template<class Base>
  410. void RefCountObj<Base>::
  411. init_type() {
  412. #ifdef HAVE_RTTI
  413. // If we have RTTI, we can determine the name of the base type.
  414. string base_name = typeid(Base).name();
  415. #else
  416. string base_name = "unknown";
  417. #endif
  418. TypeHandle base_type = register_dynamic_type(base_name);
  419. ReferenceCount::init_type();
  420. _type_handle =
  421. register_dynamic_type("RefCountObj<" + base_name + ">",
  422. base_type, ReferenceCount::get_class_type());
  423. }