shared_count_132.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. #ifndef BOOST_DETAIL_SHARED_COUNT_132_HPP_INCLUDED
  2. #define BOOST_DETAIL_SHARED_COUNT_132_HPP_INCLUDED
  3. // MS compatible compilers support #pragma once
  4. #if defined(_MSC_VER)
  5. # pragma once
  6. #endif
  7. //
  8. // detail/shared_count.hpp
  9. //
  10. // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
  11. //
  12. // Distributed under the Boost Software License, Version 1.0. (See
  13. // accompanying file LICENSE_1_0.txt or copy at
  14. // http://www.boost.org/LICENSE_1_0.txt)
  15. //
  16. #include <boost/config.hpp>
  17. #if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR)
  18. # error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible.
  19. #endif
  20. #include <boost/checked_delete.hpp>
  21. #include <boost/serialization/throw_exception.hpp>
  22. #include <boost/detail/lightweight_mutex.hpp>
  23. #if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
  24. #include <boost/detail/quick_allocator.hpp>
  25. #endif
  26. #include <memory> // std::auto_ptr, std::allocator
  27. #include <functional> // std::less
  28. #include <exception> // std::exception
  29. #include <new> // std::bad_alloc
  30. #include <typeinfo> // std::type_info in get_deleter
  31. #include <cstddef> // std::size_t
  32. #include <boost/config.hpp> // msvc 6.0 needs this for warning suppression
  33. #if defined(BOOST_NO_STDC_NAMESPACE)
  34. namespace std{
  35. using ::size_t;
  36. } // namespace std
  37. #endif
  38. namespace boost_132 {
  39. // Debug hooks
  40. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  41. void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn);
  42. void sp_array_constructor_hook(void * px);
  43. void sp_scalar_destructor_hook(void * px, std::size_t size, void * pn);
  44. void sp_array_destructor_hook(void * px);
  45. #endif
  46. // The standard library that comes with Borland C++ 5.5.1
  47. // defines std::exception and its members as having C calling
  48. // convention (-pc). When the definition of bad_weak_ptr
  49. // is compiled with -ps, the compiler issues an error.
  50. // Hence, the temporary #pragma option -pc below. The version
  51. // check is deliberately conservative.
  52. class bad_weak_ptr: public std::exception
  53. {
  54. public:
  55. virtual char const * what() const BOOST_NOEXCEPT_OR_NOTHROW
  56. {
  57. return "boost::bad_weak_ptr";
  58. }
  59. };
  60. namespace detail{
  61. class sp_counted_base
  62. {
  63. //private:
  64. typedef boost::detail::lightweight_mutex mutex_type;
  65. public:
  66. sp_counted_base(): use_count_(1), weak_count_(1)
  67. {
  68. }
  69. virtual ~sp_counted_base() // nothrow
  70. {
  71. }
  72. // dispose() is called when use_count_ drops to zero, to release
  73. // the resources managed by *this.
  74. virtual void dispose() = 0; // nothrow
  75. // destruct() is called when weak_count_ drops to zero.
  76. virtual void destruct() // nothrow
  77. {
  78. delete this;
  79. }
  80. virtual void * get_deleter(std::type_info const & ti) = 0;
  81. void add_ref_copy()
  82. {
  83. #if defined(BOOST_HAS_THREADS)
  84. mutex_type::scoped_lock lock(mtx_);
  85. #endif
  86. ++use_count_;
  87. }
  88. void add_ref_lock()
  89. {
  90. #if defined(BOOST_HAS_THREADS)
  91. mutex_type::scoped_lock lock(mtx_);
  92. #endif
  93. if(use_count_ == 0) boost::serialization::throw_exception(bad_weak_ptr());
  94. ++use_count_;
  95. }
  96. void release() // nothrow
  97. {
  98. {
  99. #if defined(BOOST_HAS_THREADS)
  100. mutex_type::scoped_lock lock(mtx_);
  101. #endif
  102. long new_use_count = --use_count_;
  103. if(new_use_count != 0) return;
  104. }
  105. dispose();
  106. weak_release();
  107. }
  108. void weak_add_ref() // nothrow
  109. {
  110. #if defined(BOOST_HAS_THREADS)
  111. mutex_type::scoped_lock lock(mtx_);
  112. #endif
  113. ++weak_count_;
  114. }
  115. void weak_release() // nothrow
  116. {
  117. long new_weak_count;
  118. {
  119. #if defined(BOOST_HAS_THREADS)
  120. mutex_type::scoped_lock lock(mtx_);
  121. #endif
  122. new_weak_count = --weak_count_;
  123. }
  124. if(new_weak_count == 0)
  125. {
  126. destruct();
  127. }
  128. }
  129. long use_count() const // nothrow
  130. {
  131. #if defined(BOOST_HAS_THREADS)
  132. mutex_type::scoped_lock lock(mtx_);
  133. #endif
  134. return use_count_;
  135. }
  136. //private:
  137. public:
  138. sp_counted_base(sp_counted_base const &);
  139. sp_counted_base & operator= (sp_counted_base const &);
  140. long use_count_; // #shared
  141. long weak_count_; // #weak + (#shared != 0)
  142. #if defined(BOOST_HAS_THREADS) || defined(BOOST_LWM_WIN32)
  143. mutable mutex_type mtx_;
  144. #endif
  145. };
  146. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  147. template<class T> void cbi_call_constructor_hook(sp_counted_base * pn, T * px, boost::checked_deleter< T > const &)
  148. {
  149. boost::sp_scalar_constructor_hook(px, sizeof(T), pn);
  150. }
  151. template<class T> void cbi_call_constructor_hook(sp_counted_base *, T * px, boost::checked_array_deleter< T > const &)
  152. {
  153. boost::sp_array_constructor_hook(px);
  154. }
  155. template<class P, class D> void cbi_call_constructor_hook(sp_counted_base *, P const &, D const &, long)
  156. {
  157. }
  158. template<class T> void cbi_call_destructor_hook(sp_counted_base * pn, T * px, boost::checked_deleter< T > const &)
  159. {
  160. boost::sp_scalar_destructor_hook(px, sizeof(T), pn);
  161. }
  162. template<class T> void cbi_call_destructor_hook(sp_counted_base *, T * px, boost::checked_array_deleter< T > const &)
  163. {
  164. boost::sp_array_destructor_hook(px);
  165. }
  166. template<class P, class D> void cbi_call_destructor_hook(sp_counted_base *, P const &, D const &, long)
  167. {
  168. }
  169. #endif
  170. //
  171. // Borland's Codeguard trips up over the -Vx- option here:
  172. //
  173. #ifdef __CODEGUARD__
  174. # pragma option push -Vx-
  175. #endif
  176. template<class P, class D> class sp_counted_base_impl: public sp_counted_base
  177. {
  178. //private:
  179. public:
  180. P ptr; // copy constructor must not throw
  181. D del; // copy constructor must not throw
  182. sp_counted_base_impl(sp_counted_base_impl const &);
  183. sp_counted_base_impl & operator= (sp_counted_base_impl const &);
  184. typedef sp_counted_base_impl<P, D> this_type;
  185. public:
  186. // pre: initial_use_count <= initial_weak_count, d(p) must not throw
  187. sp_counted_base_impl(P p, D d): ptr(p), del(d)
  188. {
  189. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  190. detail::cbi_call_constructor_hook(this, p, d, 0);
  191. #endif
  192. }
  193. virtual void dispose() // nothrow
  194. {
  195. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  196. detail::cbi_call_destructor_hook(this, ptr, del, 0);
  197. #endif
  198. del(ptr);
  199. }
  200. virtual void * get_deleter(std::type_info const & ti)
  201. {
  202. return ti == typeid(D)? &del: 0;
  203. }
  204. #if defined(BOOST_SP_USE_STD_ALLOCATOR)
  205. void * operator new(std::size_t)
  206. {
  207. return std::allocator<this_type>().allocate(1, static_cast<this_type *>(0));
  208. }
  209. void operator delete(void * p)
  210. {
  211. std::allocator<this_type>().deallocate(static_cast<this_type *>(p), 1);
  212. }
  213. #endif
  214. #if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
  215. void * operator new(std::size_t)
  216. {
  217. return boost::detail::quick_allocator<this_type>::alloc();
  218. }
  219. void operator delete(void * p)
  220. {
  221. boost::detail::quick_allocator<this_type>::dealloc(p);
  222. }
  223. #endif
  224. };
  225. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  226. int const shared_count_id = 0x2C35F101;
  227. int const weak_count_id = 0x298C38A4;
  228. #endif
  229. class weak_count;
  230. class shared_count
  231. {
  232. //private:
  233. public:
  234. sp_counted_base * pi_;
  235. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  236. int id_;
  237. #endif
  238. friend class weak_count;
  239. public:
  240. shared_count(): pi_(0) // nothrow
  241. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  242. , id_(shared_count_id)
  243. #endif
  244. {
  245. }
  246. template<class P, class D> shared_count(P p, D d): pi_(0)
  247. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  248. , id_(shared_count_id)
  249. #endif
  250. {
  251. #ifndef BOOST_NO_EXCEPTIONS
  252. try
  253. {
  254. pi_ = new sp_counted_base_impl<P, D>(p, d);
  255. }
  256. catch(...)
  257. {
  258. d(p); // delete p
  259. throw;
  260. }
  261. #else
  262. pi_ = new sp_counted_base_impl<P, D>(p, d);
  263. if(pi_ == 0)
  264. {
  265. d(p); // delete p
  266. boost::serialization::throw_exception(std::bad_alloc());
  267. }
  268. #endif
  269. }
  270. #ifndef BOOST_NO_AUTO_PTR
  271. // auto_ptr<Y> is special cased to provide the strong guarantee
  272. template<class Y>
  273. explicit shared_count(std::auto_ptr<Y> & r): pi_(
  274. new sp_counted_base_impl<
  275. Y *,
  276. boost::checked_deleter<Y>
  277. >(r.get(), boost::checked_deleter<Y>()))
  278. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  279. , id_(shared_count_id)
  280. #endif
  281. {
  282. r.release();
  283. }
  284. #endif
  285. ~shared_count() // nothrow
  286. {
  287. if(pi_ != 0) pi_->release();
  288. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  289. id_ = 0;
  290. #endif
  291. }
  292. shared_count(shared_count const & r): pi_(r.pi_) // nothrow
  293. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  294. , id_(shared_count_id)
  295. #endif
  296. {
  297. if(pi_ != 0) pi_->add_ref_copy();
  298. }
  299. explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
  300. shared_count & operator= (shared_count const & r) // nothrow
  301. {
  302. sp_counted_base * tmp = r.pi_;
  303. if(tmp != pi_)
  304. {
  305. if(tmp != 0) tmp->add_ref_copy();
  306. if(pi_ != 0) pi_->release();
  307. pi_ = tmp;
  308. }
  309. return *this;
  310. }
  311. void swap(shared_count & r) // nothrow
  312. {
  313. sp_counted_base * tmp = r.pi_;
  314. r.pi_ = pi_;
  315. pi_ = tmp;
  316. }
  317. long use_count() const // nothrow
  318. {
  319. return pi_ != 0? pi_->use_count(): 0;
  320. }
  321. bool unique() const // nothrow
  322. {
  323. return use_count() == 1;
  324. }
  325. friend inline bool operator==(shared_count const & a, shared_count const & b)
  326. {
  327. return a.pi_ == b.pi_;
  328. }
  329. friend inline bool operator<(shared_count const & a, shared_count const & b)
  330. {
  331. return std::less<sp_counted_base *>()(a.pi_, b.pi_);
  332. }
  333. void * get_deleter(std::type_info const & ti) const
  334. {
  335. return pi_? pi_->get_deleter(ti): 0;
  336. }
  337. };
  338. #ifdef __CODEGUARD__
  339. # pragma option pop
  340. #endif
  341. class weak_count
  342. {
  343. private:
  344. sp_counted_base * pi_;
  345. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  346. int id_;
  347. #endif
  348. friend class shared_count;
  349. public:
  350. weak_count(): pi_(0) // nothrow
  351. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  352. , id_(weak_count_id)
  353. #endif
  354. {
  355. }
  356. weak_count(shared_count const & r): pi_(r.pi_) // nothrow
  357. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  358. , id_(shared_count_id)
  359. #endif
  360. {
  361. if(pi_ != 0) pi_->weak_add_ref();
  362. }
  363. weak_count(weak_count const & r): pi_(r.pi_) // nothrow
  364. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  365. , id_(shared_count_id)
  366. #endif
  367. {
  368. if(pi_ != 0) pi_->weak_add_ref();
  369. }
  370. ~weak_count() // nothrow
  371. {
  372. if(pi_ != 0) pi_->weak_release();
  373. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  374. id_ = 0;
  375. #endif
  376. }
  377. weak_count & operator= (shared_count const & r) // nothrow
  378. {
  379. sp_counted_base * tmp = r.pi_;
  380. if(tmp != 0) tmp->weak_add_ref();
  381. if(pi_ != 0) pi_->weak_release();
  382. pi_ = tmp;
  383. return *this;
  384. }
  385. weak_count & operator= (weak_count const & r) // nothrow
  386. {
  387. sp_counted_base * tmp = r.pi_;
  388. if(tmp != 0) tmp->weak_add_ref();
  389. if(pi_ != 0) pi_->weak_release();
  390. pi_ = tmp;
  391. return *this;
  392. }
  393. void swap(weak_count & r) // nothrow
  394. {
  395. sp_counted_base * tmp = r.pi_;
  396. r.pi_ = pi_;
  397. pi_ = tmp;
  398. }
  399. long use_count() const // nothrow
  400. {
  401. return pi_ != 0? pi_->use_count(): 0;
  402. }
  403. friend inline bool operator==(weak_count const & a, weak_count const & b)
  404. {
  405. return a.pi_ == b.pi_;
  406. }
  407. friend inline bool operator<(weak_count const & a, weak_count const & b)
  408. {
  409. return std::less<sp_counted_base *>()(a.pi_, b.pi_);
  410. }
  411. };
  412. inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
  413. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  414. , id_(shared_count_id)
  415. #endif
  416. {
  417. if(pi_ != 0)
  418. {
  419. pi_->add_ref_lock();
  420. }
  421. else
  422. {
  423. boost::serialization::throw_exception(bad_weak_ptr());
  424. }
  425. }
  426. } // namespace detail
  427. } // namespace boost
  428. BOOST_SERIALIZATION_ASSUME_ABSTRACT(boost_132::detail::sp_counted_base)
  429. #endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED