referenceCount.I 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  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 != deleted_ref_count);
  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. TAU_PROFILE("ReferenceCount::~ReferenceCount()", " ", TAU_USER);
  100. nassertv(this != NULL);
  101. // If this assertion fails, we're trying to delete an object that
  102. // was just deleted. Possibly you used a real pointer instead of a
  103. // PointerTo at some point, and the object was deleted when the
  104. // PointerTo went out of scope. Maybe you tried to create an
  105. // automatic (local variable) instance of a class that derives from
  106. // ReferenceCount. Or maybe your headers are out of sync, and you
  107. // need to make clean in direct or some higher tree.
  108. nassertv(_ref_count != deleted_ref_count);
  109. // If this assertion fails, we're trying to delete a static object
  110. // that still has an outstanding reference count. You should make
  111. // sure that all references to your static objects are gone by the
  112. // time the object itself destructs.
  113. nassertv(_ref_count <= local_ref_count);
  114. // If this assertion fails, the reference counts are all screwed
  115. // up altogether. Maybe some errant code stomped all over memory
  116. // somewhere.
  117. nassertv(_ref_count >= 0);
  118. // If this assertion fails, someone tried to delete this object
  119. // while its reference count was still positive. Maybe you tried
  120. // to point a PointerTo at a static object (a local variable,
  121. // instead of one allocated via new)? The test below against 0x7f
  122. // is supposed to check for that, but it's a pretty hokey test.
  123. // Another possibility is you inadvertently omitted a copy
  124. // constructor for a ReferenceCount object, and then bitwise
  125. // copied a dynamically allocated value--reference count and
  126. // all--onto a locally allocated one.
  127. nassertv(_ref_count == 0 || _ref_count == local_ref_count);
  128. // Tell our weak reference holders that we're going away now.
  129. if (_weak_list != (WeakReferenceList *)NULL) {
  130. delete _weak_list;
  131. _weak_list = (WeakReferenceList *)NULL;
  132. }
  133. #ifndef NDEBUG
  134. // Ok, all clear to delete. Now set the reference count to
  135. // deleted_ref_count, so we'll have a better chance of noticing if
  136. // we happen to have a stray pointer to it still out there.
  137. _ref_count = deleted_ref_count;
  138. #endif
  139. #ifdef DO_MEMORY_USAGE
  140. MemoryUsage::remove_pointer(this);
  141. #endif
  142. }
  143. ////////////////////////////////////////////////////////////////////
  144. // Function: ReferenceCount::get_ref_count
  145. // Access: Published
  146. // Description: Returns the current reference count.
  147. ////////////////////////////////////////////////////////////////////
  148. INLINE int ReferenceCount::
  149. get_ref_count() const {
  150. #ifdef _DEBUG
  151. test_ref_count_integrity();
  152. #endif
  153. return AtomicAdjust::get(_ref_count);
  154. }
  155. ////////////////////////////////////////////////////////////////////
  156. // Function: ReferenceCount::ref
  157. // Access: Published
  158. // Description: Explicitly increments the reference count. User code
  159. // should avoid using ref() and unref() directly, which
  160. // can result in missed reference counts. Instead, let
  161. // a PointerTo object manage the reference counting
  162. // automatically.
  163. //
  164. // This function is const, even though it changes the
  165. // object, because generally fiddling with an object's
  166. // reference count isn't considered part of fiddling
  167. // with the object. An object might be const in other
  168. // ways, but we still need to accurately count the
  169. // number of references to it.
  170. ////////////////////////////////////////////////////////////////////
  171. INLINE void ReferenceCount::
  172. ref() const {
  173. TAU_PROFILE("void ReferenceCount::ref()", " ", TAU_USER);
  174. #ifdef _DEBUG
  175. nassertv(test_ref_count_integrity());
  176. #endif
  177. AtomicAdjust::inc(((ReferenceCount *)this)->_ref_count);
  178. }
  179. ////////////////////////////////////////////////////////////////////
  180. // Function: ReferenceCount::unref
  181. // Access: Published
  182. // Description: Explicitly decrements the reference count. Note that
  183. // the object will not be implicitly deleted by unref()
  184. // simply because the reference count drops to zero.
  185. // (Having a member function delete itself is
  186. // problematic; plus, we don't have a virtual destructor
  187. // anyway.) However, see the helper function
  188. // unref_delete().
  189. //
  190. // User code should avoid using ref() and unref()
  191. // directly, which can result in missed reference
  192. // counts. Instead, let a PointerTo object manage the
  193. // reference counting automatically.
  194. //
  195. // This function is const, even though it changes the
  196. // object, because generally fiddling with an object's
  197. // reference count isn't considered part of fiddling
  198. // with the object. An object might be const in other
  199. // ways, but we still need to accurately count the
  200. // number of references to it.
  201. //
  202. // The return value is true if the new reference count
  203. // is nonzero, false if it is zero.
  204. ////////////////////////////////////////////////////////////////////
  205. INLINE bool ReferenceCount::
  206. unref() const {
  207. TAU_PROFILE("void ReferenceCount::unref()", " ", TAU_USER);
  208. #ifdef _DEBUG
  209. nassertr(test_ref_count_integrity(), 0);
  210. // If this assertion fails, you tried to unref an object with a
  211. // zero reference count. Are you using ref() and unref()
  212. // directly? Are you sure you can't use PointerTo's?
  213. nassertr(_ref_count > 0, 0);
  214. #endif
  215. return AtomicAdjust::dec(((ReferenceCount *)this)->_ref_count);
  216. }
  217. ////////////////////////////////////////////////////////////////////
  218. // Function: ReferenceCount::test_ref_count_integrity
  219. // Access: Published
  220. // Description: Does some easy checks to make sure that the reference
  221. // count isn't completely bogus. Returns true if ok,
  222. // false otherwise.
  223. ////////////////////////////////////////////////////////////////////
  224. INLINE bool ReferenceCount::
  225. test_ref_count_integrity() const {
  226. #ifndef NDEBUG
  227. return do_test_ref_count_integrity();
  228. #else
  229. return true;
  230. #endif
  231. }
  232. ////////////////////////////////////////////////////////////////////
  233. // Function: ReferenceCount::test_ref_count_nonzero
  234. // Access: Published
  235. // Description: Does some easy checks to make sure that the reference
  236. // count isn't zero, or completely bogus. Returns true
  237. // if ok, false otherwise.
  238. ////////////////////////////////////////////////////////////////////
  239. INLINE bool ReferenceCount::
  240. test_ref_count_nonzero() const {
  241. #ifndef NDEBUG
  242. return do_test_ref_count_nonzero();
  243. #else
  244. return true;
  245. #endif
  246. }
  247. ////////////////////////////////////////////////////////////////////
  248. // Function: ReferenceCount::local_object
  249. // Access: Public
  250. // Description: This function should be called, once, immediately
  251. // after creating a new instance of some
  252. // ReferenceCount-derived object on the stack.
  253. //
  254. // This allows the object to be passed to functions that
  255. // will increment and decrement the object's reference
  256. // count temporarily, and it will prevent the object
  257. // from being deleted (inappropriately), when the
  258. // reference count returns to zero. It actually
  259. // achieves this by setting a large positive value in
  260. // the reference count field.
  261. ////////////////////////////////////////////////////////////////////
  262. INLINE void ReferenceCount::
  263. local_object() {
  264. // If this assertion fails, you didn't call this immediately after
  265. // creating a local object.
  266. nassertv(_ref_count == 0);
  267. _ref_count = local_ref_count;
  268. }
  269. ////////////////////////////////////////////////////////////////////
  270. // Function: ReferenceCount::has_weak_list
  271. // Access: Public
  272. // Description: Returns true if this particular ReferenceCount object
  273. // has a WeakReferenceList created, false otherwise. In
  274. // general, this will be true if there was ever a
  275. // WeakPointerTo created for this object (even if there
  276. // is not any for it now).
  277. ////////////////////////////////////////////////////////////////////
  278. INLINE bool ReferenceCount::
  279. has_weak_list() const {
  280. return _weak_list != (WeakReferenceList *)NULL;
  281. }
  282. ////////////////////////////////////////////////////////////////////
  283. // Function: ReferenceCount::get_weak_list
  284. // Access: Public
  285. // Description: Returns the WeakReferenceList associated with this
  286. // ReferenceCount object. If there has never been a
  287. // WeakReferenceList associated with this object,
  288. // creates one now.
  289. ////////////////////////////////////////////////////////////////////
  290. INLINE WeakReferenceList *ReferenceCount::
  291. get_weak_list() const {
  292. if (_weak_list == (WeakReferenceList *)NULL) {
  293. ((ReferenceCount *)this)->create_weak_list();
  294. }
  295. return _weak_list;
  296. }
  297. ////////////////////////////////////////////////////////////////////
  298. // Function: ReferenceCount::weak_ref
  299. // Access: Public
  300. // Description: Adds the indicated PointerToVoid as a weak reference
  301. // to this object.
  302. ////////////////////////////////////////////////////////////////////
  303. INLINE void ReferenceCount::
  304. weak_ref(WeakPointerToVoid *ptv) {
  305. TAU_PROFILE("void ReferenceCount::weak_ref()", " ", TAU_USER);
  306. get_weak_list()->add_reference(ptv);
  307. }
  308. ////////////////////////////////////////////////////////////////////
  309. // Function: ReferenceCount::weak_unref
  310. // Access: Public
  311. // Description: Removes the indicated PointerToVoid as a weak reference
  312. // to this object. It must have previously been added
  313. // via a call to weak_ref().
  314. ////////////////////////////////////////////////////////////////////
  315. INLINE void ReferenceCount::
  316. weak_unref(WeakPointerToVoid *ptv) {
  317. TAU_PROFILE("void ReferenceCount::weak_unref()", " ", TAU_USER);
  318. nassertv(has_weak_list());
  319. _weak_list->clear_reference(ptv);
  320. }
  321. ////////////////////////////////////////////////////////////////////
  322. // Function: DeleteWrapper::do_delete
  323. // Access: Public, Static
  324. // Description: This helper function encapsulates calling the
  325. // destructor and delete operator for the given pointer.
  326. // A pointer to this function is passed to the global
  327. // ObjectDeletor, when there is one.
  328. ////////////////////////////////////////////////////////////////////
  329. template<class ObjectType>
  330. void DeleteWrapper<ObjectType>::
  331. do_delete(void *ptr) {
  332. TAU_PROFILE("void DeleteWrapper::do_delete(void *)", " ", TAU_USER);
  333. delete ((ObjectType *)ptr);
  334. }
  335. ////////////////////////////////////////////////////////////////////
  336. // Function: RefCountDeleteWrapper::do_delete
  337. // Access: Public, Static
  338. // Description: This is similar to DeleteWrapper::do_delete(), above,
  339. // except it is specialized for an object that inherits
  340. // from ReferenceCount, and it will check that some
  341. // other pointer hasn't incremented the reference count
  342. // in the interim before the pointer is actually
  343. // deleted.
  344. ////////////////////////////////////////////////////////////////////
  345. template<class RefCountType>
  346. void RefCountDeleteWrapper<RefCountType>::
  347. do_delete(void *ptr) {
  348. TAU_PROFILE("void RefCountDeleteWrapper::do_delete(void *)", " ", TAU_USER);
  349. if (!((RefCountType *)ptr)->unref()) {
  350. // The reference count has reached 0; time to delete the pointer.
  351. delete ((RefCountType *)ptr);
  352. }
  353. }
  354. ////////////////////////////////////////////////////////////////////
  355. // Function: unref_delete
  356. // Description: This global helper function will unref the given
  357. // ReferenceCount object, and if the reference count
  358. // reaches zero, automatically delete it. It can't be a
  359. // member function because it's usually a bad idea to
  360. // delete an object from within its own member function.
  361. // It's a template function so the destructor doesn't
  362. // have to be virtual.
  363. ////////////////////////////////////////////////////////////////////
  364. template<class RefCountType>
  365. INLINE void
  366. unref_delete(RefCountType *ptr) {
  367. TAU_PROFILE("void unref_delete(RefCountType *)", " ", TAU_USER);
  368. // Although it may be tempting to try to upcast ptr to a
  369. // ReferenceCount object (particularly to get around inheritance
  370. // issues), resist that temptation, since some classes (in
  371. // particular, TransformState and RenderState) rely on a non-virtual
  372. // overloading of the unref() method.
  373. if (!ptr->unref()) {
  374. // The reference count has reached 0; time to delete the pointer.
  375. // Is there a deletor in effect? If so, pass it to that object.
  376. ObjectDeletor *deletor = ObjectDeletor::get_global_ptr();
  377. if (deletor != (ObjectDeletor *)NULL) {
  378. // Re-ref the pointer before adding it to the deletor. The
  379. // deletor will de-ref it again before deleting it.
  380. ptr->ref();
  381. deletor->delete_object(RefCountDeleteWrapper<RefCountType>::do_delete, (void *)ptr);
  382. return;
  383. }
  384. // If there's no deletor, just delete the pointer now.
  385. delete ptr;
  386. }
  387. }
  388. ////////////////////////////////////////////////////////////////////
  389. // Function: defer_delete
  390. // Description: This global helper function is designed to be called
  391. // in lieu of the delete operator on any type of object
  392. // (except for an object that inherits from
  393. // ReferenceCount, of course, since you should never
  394. // call delete explicitly on a reference-counted
  395. // object).
  396. //
  397. // This function will ultimately have the same effect as
  398. // calling delete on the object. If a ObjectDeletor
  399. // is currently in effect, the delete will happen at
  400. // some later time; but if a ObjectDeletor is not in
  401. // effect, the delete will happen immediately.
  402. //
  403. // You should not attempt to replace an array-delete
  404. // call, e.g. delete[] array, with a call to
  405. // defer_delete(). This only replaces single-object
  406. // deletes, e.g. delete object.
  407. ////////////////////////////////////////////////////////////////////
  408. template<class ObjectType>
  409. INLINE void
  410. defer_delete(ObjectType *ptr) {
  411. TAU_PROFILE("void defer_delete(ObjectType *)", " ", TAU_USER);
  412. ObjectDeletor *deletor = ObjectDeletor::get_global_ptr();
  413. if (deletor != (ObjectDeletor *)NULL) {
  414. deletor->delete_object(DeleteWrapper<ObjectType>::do_delete, (void *)ptr);
  415. return;
  416. }
  417. // If there's no deletor, just delete the pointer now.
  418. delete ptr;
  419. }
  420. ////////////////////////////////////////////////////////////////////
  421. // Function: RefCountProxy::Constructor
  422. // Access: Public
  423. // Description:
  424. ////////////////////////////////////////////////////////////////////
  425. template<class Base>
  426. INLINE RefCountProxy<Base>::
  427. RefCountProxy() {
  428. }
  429. ////////////////////////////////////////////////////////////////////
  430. // Function: RefCountProxy::Copy Constructor
  431. // Access: Public
  432. // Description:
  433. ////////////////////////////////////////////////////////////////////
  434. template<class Base>
  435. INLINE RefCountProxy<Base>::
  436. RefCountProxy(const Base &copy) : _base(copy) {
  437. }
  438. ////////////////////////////////////////////////////////////////////
  439. // Function: RefCountProxy::Base Typecast Operator
  440. // Access: Public
  441. // Description:
  442. ////////////////////////////////////////////////////////////////////
  443. template<class Base>
  444. INLINE RefCountProxy<Base>::
  445. operator Base &() {
  446. return _base;
  447. }
  448. ////////////////////////////////////////////////////////////////////
  449. // Function: RefCountProxy::Base Typecast Operator
  450. // Access: Public
  451. // Description:
  452. ////////////////////////////////////////////////////////////////////
  453. template<class Base>
  454. INLINE RefCountProxy<Base>::
  455. operator const Base &() const {
  456. return _base;
  457. }
  458. ////////////////////////////////////////////////////////////////////
  459. // Function: RefCountProxy::init_type
  460. // Access: Public
  461. // Description:
  462. ////////////////////////////////////////////////////////////////////
  463. template<class Base>
  464. void RefCountProxy<Base>::
  465. init_type() {
  466. do_init_type(Base);
  467. register_type(_type_handle,
  468. "RefCountProxy<" + get_type_handle(Base).get_name() + ">",
  469. get_type_handle(Base));
  470. }
  471. ////////////////////////////////////////////////////////////////////
  472. // Function: RefCountObj::Constructor
  473. // Access: Public
  474. // Description:
  475. ////////////////////////////////////////////////////////////////////
  476. template<class Base>
  477. INLINE RefCountObj<Base>::
  478. RefCountObj() {
  479. }
  480. ////////////////////////////////////////////////////////////////////
  481. // Function: RefCountObj::Copy Constructor
  482. // Access: Public
  483. // Description:
  484. ////////////////////////////////////////////////////////////////////
  485. template<class Base>
  486. INLINE RefCountObj<Base>::
  487. RefCountObj(const Base &copy) : Base(copy) {
  488. }
  489. ////////////////////////////////////////////////////////////////////
  490. // Function: RefCountObj::init_type
  491. // Access: Public
  492. // Description:
  493. ////////////////////////////////////////////////////////////////////
  494. template<class Base>
  495. void RefCountObj<Base>::
  496. init_type() {
  497. #if defined(HAVE_RTTI) && !defined(__EDG__)
  498. // If we have RTTI, we can determine the name of the base type.
  499. string base_name = typeid(Base).name();
  500. #else
  501. string base_name = "unknown";
  502. #endif
  503. TypeHandle base_type = register_dynamic_type(base_name);
  504. ReferenceCount::init_type();
  505. _type_handle =
  506. register_dynamic_type("RefCountObj<" + base_name + ">",
  507. base_type, ReferenceCount::get_class_type());
  508. }