diff options
Diffstat (limited to 'ksvg/impl/libs/libtext2path/src/myboost/shared_count.hpp')
-rw-r--r-- | ksvg/impl/libs/libtext2path/src/myboost/shared_count.hpp | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/ksvg/impl/libs/libtext2path/src/myboost/shared_count.hpp b/ksvg/impl/libs/libtext2path/src/myboost/shared_count.hpp new file mode 100644 index 00000000..e8ec19a8 --- /dev/null +++ b/ksvg/impl/libs/libtext2path/src/myboost/shared_count.hpp @@ -0,0 +1,367 @@ +#ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED +#define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED + +// +// detail/shared_count.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// +// 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. +// + +#include "myboost/checked_delete.hpp" +#include "myboost/throw_exception.hpp" +#include "myboost/lightweight_mutex.hpp" + +#include <memory> // std::auto_ptr, std::allocator +#include <functional> // std::less +#include <exception> // std::exception +#include <new> // std::bad_alloc +#include <typeinfo> // std::type_info in get_deleter +#include <cstddef> // std::size_t + +namespace myboost +{ + +class bad_weak_ptr: public std::exception +{ +public: + + virtual char const * what() const throw() + { + return "myboost::bad_weak_ptr"; + } +}; + +namespace detail +{ + +class sp_counted_base +{ +private: + + typedef detail::lightweight_mutex mutex_type; + +public: + + sp_counted_base(): use_count_(1), weak_count_(1) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destruct() is called when weak_count_ drops to zero. + + virtual void destruct() // nothrow + { + delete this; + } + + virtual void * get_deleter(std::type_info const & ti) = 0; + + void add_ref_copy() + { + mutex_type::scoped_lock lock(mtx_); + ++use_count_; + } + + void add_ref_lock() + { + mutex_type::scoped_lock lock(mtx_); + if(use_count_ == 0) myboost::throw_exception(myboost::bad_weak_ptr()); + ++use_count_; + } + + void release() // nothrow + { + { + mutex_type::scoped_lock lock(mtx_); + long new_use_count = --use_count_; + + if(new_use_count != 0) return; + } + + dispose(); + weak_release(); + } + + void weak_add_ref() // nothrow + { + mutex_type::scoped_lock lock(mtx_); + ++weak_count_; + } + + void weak_release() // nothrow + { + long new_weak_count; + + { + mutex_type::scoped_lock lock(mtx_); + new_weak_count = --weak_count_; + } + + if(new_weak_count == 0) + { + destruct(); + } + } + + long use_count() const // nothrow + { + mutex_type::scoped_lock lock(mtx_); + return use_count_; + } + +private: + + sp_counted_base(sp_counted_base const &); + sp_counted_base & operator= (sp_counted_base const &); + + long use_count_; // #shared + long weak_count_; // #weak + (#shared != 0) + + mutable mutex_type mtx_; +}; + +template<class P, class D> class sp_counted_base_impl: public sp_counted_base +{ +private: + + P ptr; // copy constructor must not throw + D del; // copy constructor must not throw + + sp_counted_base_impl(sp_counted_base_impl const &); + sp_counted_base_impl & operator= (sp_counted_base_impl const &); + + typedef sp_counted_base_impl<P, D> this_type; + +public: + + // pre: initial_use_count <= initial_weak_count, d(p) must not throw + + sp_counted_base_impl(P p, D d): ptr(p), del(d) + { + } + + virtual void dispose() // nothrow + { + del(ptr); + } + + virtual void * get_deleter(std::type_info const & ti) + { + return ti == typeid(D)? &del: 0; + } + + void * operator new(std::size_t) + { + return std::allocator<this_type>().allocate(1, static_cast<this_type *>(0)); + } + + void operator delete(void * p) + { + std::allocator<this_type>().deallocate(static_cast<this_type *>(p), 1); + } +}; + +class weak_count; + +class shared_count +{ +private: + + sp_counted_base * pi_; + + friend class weak_count; + +public: + + shared_count(): pi_(0) // nothrow + { + } + + template<class P, class D> shared_count(P p, D d): pi_(0) + { + + try + { + pi_ = new sp_counted_base_impl<P, D>(p, d); + } + catch(...) + { + d(p); // delete p + throw; + } + + + pi_ = new sp_counted_base_impl<P, D>(p, d); + + if(pi_ == 0) + { + d(p); // delete p + myboost::throw_exception(std::bad_alloc()); + } + } + + // auto_ptr<Y> is special cased to provide the strong guarantee + + template<class Y> + explicit shared_count(std::auto_ptr<Y> & r): pi_(new sp_counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>())) + { + r.release(); + } + + ~shared_count() // nothrow + { + if(pi_ != 0) pi_->release(); + } + + shared_count(shared_count const & r): pi_(r.pi_) // nothrow + { + if(pi_ != 0) pi_->add_ref_copy(); + } + + explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 + + shared_count & operator= (shared_count const & r) // nothrow + { + sp_counted_base * tmp = r.pi_; + if(tmp != 0) tmp->add_ref_copy(); + if(pi_ != 0) pi_->release(); + pi_ = tmp; + + return *this; + } + + void swap(shared_count & r) // nothrow + { + sp_counted_base * tmp = r.pi_; + r.pi_ = pi_; + pi_ = tmp; + } + + long use_count() const // nothrow + { + return pi_ != 0? pi_->use_count(): 0; + } + + bool unique() const // nothrow + { + return use_count() == 1; + } + + friend inline bool operator==(shared_count const & a, shared_count const & b) + { + return a.pi_ == b.pi_; + } + + friend inline bool operator<(shared_count const & a, shared_count const & b) + { + 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: + + sp_counted_base * pi_; + + friend class shared_count; + +public: + + weak_count(): pi_(0) // nothrow + { + } + + weak_count(shared_count const & r): pi_(r.pi_) // nothrow + { + if(pi_ != 0) pi_->weak_add_ref(); + } + + weak_count(weak_count const & r): pi_(r.pi_) // nothrow + { + if(pi_ != 0) pi_->weak_add_ref(); + } + + ~weak_count() // nothrow + { + if(pi_ != 0) pi_->weak_release(); + } + + weak_count & operator= (shared_count const & r) // nothrow + { + 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 + { + 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 + { + sp_counted_base * tmp = r.pi_; + r.pi_ = pi_; + pi_ = tmp; + } + + long use_count() const // nothrow + { + return pi_ != 0? pi_->use_count(): 0; + } + + friend inline bool operator==(weak_count const & a, weak_count const & b) + { + return a.pi_ == b.pi_; + } + + friend inline bool operator<(weak_count const & a, weak_count const & b) + { + return std::less<sp_counted_base *>()(a.pi_, b.pi_); + } +}; + +inline shared_count::shared_count(weak_count const & r): pi_(r.pi_) +{ + if(pi_ != 0) + { + pi_->add_ref_lock(); + } + else + { + myboost::throw_exception(myboost::bad_weak_ptr()); + } +} + +} // namespace detail + +} // namespace myboost + +#endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED |