shared_count.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #ifndef __DAHUA_MEMORY_SHAREDPTR_COUNT_H__
  2. #define __DAHUA_MEMORY_SHAREDPTR_COUNT_H__
  3. #include <memory> // std::auto_ptr
  4. #include <functional> // std::less
  5. #include <new> // std::bad_alloc
  6. #include <typeinfo> // std::type_info in get_deleter
  7. #include "sp_counted_impl.hpp"
  8. #include "checked_delete.hpp"
  9. namespace Dahua {
  10. namespace Memory {
  11. namespace Detail {
  12. struct sp_nothrow_tag {};
  13. class weak_count;
  14. class shared_count
  15. {
  16. private:
  17. sp_counted_base * pi_;
  18. friend class weak_count;
  19. public:
  20. shared_count(): pi_(0)
  21. {
  22. }
  23. template<class Y> explicit shared_count( Y * p ): pi_( 0 )
  24. {
  25. try
  26. {
  27. pi_ = new sp_counted_impl_p<Y>( p );
  28. }
  29. catch(...)
  30. {
  31. Detail::checked_delete( p );
  32. throw;
  33. }
  34. }
  35. template<class P, class D> shared_count( P p, D d ): pi_(0)
  36. {
  37. try
  38. {
  39. pi_ = new sp_counted_impl_pd<P, D>(p, d);
  40. }
  41. catch(...)
  42. {
  43. d(p); // delete p
  44. throw;
  45. }
  46. }
  47. template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 )
  48. {
  49. typedef sp_counted_impl_pda<P, D, A> impl_type;
  50. typedef typename A::template rebind< impl_type >::other A2;
  51. A2 a2( a );
  52. try
  53. {
  54. pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
  55. new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
  56. }
  57. catch(...)
  58. {
  59. d( p );
  60. if( pi_ != 0 )
  61. {
  62. a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
  63. }
  64. throw;
  65. }
  66. }
  67. // auto_ptr<Y> is special cased to provide the strong guarantee
  68. template<class Y>
  69. explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) )
  70. {
  71. assert(pi_ != 0);
  72. r.release();
  73. }
  74. ~shared_count() // nothrow
  75. {
  76. if( pi_ != 0 ) pi_->release();
  77. }
  78. shared_count(shared_count const & r): pi_(r.pi_) // nothrow
  79. {
  80. if( pi_ != 0 ) pi_->add_ref_copy();
  81. }
  82. explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
  83. shared_count & operator= (shared_count const & r) // nothrow
  84. {
  85. sp_counted_base * tmp = r.pi_;
  86. if( tmp != pi_ )
  87. {
  88. if( tmp != 0 ) tmp->add_ref_copy();
  89. if( pi_ != 0 ) pi_->release();
  90. pi_ = tmp;
  91. }
  92. return *this;
  93. }
  94. void swap(shared_count & r) // nothrow
  95. {
  96. sp_counted_base * tmp = r.pi_;
  97. r.pi_ = pi_;
  98. pi_ = tmp;
  99. }
  100. long use_count() const // nothrow
  101. {
  102. return pi_ != 0? pi_->use_count(): 0;
  103. }
  104. bool unique() const // nothrow
  105. {
  106. return use_count() == 1;
  107. }
  108. bool empty() const // nothrow
  109. {
  110. return pi_ == 0;
  111. }
  112. friend inline bool operator==(shared_count const & a, shared_count const & b)
  113. {
  114. return a.pi_ == b.pi_;
  115. }
  116. friend inline bool operator<(shared_count const & a, shared_count const & b)
  117. {
  118. return std::less<sp_counted_base *>()( a.pi_, b.pi_ );
  119. }
  120. void * get_deleter( std::type_info const & ti ) const
  121. {
  122. return pi_? pi_->get_deleter( ti ): 0;
  123. }
  124. };
  125. class weak_count
  126. {
  127. private:
  128. sp_counted_base * pi_;
  129. friend class shared_count;
  130. public:
  131. weak_count(): pi_(0) // nothrow
  132. {
  133. }
  134. weak_count(shared_count const & r): pi_(r.pi_) // nothrow
  135. {
  136. if(pi_ != 0) pi_->weak_add_ref();
  137. }
  138. weak_count(weak_count const & r): pi_(r.pi_) // nothrow
  139. {
  140. if(pi_ != 0) pi_->weak_add_ref();
  141. }
  142. ~weak_count() // nothrow
  143. {
  144. if(pi_ != 0) pi_->weak_release();
  145. }
  146. weak_count & operator= (shared_count const & r) // nothrow
  147. {
  148. sp_counted_base * tmp = r.pi_;
  149. if( tmp != pi_ )
  150. {
  151. if(tmp != 0) tmp->weak_add_ref();
  152. if(pi_ != 0) pi_->weak_release();
  153. pi_ = tmp;
  154. }
  155. return *this;
  156. }
  157. weak_count & operator= (weak_count const & r) // nothrow
  158. {
  159. sp_counted_base * tmp = r.pi_;
  160. if( tmp != pi_ )
  161. {
  162. if(tmp != 0) tmp->weak_add_ref();
  163. if(pi_ != 0) pi_->weak_release();
  164. pi_ = tmp;
  165. }
  166. return *this;
  167. }
  168. void swap(weak_count & r) // nothrow
  169. {
  170. sp_counted_base * tmp = r.pi_;
  171. r.pi_ = pi_;
  172. pi_ = tmp;
  173. }
  174. long use_count() const // nothrow
  175. {
  176. return pi_ != 0? pi_->use_count(): 0;
  177. }
  178. bool empty() const // nothrow
  179. {
  180. return pi_ == 0;
  181. }
  182. friend inline bool operator==(weak_count const & a, weak_count const & b)
  183. {
  184. return a.pi_ == b.pi_;
  185. }
  186. friend inline bool operator<(weak_count const & a, weak_count const & b)
  187. {
  188. return std::less<sp_counted_base *>()(a.pi_, b.pi_);
  189. }
  190. };
  191. inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )
  192. {
  193. if( pi_ != 0 && !pi_->add_ref_lock() )
  194. {
  195. pi_ = 0;
  196. }
  197. }
  198. } // namespace Detail
  199. } // namespace Memory
  200. } // namespace Dahua
  201. #endif // __DAHUA_MEMORY_SHAREDPTR_COUNT_H__