Added boost header
This commit is contained in:
494
test/external/boost/xpressive/detail/utility/tracking_ptr.hpp
vendored
Normal file
494
test/external/boost/xpressive/detail/utility/tracking_ptr.hpp
vendored
Normal file
@@ -0,0 +1,494 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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 dependencies
|
||||
template<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_DEBUG
|
||||
|
||||
protected:
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user