]> git.lyx.org Git - lyx.git/blobdiff - boost/boost/detail/shared_count.hpp
* Add the iostreams and range libs to our copy of boost
[lyx.git] / boost / boost / detail / shared_count.hpp
index 918d64745173bf53d4aa6ab4fcd6960792d1fee3..49aca857f71ee534da2c9073266d13b1c4786ec9 100644 (file)
 #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
-#ifndef BOOST_NO_EXCEPTIONS
-        if(use_count_ == 0 && weak_count_ != 0) throw use_count_is_zero();
-#endif
-        BOOST_NOEH_ASSERT(!(use_count_ == 0 && weak_count_ != 0));
-        ++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_;
+            boost::checked_delete( p );
+            boost::throw_exception( std::bad_alloc() );
         }
 
-        if(new_weak_count == 0)
-        {
-            self_deleter_(this);
-        }
-    }
-
-    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);
-    }
-};
-
-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)
     {
 #ifndef BOOST_NO_EXCEPTIONS
+
         try
         {
-#endif
-            pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
-#ifndef BOOST_NO_EXCEPTIONS
+            pi_ = new sp_counted_impl_pd<P, D>(p, d);
         }
-#endif
-#ifndef BOOST_NO_EXCEPTIONS
         catch(...)
-                
         {
             d(p); // delete p
             throw;
         }
-#endif
-        BOOST_NOEH_ASSERT(pi_);
-    }
 
-    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();
     }
 
-#endif
+#endif 
 
     ~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)
@@ -315,44 +210,66 @@ public:
 
     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;
@@ -360,9 +277,9 @@ public:
 
     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;
@@ -370,14 +287,14 @@ public:
 
     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)
@@ -387,17 +304,27 @@ public:
 
     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