shared_count_132.hpp 12 KB

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