IReferenceCounted.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // Copyright (C) 2002-2012 Nikolaus Gebhardt
  2. // This file is part of the "Irrlicht Engine".
  3. // For conditions of distribution and use, see copyright notice in irrlicht.h
  4. #ifndef IRR_I_IREFERENCE_COUNTED_H_INCLUDED
  5. #define IRR_I_IREFERENCE_COUNTED_H_INCLUDED
  6. #include "irrTypes.h"
  7. #ifdef _IRR_COMPILE_WITH_LEAK_HUNTER_
  8. #include "leakHunter.h"
  9. #endif
  10. namespace irr
  11. {
  12. //! Base class of most objects of the Irrlicht Engine.
  13. /** This class provides reference counting through the methods grab() and drop().
  14. It also is able to store a debug string for every instance of an object.
  15. Most objects of the Irrlicht
  16. Engine are derived from IReferenceCounted, and so they are reference counted.
  17. When you create an object in the Irrlicht engine, calling a method
  18. which starts with 'create', an object is created, and you get a pointer
  19. to the new object. If you no longer need the object, you have
  20. to call drop(). This will destroy the object, if grab() was not called
  21. in another part of you program, because this part still needs the object.
  22. Note, that you only need to call drop() to the object, if you created it,
  23. and the method had a 'create' in it.
  24. A simple example:
  25. If you want to create a texture, you may want to call an imaginable method
  26. IDriver::createTexture. You call
  27. ITexture* texture = driver->createTexture(dimension2d<u32>(128, 128));
  28. If you no longer need the texture, call texture->drop().
  29. If you want to load a texture, you may want to call imaginable method
  30. IDriver::loadTexture. You do this like
  31. ITexture* texture = driver->loadTexture("example.jpg");
  32. You will not have to drop the pointer to the loaded texture, because
  33. the name of the method does not start with 'create'. The texture
  34. is stored somewhere by the driver.
  35. */
  36. class IReferenceCounted
  37. {
  38. public:
  39. //! Constructor.
  40. IReferenceCounted()
  41. : DebugName(0), ReferenceCounter(1)
  42. {
  43. #ifdef _IRR_COMPILE_WITH_LEAK_HUNTER_
  44. LeakHunter::addObject(this);
  45. #endif
  46. }
  47. //! Destructor.
  48. virtual ~IReferenceCounted()
  49. {
  50. #ifdef _IRR_COMPILE_WITH_LEAK_HUNTER_
  51. LeakHunter::removeObject(this);
  52. #endif
  53. }
  54. //! Grabs the object. Increments the reference counter by one.
  55. /** Someone who calls grab() to an object, should later also
  56. call drop() to it. If an object never gets as much drop() as
  57. grab() calls, it will never be destroyed. The
  58. IReferenceCounted class provides a basic reference counting
  59. mechanism with its methods grab() and drop(). Most objects of
  60. the Irrlicht Engine are derived from IReferenceCounted, and so
  61. they are reference counted.
  62. When you create an object in the Irrlicht engine, calling a
  63. method which starts with 'create', an object is created, and
  64. you get a pointer to the new object. If you no longer need the
  65. object, you have to call drop(). This will destroy the object,
  66. if grab() was not called in another part of you program,
  67. because this part still needs the object. Note, that you only
  68. need to call drop() to the object, if you created it, and the
  69. method had a 'create' in it.
  70. A simple example:
  71. If you want to create a texture, you may want to call an
  72. imaginable method IDriver::createTexture. You call
  73. ITexture* texture = driver->createTexture(dimension2d<u32>(128, 128));
  74. If you no longer need the texture, call texture->drop().
  75. If you want to load a texture, you may want to call imaginable
  76. method IDriver::loadTexture. You do this like
  77. ITexture* texture = driver->loadTexture("example.jpg");
  78. You will not have to drop the pointer to the loaded texture,
  79. because the name of the method does not start with 'create'.
  80. The texture is stored somewhere by the driver. */
  81. void grab() const { ++ReferenceCounter; }
  82. //! Drops the object. Decrements the reference counter by one.
  83. /** The IReferenceCounted class provides a basic reference
  84. counting mechanism with its methods grab() and drop(). Most
  85. objects of the Irrlicht Engine are derived from
  86. IReferenceCounted, and so they are reference counted.
  87. When you create an object in the Irrlicht engine, calling a
  88. method which starts with 'create', an object is created, and
  89. you get a pointer to the new object. If you no longer need the
  90. object, you have to call drop(). This will destroy the object,
  91. if grab() was not called in another part of you program,
  92. because this part still needs the object. Note, that you only
  93. need to call drop() to the object, if you created it, and the
  94. method had a 'create' in it.
  95. A simple example:
  96. If you want to create a texture, you may want to call an
  97. imaginable method IDriver::createTexture. You call
  98. ITexture* texture = driver->createTexture(dimension2d<u32>(128, 128));
  99. If you no longer need the texture, call texture->drop().
  100. If you want to load a texture, you may want to call imaginable
  101. method IDriver::loadTexture. You do this like
  102. ITexture* texture = driver->loadTexture("example.jpg");
  103. You will not have to drop the pointer to the loaded texture,
  104. because the name of the method does not start with 'create'.
  105. The texture is stored somewhere by the driver.
  106. \return True, if the object was deleted. */
  107. bool drop() const
  108. {
  109. // someone is doing bad reference counting.
  110. IRR_DEBUG_BREAK_IF(ReferenceCounter <= 0)
  111. --ReferenceCounter;
  112. if (!ReferenceCounter)
  113. {
  114. delete this;
  115. return true;
  116. }
  117. return false;
  118. }
  119. //! Get the reference count.
  120. /** \return Current value of the reference counter. */
  121. s32 getReferenceCount() const
  122. {
  123. return ReferenceCounter;
  124. }
  125. //! Returns the debug name of the object.
  126. /** The Debugname may only be set and changed by the object
  127. itself. This method should only be used in Debug mode.
  128. \return Returns a string, previously set by setDebugName(); */
  129. const c8* getDebugName() const
  130. {
  131. return DebugName;
  132. }
  133. protected:
  134. //! Sets the debug name of the object.
  135. /** The Debugname may only be set and changed by the object
  136. itself. This method should only be used in Debug mode.
  137. \param newName: New debug name to set. */
  138. void setDebugName(const c8* newName)
  139. {
  140. DebugName = newName;
  141. }
  142. private:
  143. //! The debug name.
  144. const c8* DebugName;
  145. //! The reference counter. Mutable to do reference counting on const objects.
  146. mutable s32 ReferenceCounter;
  147. };
  148. } // end namespace irr
  149. #endif