home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / REFCNT.HPP < prev    next >
C/C++ Source or Header  |  1997-07-05  |  5KB  |  202 lines

  1. // +++Date last modified: 05-Jul-1997
  2.  
  3. //
  4. // A little attempt to maintain a reference-counting generic class based
  5. // on templates.  The purpose is to allow the STL to contain inherited
  6. // objects via pointers to the base class.
  7. //
  8. // Released to the public domain by the author, Darin McBride
  9. // The author retains copyright.  Please send bugs (and, hopefully
  10. // bugfixes as well) to the author: darin.mcbride@tower.alive.ampr.ab.ca
  11. // The author can be reached in C_PLUSPLUS on the Fidonet backbone
  12. // (often to the chagrin of other participants <G>)
  13. //
  14. // Usage Notes:
  15. //       - Always use RefCount<base_class>, not RefCount<derived_class>
  16. //         or RefCount<base_class*>.  The template parameter must be the
  17. //         base class, not a pointer to it!
  18. //       - this class expects that pointers given to it are then
  19. //         OWNED by this class.
  20. //       - Giving actual objects to the class will result in a
  21. //         COPY of that object being owned by the class.  This requires
  22. //         that a copy constructor exists for that object.
  23. //       - Do not *ever* manually delete a pointer stored in this class;
  24. //         assign a NULL pointer to it instead if the object must be deleted
  25. //         before the pointer.
  26.  
  27. #ifndef __REF_COUNT_HPP
  28. #define __REF_COUNT_HPP
  29.  
  30. #ifndef NULL
  31. #define NULL ((void*)0)
  32. #endif
  33.  
  34. template <class T>
  35. class RefCount
  36. {
  37.     friend ostream& operator<<(ostream&, const RefCount&);
  38.     public:
  39.         // typedefs for later use
  40.         typedef T& reference;
  41.         typedef const T& const_reference;
  42.         typedef T* pointer;
  43.         typedef T const* pointer_to_const;
  44.         typedef T* const const_pointer;
  45.  
  46.     private:
  47.         pointer value;
  48.         int*    refcnt;
  49.  
  50.         // utility functions:
  51.         void InitRefCnt();
  52.         void ReleaseRefCnt();
  53.         void IncRefCnt();
  54.  
  55.         void ReleaseThis();
  56.  
  57.     public:
  58.         RefCount();
  59.         RefCount(const_pointer p);
  60.         RefCount(const RefCount& rc);
  61.  
  62.         ~RefCount();
  63.  
  64.         RefCount& operator=(const RefCount& rc);
  65.         RefCount& operator=(const_pointer val);
  66.  
  67.         reference operator*() const;
  68.         const_pointer operator->() const;
  69.         operator const_pointer() const;
  70.  
  71.         bool operator==(RefCount&) const;
  72. };
  73.  
  74. template <class T>
  75. inline ostream& operator<<(ostream& os, const RefCount<T>& rc)
  76. {
  77.     return os << *rc.value;
  78. }
  79.  
  80. template <class T>
  81. inline void RefCount::InitRefCnt()
  82. {
  83.     Assert(refcnt == NULL);
  84. #ifdef PROVE_IT_WORKS_DAMMIT
  85.     cout << "Initializing refcnt" << endl;
  86. #endif
  87.     refcnt = new int(1);
  88. }
  89.  
  90. template <class T>
  91. inline void RefCount::ReleaseRefCnt()
  92. {
  93.     Assert(refcnt != NULL);
  94.     Assert(*refcnt == 0);
  95. #ifdef PROVE_IT_WORKS_DAMMIT
  96.     cout << "Releasing refcnt" << endl;
  97. #endif
  98.     delete refcnt;
  99. }
  100.  
  101. template <class T>
  102. inline void RefCount::IncRefCnt()
  103. {
  104.     Assert(refcnt != NULL);
  105.     Assert(*refcnt > 0);
  106.     ++(*refcnt);
  107. #ifdef PROVE_IT_WORKS_DAMMIT
  108.     cout << "refcnt incremented to " << *refcnt << endl;
  109. #endif
  110. }
  111.  
  112. template <class T>
  113. inline void RefCount::ReleaseThis()
  114. {
  115.     Assert(refcnt != NULL);
  116.     Assert(*refcnt > 0);
  117. #ifdef PROVE_IT_WORKS_DAMMIT
  118.     cout << "refcnt being decremented from " << *refcnt << endl;
  119. #endif
  120.     if (--(*refcnt) == 0) {
  121.         ReleaseRefCnt();
  122.         delete value;
  123.     }
  124. }
  125.  
  126. template <class T>
  127. inline RefCount::RefCount() : value(NULL), refcnt(0)
  128. {
  129.     InitRefCnt();
  130. }
  131.  
  132. template <class T>
  133. inline RefCount::RefCount(const_pointer p) : value(p), refcnt(0)
  134. {
  135.     InitRefCnt();
  136. }
  137.  
  138. template <class T>
  139. inline RefCount::RefCount(const RefCount& rc) : value(rc.value), refcnt(rc.refcnt)
  140. {
  141.     IncRefCnt();
  142. }
  143.  
  144. template <class T>
  145. inline RefCount::~RefCount()
  146. {
  147.     ReleaseThis();
  148. }
  149.  
  150. template <class T>
  151. RefCount& RefCount::operator=(const RefCount& rc)
  152. {
  153.     if (this != &rc)
  154.     {
  155.         ReleaseThis();
  156.         value  = rc.value;
  157.         refcnt = rc.refcnt;
  158.         IncRefCnt();
  159.     }
  160.  
  161.     return *this;
  162. }
  163.  
  164. template <class T>
  165. RefCount& RefCount::operator=(const_pointer val)
  166. {
  167.     ReleaseThis();
  168.     refcnt = NULL; // we don't want to refer to the old reference count
  169.     InitRefCnt();
  170.     value = val;
  171.  
  172.     return *this;
  173. }
  174.  
  175. template <class T>
  176. RefCount::reference RefCount::operator*() const
  177. {
  178.     return *value;
  179. }
  180.  
  181. template <class T>
  182. RefCount::const_pointer RefCount::operator->() const
  183. {
  184.     return value;
  185. }
  186.  
  187. template <class T>
  188. RefCount::operator RefCount::const_pointer() const
  189. {
  190.     return value;
  191. }
  192.  
  193. template <class T>
  194. bool RefCount::operator==(const RefCount& rc) const
  195. {
  196.     if (&rc == this || rc.refcnt == refcnt)
  197.         return true;
  198.     return *value == *rc.value;
  199. }
  200.  
  201. #endif // __REF_COUNT_HPP
  202.