#ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
#define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
-#if _MSC_VER >= 1020
-#pragma once
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
#endif
//
// detail/shared_count.hpp
//
-// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2005 Peter Dimov
//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
//
-#include <boost/config.hpp>
-
-#ifndef BOOST_NO_AUTO_PTR
-# include <memory>
+#ifdef __BORLANDC__
+# pragma warn -8027 // Functions containing try are not expanded inline
#endif
+#include <boost/config.hpp>
#include <boost/checked_delete.hpp>
-#include <boost/detail/lightweight_mutex.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/detail/bad_weak_ptr.hpp>
+#include <boost/detail/sp_counted_base.hpp>
+#include <boost/detail/sp_counted_impl.hpp>
-#include <functional> // for std::less
-#include <exception> // for std::exception
+#include <memory> // std::auto_ptr, std::allocator
+#include <functional> // std::less
+#include <new> // std::bad_alloc
+#include <typeinfo> // std::type_info in get_deleter
namespace boost
{
-class use_count_is_zero: public std::exception
+namespace detail
{
-public:
- virtual char const * what() const throw()
- {
- return "use_count_is_zero";
- }
-};
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
-class counted_base
-{
-private:
+int const shared_count_id = 0x2C35F101;
+int const weak_count_id = 0x298C38A4;
- typedef detail::lightweight_mutex mutex_type;
+#endif
-public:
+class weak_count;
- counted_base():
- use_count_(0), weak_count_(0), self_deleter_(&self_delete)
- {
- }
+class shared_count
+{
+private:
- // pre: initial_use_count <= initial_weak_count
+ sp_counted_base * pi_;
- explicit counted_base(long initial_use_count, long initial_weak_count):
- use_count_(initial_use_count), weak_count_(initial_weak_count), self_deleter_(&self_delete)
- {
- }
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ int id_;
+#endif
- virtual ~counted_base() // nothrow
- {
- }
+ friend class weak_count;
- // dispose() is called when use_count_ drops to zero, to release
- // the resources managed by *this.
- //
- // counted_base doesn't manage any resources except itself, and
- // the default implementation is a no-op.
- //
- // dispose() is not pure virtual since weak_ptr instantiates a
- // counted_base in its default constructor.
+public:
- virtual void dispose() // nothrow
+ shared_count(): pi_(0) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
{
}
- void add_ref()
- {
-#ifdef BOOST_HAS_THREADS
- mutex_type::scoped_lock lock(mtx_);
+ template<class Y> explicit shared_count( Y * p ): pi_( 0 )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
#endif
- if(use_count_ == 0 && weak_count_ != 0) throw use_count_is_zero();
- ++use_count_;
- ++weak_count_;
- }
-
- void release() // nothrow
{
- long new_use_count;
- long new_weak_count;
-
- {
-#ifdef BOOST_HAS_THREADS
- mutex_type::scoped_lock lock(mtx_);
-#endif
- new_use_count = --use_count_;
- new_weak_count = --weak_count_;
- }
+#ifndef BOOST_NO_EXCEPTIONS
- if(new_use_count == 0)
+ try
{
- dispose();
+ pi_ = new sp_counted_impl_p<Y>( p );
}
-
- if(new_weak_count == 0)
+ catch(...)
{
- // not a direct 'delete this', because the inlined
- // release() may use a different heap manager
- self_deleter_(this);
+ boost::checked_delete( p );
+ throw;
}
- }
- void weak_add_ref() // nothrow
- {
-#ifdef BOOST_HAS_THREADS
- mutex_type::scoped_lock lock(mtx_);
-#endif
- ++weak_count_;
- }
+#else
- void weak_release() // nothrow
- {
- long new_weak_count;
+ pi_ = new sp_counted_impl_p<Y>( p );
+ if( pi_ == 0 )
{
-#ifdef BOOST_HAS_THREADS
- mutex_type::scoped_lock lock(mtx_);
-#endif
- new_weak_count = --weak_count_;
- }
-
- if(new_weak_count == 0)
- {
- self_deleter_(this);
+ boost::checked_delete( p );
+ boost::throw_exception( std::bad_alloc() );
}
- }
- long use_count() const // nothrow
- {
-#ifdef BOOST_HAS_THREADS
- mutex_type::scoped_lock lock(mtx_);
#endif
- return use_count_;
- }
-
-private:
-
- counted_base(counted_base const &);
- counted_base & operator= (counted_base const &);
-
- static void self_delete(counted_base * p)
- {
- delete p;
}
- // inv: use_count_ <= weak_count_
-
- long use_count_;
- long weak_count_;
-#ifdef BOOST_HAS_THREADS
- mutable mutex_type mtx_;
+ template<class P, class D> shared_count(P p, D d): pi_(0)
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
#endif
- void (*self_deleter_) (counted_base *);
-};
-
-inline void intrusive_ptr_add_ref(counted_base * p)
-{
- p->add_ref();
-}
-
-inline void intrusive_ptr_release(counted_base * p)
-{
- p->release();
-}
-
-namespace detail
-{
-
-template<class P, class D> class counted_base_impl: public counted_base
-{
-private:
-
- P ptr; // copy constructor must not throw
- D del; // copy constructor must not throw
-
- counted_base_impl(counted_base_impl const &);
- counted_base_impl & operator= (counted_base_impl const &);
-
-public:
-
- // pre: initial_use_count <= initial_weak_count, d(p) must not throw
-
- counted_base_impl(P p, D d, long initial_use_count, long initial_weak_count):
- counted_base(initial_use_count, initial_weak_count), ptr(p), del(d)
- {
- }
-
- virtual void dispose() // nothrow
{
- del(ptr);
- }
-};
+#ifndef BOOST_NO_EXCEPTIONS
-class weak_count;
-
-class shared_count
-{
-private:
-
- counted_base * pi_;
-
- friend class weak_count;
-
- template<class P, class D> shared_count(P, D, counted_base const *);
-
-public:
-
- shared_count(): pi_(new counted_base(1, 1))
- {
- }
-
- explicit shared_count(counted_base * pi): pi_(pi) // never throws
- {
- pi_->add_ref();
- }
-
- template<class P, class D> shared_count(P p, D d, void const * = 0): pi_(0)
- {
try
{
- pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
+ pi_ = new sp_counted_impl_pd<P, D>(p, d);
}
catch(...)
{
d(p); // delete p
throw;
}
- }
- template<class P, class D> shared_count(P, D, counted_base * pi): pi_(pi)
- {
- pi_->add_ref();
+#else
+
+ pi_ = new sp_counted_impl_pd<P, D>(p, d);
+
+ if(pi_ == 0)
+ {
+ d(p); // delete p
+ boost::throw_exception(std::bad_alloc());
+ }
+
+#endif
}
#ifndef BOOST_NO_AUTO_PTR
// auto_ptr<Y> is special cased to provide the strong guarantee
- template<typename Y>
- explicit shared_count(std::auto_ptr<Y> & r): pi_(new counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>(), 1, 1))
+ template<class Y>
+ explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
{
+#ifdef BOOST_NO_EXCEPTIONS
+
+ if( pi_ == 0 )
+ {
+ boost::throw_exception(std::bad_alloc());
+ }
+
+#endif
+
r.release();
}
~shared_count() // nothrow
{
- pi_->release();
+ if( pi_ != 0 ) pi_->release();
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ id_ = 0;
+#endif
}
shared_count(shared_count const & r): pi_(r.pi_) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
{
- pi_->add_ref();
+ if( pi_ != 0 ) pi_->add_ref_copy();
}
- explicit shared_count(weak_count const & r); // throws use_count_is_zero when r.use_count() == 0
+ explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
shared_count & operator= (shared_count const & r) // nothrow
{
- counted_base * tmp = r.pi_;
- tmp->add_ref();
- pi_->release();
- pi_ = tmp;
+ sp_counted_base * tmp = r.pi_;
+
+ if( tmp != pi_ )
+ {
+ if( tmp != 0 ) tmp->add_ref_copy();
+ if( pi_ != 0 ) pi_->release();
+ pi_ = tmp;
+ }
return *this;
}
void swap(shared_count & r) // nothrow
{
- counted_base * tmp = r.pi_;
+ sp_counted_base * tmp = r.pi_;
r.pi_ = pi_;
pi_ = tmp;
}
long use_count() const // nothrow
{
- return pi_->use_count();
+ return pi_ != 0? pi_->use_count(): 0;
}
bool unique() const // nothrow
{
- return pi_->use_count() == 1;
+ return use_count() == 1;
}
friend inline bool operator==(shared_count const & a, shared_count const & b)
friend inline bool operator<(shared_count const & a, shared_count const & b)
{
- return std::less<counted_base *>()(a.pi_, b.pi_);
+ return std::less<sp_counted_base *>()( a.pi_, b.pi_ );
+ }
+
+ void * get_deleter(std::type_info const & ti) const
+ {
+ return pi_? pi_->get_deleter( ti ): 0;
}
};
+
class weak_count
{
private:
- counted_base * pi_;
+ sp_counted_base * pi_;
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ int id_;
+#endif
friend class shared_count;
public:
- weak_count(): pi_(new counted_base(0, 1)) // can throw
+ weak_count(): pi_(0) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(weak_count_id)
+#endif
{
}
weak_count(shared_count const & r): pi_(r.pi_) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
{
- pi_->weak_add_ref();
+ if(pi_ != 0) pi_->weak_add_ref();
}
weak_count(weak_count const & r): pi_(r.pi_) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
{
- pi_->weak_add_ref();
+ if(pi_ != 0) pi_->weak_add_ref();
}
~weak_count() // nothrow
{
- pi_->weak_release();
+ if(pi_ != 0) pi_->weak_release();
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ id_ = 0;
+#endif
}
weak_count & operator= (shared_count const & r) // nothrow
{
- counted_base * tmp = r.pi_;
- tmp->weak_add_ref();
- pi_->weak_release();
+ sp_counted_base * tmp = r.pi_;
+ if(tmp != 0) tmp->weak_add_ref();
+ if(pi_ != 0) pi_->weak_release();
pi_ = tmp;
return *this;
weak_count & operator= (weak_count const & r) // nothrow
{
- counted_base * tmp = r.pi_;
- tmp->weak_add_ref();
- pi_->weak_release();
+ sp_counted_base * tmp = r.pi_;
+ if(tmp != 0) tmp->weak_add_ref();
+ if(pi_ != 0) pi_->weak_release();
pi_ = tmp;
return *this;
void swap(weak_count & r) // nothrow
{
- counted_base * tmp = r.pi_;
+ sp_counted_base * tmp = r.pi_;
r.pi_ = pi_;
pi_ = tmp;
}
long use_count() const // nothrow
{
- return pi_->use_count();
+ return pi_ != 0? pi_->use_count(): 0;
}
friend inline bool operator==(weak_count const & a, weak_count const & b)
friend inline bool operator<(weak_count const & a, weak_count const & b)
{
- return std::less<counted_base *>()(a.pi_, b.pi_);
+ return std::less<sp_counted_base *>()(a.pi_, b.pi_);
}
};
-inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
+inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
{
- pi_->add_ref();
+ if( pi_ == 0 || !pi_->add_ref_lock() )
+ {
+ boost::throw_exception( boost::bad_weak_ptr() );
+ }
}
} // namespace detail
} // namespace boost
+#ifdef __BORLANDC__
+# pragma warn .8027 // Functions containing try are not expanded inline
+#endif
+
#endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED