File indexing completed on 2025-01-30 09:59:44
0001 #ifndef BOOST_DETAIL_SHARED_COUNT_132_HPP_INCLUDED
0002 #define BOOST_DETAIL_SHARED_COUNT_132_HPP_INCLUDED
0003
0004
0005
0006 #if defined(_MSC_VER)
0007 # pragma once
0008 #endif
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <boost/config.hpp>
0021
0022 #if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR)
0023 # error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible.
0024 #endif
0025
0026 #include <boost/checked_delete.hpp>
0027 #include <boost/serialization/throw_exception.hpp>
0028 #include <boost/detail/lightweight_mutex.hpp>
0029
0030 #if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
0031 #include <boost/detail/quick_allocator.hpp>
0032 #endif
0033
0034 #include <memory> // std::auto_ptr, std::allocator
0035 #include <functional> // std::less
0036 #include <exception> // std::exception
0037 #include <new> // std::bad_alloc
0038 #include <typeinfo> // std::type_info in get_deleter
0039 #include <cstddef> // std::size_t
0040
0041 #include <boost/config.hpp> // msvc 6.0 needs this for warning suppression
0042 #if defined(BOOST_NO_STDC_NAMESPACE)
0043 namespace std{
0044 using ::size_t;
0045 }
0046 #endif
0047
0048 namespace boost_132 {
0049
0050
0051
0052 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
0053
0054 void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn);
0055 void sp_array_constructor_hook(void * px);
0056 void sp_scalar_destructor_hook(void * px, std::size_t size, void * pn);
0057 void sp_array_destructor_hook(void * px);
0058
0059 #endif
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 class bad_weak_ptr: public std::exception
0070 {
0071 public:
0072
0073 virtual char const * what() const BOOST_NOEXCEPT_OR_NOTHROW
0074 {
0075 return "boost::bad_weak_ptr";
0076 }
0077 };
0078
0079 namespace detail{
0080
0081 class sp_counted_base
0082 {
0083
0084
0085 typedef boost::detail::lightweight_mutex mutex_type;
0086
0087 public:
0088
0089 sp_counted_base(): use_count_(1), weak_count_(1)
0090 {
0091 }
0092
0093 virtual ~sp_counted_base()
0094 {
0095 }
0096
0097
0098
0099
0100 virtual void dispose() = 0;
0101
0102
0103
0104 virtual void destruct()
0105 {
0106 delete this;
0107 }
0108
0109 virtual void * get_deleter(std::type_info const & ti) = 0;
0110
0111 void add_ref_copy()
0112 {
0113 #if defined(BOOST_HAS_THREADS)
0114 mutex_type::scoped_lock lock(mtx_);
0115 #endif
0116 ++use_count_;
0117 }
0118
0119 void add_ref_lock()
0120 {
0121 #if defined(BOOST_HAS_THREADS)
0122 mutex_type::scoped_lock lock(mtx_);
0123 #endif
0124 if(use_count_ == 0) boost::serialization::throw_exception(bad_weak_ptr());
0125 ++use_count_;
0126 }
0127
0128 void release()
0129 {
0130 {
0131 #if defined(BOOST_HAS_THREADS)
0132 mutex_type::scoped_lock lock(mtx_);
0133 #endif
0134 long new_use_count = --use_count_;
0135
0136 if(new_use_count != 0) return;
0137 }
0138
0139 dispose();
0140 weak_release();
0141 }
0142
0143 void weak_add_ref()
0144 {
0145 #if defined(BOOST_HAS_THREADS)
0146 mutex_type::scoped_lock lock(mtx_);
0147 #endif
0148 ++weak_count_;
0149 }
0150
0151 void weak_release()
0152 {
0153 long new_weak_count;
0154
0155 {
0156 #if defined(BOOST_HAS_THREADS)
0157 mutex_type::scoped_lock lock(mtx_);
0158 #endif
0159 new_weak_count = --weak_count_;
0160 }
0161
0162 if(new_weak_count == 0)
0163 {
0164 destruct();
0165 }
0166 }
0167
0168 long use_count() const
0169 {
0170 #if defined(BOOST_HAS_THREADS)
0171 mutex_type::scoped_lock lock(mtx_);
0172 #endif
0173 return use_count_;
0174 }
0175
0176
0177 public:
0178 sp_counted_base(sp_counted_base const &);
0179 sp_counted_base & operator= (sp_counted_base const &);
0180
0181 long use_count_;
0182 long weak_count_;
0183
0184 #if defined(BOOST_HAS_THREADS) || defined(BOOST_LWM_WIN32)
0185 mutable mutex_type mtx_;
0186 #endif
0187 };
0188
0189 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
0190
0191 template<class T> void cbi_call_constructor_hook(sp_counted_base * pn, T * px, boost::checked_deleter< T > const &)
0192 {
0193 boost::sp_scalar_constructor_hook(px, sizeof(T), pn);
0194 }
0195
0196 template<class T> void cbi_call_constructor_hook(sp_counted_base *, T * px, boost::checked_array_deleter< T > const &)
0197 {
0198 boost::sp_array_constructor_hook(px);
0199 }
0200
0201 template<class P, class D> void cbi_call_constructor_hook(sp_counted_base *, P const &, D const &, long)
0202 {
0203 }
0204
0205 template<class T> void cbi_call_destructor_hook(sp_counted_base * pn, T * px, boost::checked_deleter< T > const &)
0206 {
0207 boost::sp_scalar_destructor_hook(px, sizeof(T), pn);
0208 }
0209
0210 template<class T> void cbi_call_destructor_hook(sp_counted_base *, T * px, boost::checked_array_deleter< T > const &)
0211 {
0212 boost::sp_array_destructor_hook(px);
0213 }
0214
0215 template<class P, class D> void cbi_call_destructor_hook(sp_counted_base *, P const &, D const &, long)
0216 {
0217 }
0218
0219 #endif
0220
0221
0222
0223
0224 #ifdef __CODEGUARD__
0225 # pragma option push -Vx-
0226 #endif
0227
0228 template<class P, class D> class sp_counted_base_impl: public sp_counted_base
0229 {
0230
0231 public:
0232 P ptr;
0233 D del;
0234
0235 sp_counted_base_impl(sp_counted_base_impl const &);
0236 sp_counted_base_impl & operator= (sp_counted_base_impl const &);
0237
0238 typedef sp_counted_base_impl<P, D> this_type;
0239
0240 public:
0241
0242
0243
0244 sp_counted_base_impl(P p, D d): ptr(p), del(d)
0245 {
0246 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
0247 detail::cbi_call_constructor_hook(this, p, d, 0);
0248 #endif
0249 }
0250
0251 virtual void dispose()
0252 {
0253 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
0254 detail::cbi_call_destructor_hook(this, ptr, del, 0);
0255 #endif
0256 del(ptr);
0257 }
0258
0259 virtual void * get_deleter(std::type_info const & ti)
0260 {
0261 return ti == typeid(D)? &del: 0;
0262 }
0263
0264 #if defined(BOOST_SP_USE_STD_ALLOCATOR)
0265
0266 void * operator new(std::size_t)
0267 {
0268 return std::allocator<this_type>().allocate(1, static_cast<this_type *>(0));
0269 }
0270
0271 void operator delete(void * p)
0272 {
0273 std::allocator<this_type>().deallocate(static_cast<this_type *>(p), 1);
0274 }
0275
0276 #endif
0277
0278 #if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
0279
0280 void * operator new(std::size_t)
0281 {
0282 return boost::detail::quick_allocator<this_type>::alloc();
0283 }
0284
0285 void operator delete(void * p)
0286 {
0287 boost::detail::quick_allocator<this_type>::dealloc(p);
0288 }
0289
0290 #endif
0291 };
0292
0293 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
0294
0295 int const shared_count_id = 0x2C35F101;
0296 int const weak_count_id = 0x298C38A4;
0297
0298 #endif
0299
0300 class weak_count;
0301
0302 class shared_count
0303 {
0304
0305 public:
0306 sp_counted_base * pi_;
0307
0308 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
0309 int id_;
0310 #endif
0311
0312 friend class weak_count;
0313
0314 public:
0315
0316 shared_count(): pi_(0)
0317 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
0318 , id_(shared_count_id)
0319 #endif
0320 {
0321 }
0322
0323 template<class P, class D> shared_count(P p, D d): pi_(0)
0324 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
0325 , id_(shared_count_id)
0326 #endif
0327 {
0328 #ifndef BOOST_NO_EXCEPTIONS
0329
0330 try
0331 {
0332 pi_ = new sp_counted_base_impl<P, D>(p, d);
0333 }
0334 catch(...)
0335 {
0336 d(p);
0337 throw;
0338 }
0339
0340 #else
0341
0342 pi_ = new sp_counted_base_impl<P, D>(p, d);
0343
0344 if(pi_ == 0)
0345 {
0346 d(p);
0347 boost::serialization::throw_exception(std::bad_alloc());
0348 }
0349
0350 #endif
0351 }
0352
0353 #ifndef BOOST_NO_AUTO_PTR
0354
0355
0356
0357 template<class Y>
0358 explicit shared_count(std::auto_ptr<Y> & r): pi_(
0359 new sp_counted_base_impl<
0360 Y *,
0361 boost::checked_deleter<Y>
0362 >(r.get(), boost::checked_deleter<Y>()))
0363 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
0364 , id_(shared_count_id)
0365 #endif
0366 {
0367 r.release();
0368 }
0369
0370 #endif
0371
0372 ~shared_count()
0373 {
0374 if(pi_ != 0) pi_->release();
0375 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
0376 id_ = 0;
0377 #endif
0378 }
0379
0380 shared_count(shared_count const & r): pi_(r.pi_)
0381 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
0382 , id_(shared_count_id)
0383 #endif
0384 {
0385 if(pi_ != 0) pi_->add_ref_copy();
0386 }
0387
0388 explicit shared_count(weak_count const & r);
0389
0390 shared_count & operator= (shared_count const & r)
0391 {
0392 sp_counted_base * tmp = r.pi_;
0393
0394 if(tmp != pi_)
0395 {
0396 if(tmp != 0) tmp->add_ref_copy();
0397 if(pi_ != 0) pi_->release();
0398 pi_ = tmp;
0399 }
0400
0401 return *this;
0402 }
0403
0404 void swap(shared_count & r)
0405 {
0406 sp_counted_base * tmp = r.pi_;
0407 r.pi_ = pi_;
0408 pi_ = tmp;
0409 }
0410
0411 long use_count() const
0412 {
0413 return pi_ != 0? pi_->use_count(): 0;
0414 }
0415
0416 bool unique() const
0417 {
0418 return use_count() == 1;
0419 }
0420
0421 friend inline bool operator==(shared_count const & a, shared_count const & b)
0422 {
0423 return a.pi_ == b.pi_;
0424 }
0425
0426 friend inline bool operator<(shared_count const & a, shared_count const & b)
0427 {
0428 return std::less<sp_counted_base *>()(a.pi_, b.pi_);
0429 }
0430
0431 void * get_deleter(std::type_info const & ti) const
0432 {
0433 return pi_? pi_->get_deleter(ti): 0;
0434 }
0435 };
0436
0437 #ifdef __CODEGUARD__
0438 # pragma option pop
0439 #endif
0440
0441
0442 class weak_count
0443 {
0444 private:
0445
0446 sp_counted_base * pi_;
0447
0448 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
0449 int id_;
0450 #endif
0451
0452 friend class shared_count;
0453
0454 public:
0455
0456 weak_count(): pi_(0)
0457 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
0458 , id_(weak_count_id)
0459 #endif
0460 {
0461 }
0462
0463 weak_count(shared_count const & r): pi_(r.pi_)
0464 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
0465 , id_(shared_count_id)
0466 #endif
0467 {
0468 if(pi_ != 0) pi_->weak_add_ref();
0469 }
0470
0471 weak_count(weak_count const & r): pi_(r.pi_)
0472 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
0473 , id_(shared_count_id)
0474 #endif
0475 {
0476 if(pi_ != 0) pi_->weak_add_ref();
0477 }
0478
0479 ~weak_count()
0480 {
0481 if(pi_ != 0) pi_->weak_release();
0482 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
0483 id_ = 0;
0484 #endif
0485 }
0486
0487 weak_count & operator= (shared_count const & r)
0488 {
0489 sp_counted_base * tmp = r.pi_;
0490 if(tmp != 0) tmp->weak_add_ref();
0491 if(pi_ != 0) pi_->weak_release();
0492 pi_ = tmp;
0493
0494 return *this;
0495 }
0496
0497 weak_count & operator= (weak_count const & r)
0498 {
0499 sp_counted_base * tmp = r.pi_;
0500 if(tmp != 0) tmp->weak_add_ref();
0501 if(pi_ != 0) pi_->weak_release();
0502 pi_ = tmp;
0503
0504 return *this;
0505 }
0506
0507 void swap(weak_count & r)
0508 {
0509 sp_counted_base * tmp = r.pi_;
0510 r.pi_ = pi_;
0511 pi_ = tmp;
0512 }
0513
0514 long use_count() const
0515 {
0516 return pi_ != 0? pi_->use_count(): 0;
0517 }
0518
0519 friend inline bool operator==(weak_count const & a, weak_count const & b)
0520 {
0521 return a.pi_ == b.pi_;
0522 }
0523
0524 friend inline bool operator<(weak_count const & a, weak_count const & b)
0525 {
0526 return std::less<sp_counted_base *>()(a.pi_, b.pi_);
0527 }
0528 };
0529
0530 inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
0531 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
0532 , id_(shared_count_id)
0533 #endif
0534 {
0535 if(pi_ != 0)
0536 {
0537 pi_->add_ref_lock();
0538 }
0539 else
0540 {
0541 boost::serialization::throw_exception(bad_weak_ptr());
0542 }
0543 }
0544
0545 }
0546
0547 }
0548
0549 BOOST_SERIALIZATION_ASSUME_ABSTRACT(boost_132::detail::sp_counted_base)
0550
0551 #endif