SharedPtr.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. //
  2. // "$Id: SharedPtr.h 42122 2017-12-20 09:04:23Z zhang_xiulang $"
  3. //
  4. // Copyright (c)1992-2011, ZheJiang Dahua Technology Stock CO.LTD.
  5. // All Rights Reserved.
  6. //
  7. // Description:
  8. // Revisions: Year-Month-Day SVN-Author Modification
  9. //
  10. #ifndef INFRA_SHARED_PTR_H__
  11. #define INFRA_SHARED_PTR_H__
  12. #include "Detail/smartptr_detail.h"
  13. #include "Detail/shared_count.h"
  14. #if defined(_MSC_VER) && (_MSC_VER < 1300)
  15. #define DAHUA_NO_CV_VOID_SPECIALIZATIONS
  16. #define DAHUA_NO_SFINAE
  17. #define DAHUA_NO_MEMBER_TEMPLATE_FRIENDS
  18. #endif
  19. namespace Dahua {
  20. namespace Memory {
  21. ////////////////////////////////////////////////////////////////////////////////
  22. namespace Detail {
  23. template<class T> struct shared_ptr_traits
  24. {
  25. typedef T & reference;
  26. };
  27. template<> struct shared_ptr_traits<void>
  28. {
  29. typedef void reference;
  30. };
  31. #ifndef DAHUA_NO_CV_VOID_SPECIALIZATIONS
  32. template<> struct shared_ptr_traits<void const>
  33. {
  34. typedef void reference;
  35. };
  36. template<> struct shared_ptr_traits<void volatile>
  37. {
  38. typedef void reference;
  39. };
  40. template<> struct shared_ptr_traits<void const volatile>
  41. {
  42. typedef void reference;
  43. };
  44. #endif
  45. // rvalue auto_ptr support based on a technique by Dave Abrahams
  46. #ifndef DAHUA_NO_SFINAE
  47. template< class T, class R > struct sp_enable_if_auto_ptr
  48. {
  49. };
  50. template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
  51. {
  52. typedef R type;
  53. };
  54. #endif
  55. template< class Y, class T > struct sp_convertible
  56. {
  57. typedef char (&yes) [1];
  58. typedef char (&no) [2];
  59. static yes f( T* );
  60. static no f( ... );
  61. enum _vt { value = sizeof( (f)( static_cast<Y*>(0) ) ) == sizeof(yes) };
  62. };
  63. template< class Y, class T > inline void sp_assert_convertible()
  64. {
  65. typedef char tmp[ sp_convertible< Y, T >::value? 1: -1 ];
  66. (void)sizeof( tmp );
  67. }
  68. } // namespace Detail
  69. ////////////////////////////////////////////////////////////////////////////////
  70. template < class T > class TWeakPtr;
  71. template < class T > class TSharedPtr;
  72. template < class T > class TEnableSharedFromThis;
  73. template< class X, class Y, class T > inline void sp_enable_shared_from_this( TSharedPtr<X> const * ppx, Y const * py, TEnableSharedFromThis< T > const * pe )
  74. {
  75. if( pe != 0 )
  76. {
  77. pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
  78. }
  79. }
  80. inline void sp_enable_shared_from_this( ... )
  81. {
  82. }
  83. template< class T, class Y > inline void sp_pointer_construct( TSharedPtr< T > * ppx, Y * p, Detail::shared_count & pn )
  84. {
  85. Detail::shared_count( p ).swap( pn );
  86. sp_enable_shared_from_this( ppx, p, p );
  87. }
  88. template<class T> class TSharedPtr // noncopyable
  89. {
  90. #ifdef DAHUA_NO_MEMBER_TEMPLATE_FRIENDS
  91. public:
  92. #else
  93. template<class Y> friend class TSharedPtr;
  94. template<class Y> friend class TWeakPtr;
  95. #endif
  96. T* px; // contained pointer
  97. Detail::shared_count pn; // reference counter
  98. public:
  99. typedef TSharedPtr<T> this_type;
  100. typedef T element_type;
  101. typedef T value_type;
  102. typedef T * pointer;
  103. typedef typename Detail::shared_ptr_traits<T>::reference reference;
  104. TSharedPtr(): px(0), pn() // never throws in 1.30+
  105. {
  106. }
  107. template<class Y> explicit TSharedPtr( Y * p ): px( p ), pn( ) // Y must be complete
  108. {
  109. sp_pointer_construct( this, p, pn );
  110. }
  111. //
  112. // Requirements: D's copy constructor must not throw
  113. //
  114. // TSharedPtr will release p by calling d(p)
  115. //
  116. template<class Y, class D> TSharedPtr(Y * p, D d): px(p), pn(p, d)
  117. {
  118. }
  119. // As above, but with allocator. A's copy constructor shall not throw.
  120. template<class Y, class D, class A> TSharedPtr( Y * p, D d, A a ): px( p ), pn( p, d, a )
  121. {
  122. }
  123. // generated copy constructor, assignment, destructor are fine...
  124. // except that Borland C++ has a bug, and g++ with -Wsynth warns
  125. #if defined(__BORLANDC__) || defined(__GNUC__)
  126. TSharedPtr & operator=(TSharedPtr const & r) // never throws
  127. {
  128. px = r.px;
  129. pn = r.pn; // shared_count::op= doesn't throw
  130. return *this;
  131. }
  132. #endif
  133. template<class Y>
  134. TSharedPtr(TSharedPtr<Y> const & r): px(r.px), pn(r.pn) // never throws
  135. {
  136. }
  137. // aliasing
  138. template< class Y >
  139. TSharedPtr( TSharedPtr<Y> const & r, T * p ): px( p ), pn( r.pn ) // never throws
  140. {
  141. }
  142. template<class Y>
  143. TSharedPtr(TSharedPtr<Y> const & r, Detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
  144. {
  145. }
  146. template<class Y>
  147. TSharedPtr(TSharedPtr<Y> const & r, Detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
  148. {
  149. }
  150. template<class Y>
  151. TSharedPtr(TSharedPtr<Y> const & r, Detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
  152. {
  153. if(px == 0) // need to allocate new counter -- the cast failed
  154. {
  155. pn = Detail::shared_count();
  156. }
  157. }
  158. template<class Y>
  159. TSharedPtr(TSharedPtr<Y> const & r, Detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
  160. {
  161. if(px == 0)
  162. {
  163. throw std::bad_cast();
  164. }
  165. }
  166. template<class Y>
  167. explicit TSharedPtr(std::auto_ptr<Y> & r): px(r.get()), pn()
  168. {
  169. Y * tmp = r.get();
  170. pn = Detail::shared_count(r);
  171. }
  172. #ifndef DAHUA_NO_SFINAE
  173. template<class Ap>
  174. TSharedPtr( Ap r, typename Detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
  175. {
  176. typename Ap::element_type * tmp = r.get();
  177. pn = Detail::shared_count( r );
  178. }
  179. #endif
  180. template<class Y>
  181. explicit TSharedPtr(TWeakPtr<Y> const & r): pn( r.m_pn ) // may throw
  182. {
  183. Detail::sp_assert_convertible< Y, T >();
  184. px = r.m_ptr;
  185. }
  186. template<class Y>
  187. explicit TSharedPtr( TWeakPtr<Y> const & r, Detail::sp_nothrow_tag ): px( 0 ), pn( r.m_pn ) // may throw
  188. {
  189. if ( !pn.empty() )
  190. {
  191. px = r.m_ptr;
  192. }
  193. }
  194. template<class Y>
  195. TSharedPtr & operator=(TSharedPtr<Y> const & r) // never throws
  196. {
  197. px = r.px;
  198. pn = r.pn; // shared_count::op= doesn't throw
  199. return *this;
  200. }
  201. template<class Y>
  202. TSharedPtr & operator=( std::auto_ptr<Y> & r )
  203. {
  204. this_type(r).swap(*this);
  205. return *this;
  206. }
  207. #ifndef DAHUA_NO_SFINAE
  208. template<class Ap>
  209. typename Detail::sp_enable_if_auto_ptr< Ap, TSharedPtr & >::type operator=( Ap r )
  210. {
  211. this_type( r ).swap( *this );
  212. return *this;
  213. }
  214. #endif
  215. void reset() // never throws in 1.30+
  216. {
  217. this_type().swap(*this);
  218. }
  219. template<class Y> void reset(Y * p) // Y must be complete
  220. {
  221. assert(p == 0 || p != px); // catch self-reset errors
  222. this_type(p).swap(*this);
  223. }
  224. template<class Y, class D> void reset( Y * p, D d )
  225. {
  226. this_type( p, d ).swap( *this );
  227. }
  228. template<class Y, class D, class A> void reset( Y * p, D d, A a )
  229. {
  230. this_type( p, d, a ).swap( *this );
  231. }
  232. template<class Y> void reset( TSharedPtr<Y> const & r, T * p )
  233. {
  234. this_type( r, p ).swap( *this );
  235. }
  236. reference operator* () const // never throws
  237. {
  238. assert(px != 0);
  239. return *px;
  240. }
  241. T * operator-> () const // never throws
  242. {
  243. assert(px != 0);
  244. return px;
  245. }
  246. T * get() const // never throws
  247. {
  248. return px;
  249. }
  250. // implicit conversion to "bool"
  251. typedef T * this_type::*unspecified_bool_type;
  252. operator unspecified_bool_type() const // never throws
  253. {
  254. return px == 0? 0: &this_type::px;
  255. }
  256. // operator! is redundant, but some compilers need it
  257. bool operator! () const // never throws
  258. {
  259. return px == 0;
  260. }
  261. bool unique() const // never throws
  262. {
  263. return pn.unique();
  264. }
  265. long use_count() const // never throws
  266. {
  267. return pn.use_count();
  268. }
  269. void swap(TSharedPtr<T> & other) // never throws
  270. {
  271. std::swap(px, other.px);
  272. pn.swap(other.pn);
  273. }
  274. template<class Y> bool _internal_less(TSharedPtr<Y> const & rhs) const
  275. {
  276. return pn < rhs.pn;
  277. }
  278. void * _internal_get_deleter(std::type_info const & ti) const
  279. {
  280. return pn.get_deleter(ti);
  281. }
  282. };
  283. } // namespace Memory
  284. } // namespace Dahua
  285. ////////////////////////////////////////////////////////////////////////////////
  286. template<class T, class U> inline bool operator==(Dahua::Memory::TSharedPtr<T> const & a, Dahua::Memory::TSharedPtr<U> const & b)
  287. {
  288. return a.get() == b.get();
  289. }
  290. template<class T, class U> inline bool operator!=(Dahua::Memory::TSharedPtr<T> const & a, Dahua::Memory::TSharedPtr<U> const & b)
  291. {
  292. return a.get() != b.get();
  293. }
  294. #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
  295. // Resolve the ambiguity between our op!= and the one in rel_ops
  296. template<class T> inline bool operator!=(Dahua::Memory::TSharedPtr<T> const & a, Dahua::Memory::TSharedPtr<T> const & b)
  297. {
  298. return a.get() != b.get();
  299. }
  300. #endif
  301. template<class T, class U> inline bool operator<(Dahua::Memory::TSharedPtr<T> const & a, Dahua::Memory::TSharedPtr<U> const & b)
  302. {
  303. return a._internal_less(b);
  304. }
  305. template<class T> inline void swap(Dahua::Memory::TSharedPtr<T> & a, Dahua::Memory::TSharedPtr<T> & b)
  306. {
  307. a.swap(b);
  308. }
  309. template<class T, class U> Dahua::Memory::TSharedPtr<T> static_pointer_cast(Dahua::Memory::TSharedPtr<U> const & r)
  310. {
  311. return Dahua::Memory::TSharedPtr<T>(r, Dahua::Memory::Detail::static_cast_tag());
  312. }
  313. template<class T, class U> Dahua::Memory::TSharedPtr<T> const_pointer_cast(Dahua::Memory::TSharedPtr<U> const & r)
  314. {
  315. return Dahua::Memory::TSharedPtr<T>(r, Dahua::Memory::Detail::const_cast_tag());
  316. }
  317. template<class T, class U> Dahua::Memory::TSharedPtr<T> dynamic_pointer_cast(Dahua::Memory::TSharedPtr<U> const & r)
  318. {
  319. return Dahua::Memory::TSharedPtr<T>(r, Dahua::Memory::Detail::dynamic_cast_tag());
  320. }
  321. // get_pointer(p) is a generic way to say p.get()
  322. template<class T> inline T * get_pointer(Dahua::Memory::TSharedPtr<T> const & p)
  323. {
  324. return p.get();
  325. }
  326. // get_deleter
  327. template<class D, class T> D * get_deleter(Dahua::Memory::TSharedPtr<T> const & p)
  328. {
  329. return static_cast<D *>(p._internal_get_deleter(typeid(D)));
  330. }
  331. #endif // INFRA_SHARED_PTR_H__