Back to home page

EIC code displayed by LXR

 
 

    


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 // MS compatible compilers support #pragma once
0005 
0006 #if defined(_MSC_VER)
0007 # pragma once
0008 #endif
0009 
0010 //
0011 //  detail/shared_count.hpp
0012 //
0013 //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
0014 //
0015 // Distributed under the Boost Software License, Version 1.0. (See
0016 // accompanying file LICENSE_1_0.txt or copy at
0017 // http://www.boost.org/LICENSE_1_0.txt)
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 } // namespace std
0046 #endif
0047 
0048 namespace boost_132 {
0049 
0050 // Debug hooks
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 // The standard library that comes with Borland C++ 5.5.1
0063 // defines std::exception and its members as having C calling
0064 // convention (-pc). When the definition of bad_weak_ptr
0065 // is compiled with -ps, the compiler issues an error.
0066 // Hence, the temporary #pragma option -pc below. The version
0067 // check is deliberately conservative.
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 //private:
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() // nothrow
0094     {
0095     }
0096 
0097     // dispose() is called when use_count_ drops to zero, to release
0098     // the resources managed by *this.
0099 
0100     virtual void dispose() = 0; // nothrow
0101 
0102     // destruct() is called when weak_count_ drops to zero.
0103 
0104     virtual void destruct() // nothrow
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() // nothrow
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() // nothrow
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() // nothrow
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 // nothrow
0169     {
0170 #if defined(BOOST_HAS_THREADS)
0171         mutex_type::scoped_lock lock(mtx_);
0172 #endif
0173         return use_count_;
0174     }
0175 
0176 //private:
0177 public:
0178     sp_counted_base(sp_counted_base const &);
0179     sp_counted_base & operator= (sp_counted_base const &);
0180 
0181     long use_count_;        // #shared
0182     long weak_count_;       // #weak + (#shared != 0)
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 // Borland's Codeguard trips up over the -Vx- option here:
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 //private:
0231 public:
0232     P ptr; // copy constructor must not throw
0233     D del; // copy constructor must not throw
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     // pre: initial_use_count <= initial_weak_count, d(p) must not throw
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() // nothrow
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 //private:
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) // nothrow
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); // delete 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); // delete p
0347             boost::serialization::throw_exception(std::bad_alloc());
0348         }
0349 
0350 #endif
0351     }
0352 
0353 #ifndef BOOST_NO_AUTO_PTR
0354 
0355     // auto_ptr<Y> is special cased to provide the strong guarantee
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() // nothrow
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_) // nothrow
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); // throws bad_weak_ptr when r.use_count() == 0
0389 
0390     shared_count & operator= (shared_count const & r) // nothrow
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) // nothrow
0405     {
0406         sp_counted_base * tmp = r.pi_;
0407         r.pi_ = pi_;
0408         pi_ = tmp;
0409     }
0410 
0411     long use_count() const // nothrow
0412     {
0413         return pi_ != 0? pi_->use_count(): 0;
0414     }
0415 
0416     bool unique() const // nothrow
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) // nothrow
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_) // nothrow
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_) // nothrow
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() // nothrow
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) // nothrow
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) // nothrow
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) // nothrow
0508     {
0509         sp_counted_base * tmp = r.pi_;
0510         r.pi_ = pi_;
0511         pi_ = tmp;
0512     }
0513 
0514     long use_count() const // nothrow
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 } // namespace detail
0546 
0547 } // namespace boost
0548 
0549 BOOST_SERIALIZATION_ASSUME_ABSTRACT(boost_132::detail::sp_counted_base)
0550 
0551 #endif  // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED