tracking_ptr.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 495 行

HPP
495
字号
///////////////////////////////////////////////////////////////////////////////// tracking_ptr.hpp////  Copyright 2008 Eric Niebler. 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)#ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_TRACKING_PTR_HPP_EAN_10_04_2005#define BOOST_XPRESSIVE_DETAIL_UTILITY_TRACKING_PTR_HPP_EAN_10_04_2005// MS compatible compilers support #pragma once#if defined(_MSC_VER) && (_MSC_VER >= 1020)# pragma once#endif#ifdef BOOST_XPRESSIVE_DEBUG_TRACKING_POINTER# include <iostream>#endif#include <set>#include <functional>#include <boost/config.hpp>#include <boost/assert.hpp>#include <boost/weak_ptr.hpp>#include <boost/shared_ptr.hpp>#include <boost/mpl/assert.hpp>#include <boost/intrusive_ptr.hpp>#include <boost/detail/workaround.hpp>#include <boost/detail/atomic_count.hpp>#include <boost/iterator/iterator_facade.hpp>#include <boost/iterator/filter_iterator.hpp>#include <boost/type_traits/is_base_and_derived.hpp>namespace boost { namespace xpressive { namespace detail{template<typename Type>struct tracking_ptr;template<typename Derived>struct enable_reference_tracking;///////////////////////////////////////////////////////////////////////////////// weak_iterator//  steps through a set of weak_ptr, converts to shared_ptrs on the fly and//  removes from the set the weak_ptrs that have expired.template<typename Derived>struct weak_iterator  : iterator_facade    <        weak_iterator<Derived>      , shared_ptr<Derived> const      , std::forward_iterator_tag    >{    typedef std::set<weak_ptr<Derived> > set_type;    typedef typename set_type::iterator base_iterator;    weak_iterator()      : cur_()      , iter_()      , set_(0)    {    }    weak_iterator(base_iterator iter, set_type *set)      : cur_()      , iter_(iter)      , set_(set)    {        this->satisfy_();    }private:    friend class boost::iterator_core_access;    shared_ptr<Derived> const &dereference() const    {        return this->cur_;    }    void increment()    {        ++this->iter_;        this->satisfy_();    }    bool equal(weak_iterator<Derived> const &that) const    {        return this->iter_ == that.iter_;    }    void satisfy_()    {        while(this->iter_ != this->set_->end())        {            this->cur_ = this->iter_->lock();            if(this->cur_)                return;            base_iterator tmp = this->iter_++;            this->set_->erase(tmp);        }        this->cur_.reset();    }    shared_ptr<Derived> cur_;    base_iterator iter_;    set_type *set_;};///////////////////////////////////////////////////////////////////////////////// filter_self//  for use with a filter_iterator to filter a node out of a list of dependenciestemplate<typename Derived>struct filter_self  : std::unary_function<shared_ptr<Derived>, bool>{    filter_self(enable_reference_tracking<Derived> *self)      : self_(self)    {    }    bool operator ()(shared_ptr<Derived> const &that) const    {        return this->self_ != that.get();    }private:    enable_reference_tracking<Derived> *self_;};///////////////////////////////////////////////////////////////////////////////// swap without bringing in std::swap -- must be found by ADL.template<typename T>void adl_swap(T &t1, T &t2){    swap(t1, t2);}///////////////////////////////////////////////////////////////////////////////// enable_reference_tracking//   inherit from this type to enable reference tracking for a type. You can//   then use tracking_ptr (below) as a holder for derived objects.//template<typename Derived>struct enable_reference_tracking{    typedef std::set<shared_ptr<Derived> > references_type;    typedef std::set<weak_ptr<Derived> > dependents_type;    void tracking_copy(Derived const &that)    {        if(&this->derived_() != &that)        {            this->raw_copy_(that);            this->tracking_update();        }    }    void tracking_clear()    {        this->raw_copy_(Derived());    }    // called automatically as a result of a tracking_copy(). Must be called explicitly    // if you change the references without calling tracking_copy().    void tracking_update()    {        // add "this" as a dependency to all the references        this->update_references_();        // notify our dependencies that we have new references        this->update_dependents_();    }    void track_reference(enable_reference_tracking<Derived> &that)    {        // avoid some unbounded memory growth in certain circumstances by        // opportunistically removing stale dependencies from "that"        that.purge_stale_deps_();        // add "that" as a reference        this->refs_.insert(that.self_);        // also inherit that's references        this->refs_.insert(that.refs_.begin(), that.refs_.end());    }    long use_count() const    {        return this->cnt_;    }    void add_ref()    {        ++this->cnt_;    }    void release()    {        BOOST_ASSERT(0 < this->cnt_);        if(0 == --this->cnt_)        {            this->refs_.clear();            this->self_.reset();        }    }    //{{AFX_DEBUG    #ifdef BOOST_XPRESSIVE_DEBUG_TRACKING_POINTER    friend std::ostream &operator <<(std::ostream &sout, enable_reference_tracking<Derived> const &that)    {        that.dump_(sout);        return sout;    }    #endif    //}}AFX_DEBUGprotected:    enable_reference_tracking()      : refs_()      , deps_()      , self_()      , cnt_(0)    {    }    enable_reference_tracking(enable_reference_tracking<Derived> const &that)      : refs_()      , deps_()      , self_()      , cnt_(0)    {        this->operator =(that);    }    enable_reference_tracking<Derived> &operator =(enable_reference_tracking<Derived> const &that)    {        references_type(that.refs_).swap(this->refs_);        return *this;    }    void swap(enable_reference_tracking<Derived> &that)    {        this->refs_.swap(that.refs_);    }private:    friend struct tracking_ptr<Derived>;    Derived &derived_()    {        return *static_cast<Derived *>(this);    }    void raw_copy_(Derived that)    {        detail::adl_swap(this->derived_(), that);    }    bool has_deps_() const    {        return !this->deps_.empty();    }    void update_references_()    {        typename references_type::iterator cur = this->refs_.begin();        typename references_type::iterator end = this->refs_.end();        for(; cur != end; ++cur)        {            // for each reference, add this as a dependency            (*cur)->track_dependency_(*this);        }    }    void update_dependents_()    {        // called whenever this regex object changes (i.e., is assigned to). it walks        // the list of dependent regexes and updates *their* lists of references,        // thereby spreading out the reference counting responsibility evenly.        weak_iterator<Derived> cur(this->deps_.begin(), &this->deps_);        weak_iterator<Derived> end(this->deps_.end(), &this->deps_);        for(; cur != end; ++cur)        {            (*cur)->track_reference(*this);        }    }    void track_dependency_(enable_reference_tracking<Derived> &dep)    {        if(this == &dep) // never add ourself as a dependency            return;        // add dep as a dependency        this->deps_.insert(dep.self_);        filter_self<Derived> not_self(this);        weak_iterator<Derived> begin(dep.deps_.begin(), &dep.deps_);        weak_iterator<Derived> end(dep.deps_.end(), &dep.deps_);        // also inherit dep's dependencies        this->deps_.insert(            make_filter_iterator(not_self, begin, end)          , make_filter_iterator(not_self, end, end)        );    }    void purge_stale_deps_()    {        weak_iterator<Derived> cur(this->deps_.begin(), &this->deps_);        weak_iterator<Derived> end(this->deps_.end(), &this->deps_);        for(; cur != end; ++cur)            ;    }    //{{AFX_DEBUG    #ifdef BOOST_XPRESSIVE_DEBUG_TRACKING_POINTER    void dump_(std::ostream &sout) const;    #endif    //}}AFX_DEBUG    references_type refs_;    dependents_type deps_;    shared_ptr<Derived> self_;    boost::detail::atomic_count cnt_;};template<typename Derived>inline void intrusive_ptr_add_ref(enable_reference_tracking<Derived> *p){    p->add_ref();}template<typename Derived>inline void intrusive_ptr_release(enable_reference_tracking<Derived> *p){    p->release();}//{{AFX_DEBUG#ifdef BOOST_XPRESSIVE_DEBUG_TRACKING_POINTER///////////////////////////////////////////////////////////////////////////////// dump_//template<typename Derived>inline void enable_reference_tracking<Derived>::dump_(std::ostream &sout) const{    shared_ptr<Derived> this_ = this->self_;    sout << "0x" << (void*)this << " cnt=" << this_.use_count()-1 << " refs={";    typename references_type::const_iterator cur1 = this->refs_.begin();    typename references_type::const_iterator end1 = this->refs_.end();    for(; cur1 != end1; ++cur1)    {        sout << "0x" << (void*)&**cur1 << ',';    }    sout << "} deps={";    typename dependents_type::const_iterator cur2 = this->deps_.begin();    typename dependents_type::const_iterator end2 = this->deps_.end();    for(; cur2 != end2; ++cur2)    {        // ericne, 27/nov/05: CW9_4 doesn't like if(shared_ptr x = y)        shared_ptr<Derived> dep = cur2->lock();        if(dep.get())        {            sout << "0x" << (void*)&*dep << ',';        }    }    sout << '}';}#endif//}}AFX_DEBUG///////////////////////////////////////////////////////////////////////////////// tracking_ptr//   holder for a reference-tracked type. Does cycle-breaking, lazy initialization//   and copy-on-write. TODO: implement move semantics.//template<typename Type>struct tracking_ptr{    BOOST_MPL_ASSERT((is_base_and_derived<enable_reference_tracking<Type>, Type>));    typedef Type element_type;    tracking_ptr()      : impl_()    {    }    tracking_ptr(tracking_ptr<element_type> const &that)      : impl_()    {        this->operator =(that);    }    tracking_ptr<element_type> &operator =(tracking_ptr<element_type> const &that)    {        // Note: the copy-and-swap idiom doesn't work here if has_deps_()==true        // because it invalidates references to the element_type object.        if(this != &that)        {            if(that)            {                if(that.has_deps_() || this->has_deps_())                {                    this->fork_(); // deep copy, forks data if necessary                    this->impl_->tracking_copy(*that);                }                else                {                    this->impl_ = that.impl_; // shallow, copy-on-write                }            }            else if(*this)            {                this->impl_->tracking_clear();            }        }        return *this;    }    // NOTE: this does *not* do tracking. Can't provide a non-throwing swap that tracks references    void swap(tracking_ptr<element_type> &that) // throw()    {        this->impl_.swap(that.impl_);    }    // calling this forces this->impl_ to fork.    shared_ptr<element_type> const &get() const    {        if(intrusive_ptr<element_type> impl = this->fork_())        {            this->impl_->tracking_copy(*impl);        }        return this->impl_->self_;    }    #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)    typedef bool unspecified_bool_type;    #else    typedef typename intrusive_ptr<element_type>::unspecified_bool_type unspecified_bool_type;    #endif    // smart-pointer operators    operator unspecified_bool_type() const    {        return this->impl_;    }    bool operator !() const    {        return !this->impl_;    }    // Since this does not un-share the data, it returns a ptr-to-const    element_type const *operator ->() const    {        return get_pointer(this->impl_);    }    // Since this does not un-share the data, it returns a ref-to-const    element_type const &operator *() const    {        return *this->impl_;    }private:    // calling this forces impl_ to fork.    intrusive_ptr<element_type> fork_() const    {        intrusive_ptr<element_type> impl;        if(!this->impl_ || 1 != this->impl_->use_count())        {            impl = this->impl_;            BOOST_ASSERT(!this->has_deps_());            shared_ptr<element_type> simpl(new element_type);            this->impl_ = get_pointer(simpl->self_ = simpl);        }        return impl;    }    // does anybody have a dependency on us?    bool has_deps_() const    {        return this->impl_ && this->impl_->has_deps_();    }    // mutable to allow lazy initialization    mutable intrusive_ptr<element_type> impl_;};}}} // namespace boost::xpressive::detail#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?