Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:52

0001 ///////////////////////////////////////////////////////////////////////////////
0002 // tracking_ptr.hpp
0003 //
0004 //  Copyright 2008 Eric Niebler. Distributed under the Boost
0005 //  Software License, Version 1.0. (See accompanying file
0006 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 #ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_TRACKING_PTR_HPP_EAN_10_04_2005
0009 #define BOOST_XPRESSIVE_DETAIL_UTILITY_TRACKING_PTR_HPP_EAN_10_04_2005
0010 
0011 // MS compatible compilers support #pragma once
0012 #if defined(_MSC_VER)
0013 # pragma once
0014 #endif
0015 
0016 #ifdef BOOST_XPRESSIVE_DEBUG_TRACKING_POINTER
0017 # include <iostream>
0018 #endif
0019 #include <set>
0020 #include <functional>
0021 #include <boost/config.hpp>
0022 #include <boost/assert.hpp>
0023 #include <boost/weak_ptr.hpp>
0024 #include <boost/shared_ptr.hpp>
0025 #include <boost/mpl/assert.hpp>
0026 #include <boost/intrusive_ptr.hpp>
0027 #include <boost/detail/workaround.hpp>
0028 #include <boost/detail/atomic_count.hpp>
0029 #include <boost/iterator/iterator_facade.hpp>
0030 #include <boost/iterator/filter_iterator.hpp>
0031 #include <boost/type_traits/is_base_and_derived.hpp>
0032 
0033 namespace boost { namespace xpressive { namespace detail
0034 {
0035 
0036 template<typename Type>
0037 struct tracking_ptr;
0038 
0039 template<typename Derived>
0040 struct enable_reference_tracking;
0041 
0042 ///////////////////////////////////////////////////////////////////////////////
0043 // weak_iterator
0044 //  steps through a set of weak_ptr, converts to shared_ptrs on the fly and
0045 //  removes from the set the weak_ptrs that have expired.
0046 template<typename Derived>
0047 struct weak_iterator
0048   : iterator_facade
0049     <
0050         weak_iterator<Derived>
0051       , shared_ptr<Derived> const
0052       , std::forward_iterator_tag
0053     >
0054 {
0055     typedef std::set<weak_ptr<Derived> > set_type;
0056     typedef typename set_type::iterator base_iterator;
0057 
0058     weak_iterator()
0059       : cur_()
0060       , iter_()
0061       , set_(0)
0062     {
0063     }
0064 
0065     weak_iterator(base_iterator iter, set_type *set)
0066       : cur_()
0067       , iter_(iter)
0068       , set_(set)
0069     {
0070         this->satisfy_();
0071     }
0072 
0073 private:
0074     friend class boost::iterator_core_access;
0075 
0076     shared_ptr<Derived> const &dereference() const
0077     {
0078         return this->cur_;
0079     }
0080 
0081     void increment()
0082     {
0083         ++this->iter_;
0084         this->satisfy_();
0085     }
0086 
0087     bool equal(weak_iterator<Derived> const &that) const
0088     {
0089         return this->iter_ == that.iter_;
0090     }
0091 
0092     void satisfy_()
0093     {
0094         while(this->iter_ != this->set_->end())
0095         {
0096             this->cur_ = this->iter_->lock();
0097             if(this->cur_)
0098                 return;
0099             base_iterator tmp = this->iter_++;
0100             this->set_->erase(tmp);
0101         }
0102         this->cur_.reset();
0103     }
0104 
0105     shared_ptr<Derived> cur_;
0106     base_iterator iter_;
0107     set_type *set_;
0108 };
0109 
0110 ///////////////////////////////////////////////////////////////////////////////
0111 // filter_self
0112 //  for use with a filter_iterator to filter a node out of a list of dependencies
0113 template<typename Derived>
0114 struct filter_self
0115 {
0116     typedef shared_ptr<Derived> argument_type;
0117     typedef bool result_type;
0118 
0119     filter_self(enable_reference_tracking<Derived> *self)
0120       : self_(self)
0121     {
0122     }
0123 
0124     bool operator ()(shared_ptr<Derived> const &that) const
0125     {
0126         return this->self_ != that.get();
0127     }
0128 
0129 private:
0130     enable_reference_tracking<Derived> *self_;
0131 };
0132 
0133 ///////////////////////////////////////////////////////////////////////////////
0134 // swap without bringing in std::swap -- must be found by ADL.
0135 template<typename T>
0136 void adl_swap(T &t1, T &t2)
0137 {
0138     swap(t1, t2);
0139 }
0140 
0141 ///////////////////////////////////////////////////////////////////////////////
0142 // enable_reference_tracking
0143 //   inherit from this type to enable reference tracking for a type. You can
0144 //   then use tracking_ptr (below) as a holder for derived objects.
0145 //
0146 template<typename Derived>
0147 struct enable_reference_tracking
0148 {
0149     typedef std::set<shared_ptr<Derived> > references_type;
0150     typedef std::set<weak_ptr<Derived> > dependents_type;
0151 
0152     void tracking_copy(Derived const &that)
0153     {
0154         if(&this->derived_() != &that)
0155         {
0156             this->raw_copy_(that);
0157             this->tracking_update();
0158         }
0159     }
0160 
0161     void tracking_clear()
0162     {
0163         this->raw_copy_(Derived());
0164     }
0165 
0166     // called automatically as a result of a tracking_copy(). Must be called explicitly
0167     // if you change the references without calling tracking_copy().
0168     void tracking_update()
0169     {
0170         // add "this" as a dependency to all the references
0171         this->update_references_();
0172         // notify our dependencies that we have new references
0173         this->update_dependents_();
0174     }
0175 
0176     void track_reference(enable_reference_tracking<Derived> &that)
0177     {
0178         // avoid some unbounded memory growth in certain circumstances by
0179         // opportunistically removing stale dependencies from "that"
0180         that.purge_stale_deps_();
0181         // add "that" as a reference
0182         this->refs_.insert(that.self_);
0183         // also inherit that's references
0184         this->refs_.insert(that.refs_.begin(), that.refs_.end());
0185     }
0186 
0187     long use_count() const
0188     {
0189         return this->cnt_;
0190     }
0191 
0192     void add_ref()
0193     {
0194         ++this->cnt_;
0195     }
0196 
0197     void release()
0198     {
0199         BOOST_ASSERT(0 < this->cnt_);
0200         if(0 == --this->cnt_)
0201         {
0202             this->refs_.clear();
0203             this->self_.reset();
0204         }
0205     }
0206 
0207     //{{AFX_DEBUG
0208     #ifdef BOOST_XPRESSIVE_DEBUG_TRACKING_POINTER
0209     friend std::ostream &operator <<(std::ostream &sout, enable_reference_tracking<Derived> const &that)
0210     {
0211         that.dump_(sout);
0212         return sout;
0213     }
0214     #endif
0215     //}}AFX_DEBUG
0216 
0217 protected:
0218 
0219     enable_reference_tracking()
0220       : refs_()
0221       , deps_()
0222       , self_()
0223       , cnt_(0)
0224     {
0225     }
0226 
0227     enable_reference_tracking(enable_reference_tracking<Derived> const &that)
0228       : refs_()
0229       , deps_()
0230       , self_()
0231       , cnt_(0)
0232     {
0233         this->operator =(that);
0234     }
0235 
0236     enable_reference_tracking<Derived> &operator =(enable_reference_tracking<Derived> const &that)
0237     {
0238         references_type(that.refs_).swap(this->refs_);
0239         return *this;
0240     }
0241 
0242     void swap(enable_reference_tracking<Derived> &that)
0243     {
0244         this->refs_.swap(that.refs_);
0245     }
0246 
0247 private:
0248     friend struct tracking_ptr<Derived>;
0249 
0250     Derived &derived_()
0251     {
0252         return *static_cast<Derived *>(this);
0253     }
0254 
0255     void raw_copy_(Derived that)
0256     {
0257         detail::adl_swap(this->derived_(), that);
0258     }
0259 
0260     bool has_deps_() const
0261     {
0262         return !this->deps_.empty();
0263     }
0264 
0265     void update_references_()
0266     {
0267         typename references_type::iterator cur = this->refs_.begin();
0268         typename references_type::iterator end = this->refs_.end();
0269         for(; cur != end; ++cur)
0270         {
0271             // for each reference, add this as a dependency
0272             (*cur)->track_dependency_(*this);
0273         }
0274     }
0275 
0276     void update_dependents_()
0277     {
0278         // called whenever this regex object changes (i.e., is assigned to). it walks
0279         // the list of dependent regexes and updates *their* lists of references,
0280         // thereby spreading out the reference counting responsibility evenly.
0281         weak_iterator<Derived> cur(this->deps_.begin(), &this->deps_);
0282         weak_iterator<Derived> end(this->deps_.end(), &this->deps_);
0283 
0284         for(; cur != end; ++cur)
0285         {
0286             (*cur)->track_reference(*this);
0287         }
0288     }
0289 
0290     void track_dependency_(enable_reference_tracking<Derived> &dep)
0291     {
0292         if(this == &dep) // never add ourself as a dependency
0293             return;
0294 
0295         // add dep as a dependency
0296         this->deps_.insert(dep.self_);
0297 
0298         filter_self<Derived> not_self(this);
0299         weak_iterator<Derived> begin(dep.deps_.begin(), &dep.deps_);
0300         weak_iterator<Derived> end(dep.deps_.end(), &dep.deps_);
0301 
0302         // also inherit dep's dependencies
0303         this->deps_.insert(
0304             make_filter_iterator(not_self, begin, end)
0305           , make_filter_iterator(not_self, end, end)
0306         );
0307     }
0308 
0309     void purge_stale_deps_()
0310     {
0311         weak_iterator<Derived> cur(this->deps_.begin(), &this->deps_);
0312         weak_iterator<Derived> end(this->deps_.end(), &this->deps_);
0313 
0314         for(; cur != end; ++cur)
0315             ;
0316     }
0317 
0318     //{{AFX_DEBUG
0319     #ifdef BOOST_XPRESSIVE_DEBUG_TRACKING_POINTER
0320     void dump_(std::ostream &sout) const;
0321     #endif
0322     //}}AFX_DEBUG
0323 
0324     references_type refs_;
0325     dependents_type deps_;
0326     shared_ptr<Derived> self_;
0327     boost::detail::atomic_count cnt_;
0328 };
0329 
0330 template<typename Derived>
0331 inline void intrusive_ptr_add_ref(enable_reference_tracking<Derived> *p)
0332 {
0333     p->add_ref();
0334 }
0335 
0336 template<typename Derived>
0337 inline void intrusive_ptr_release(enable_reference_tracking<Derived> *p)
0338 {
0339     p->release();
0340 }
0341 
0342 //{{AFX_DEBUG
0343 #ifdef BOOST_XPRESSIVE_DEBUG_TRACKING_POINTER
0344 ///////////////////////////////////////////////////////////////////////////////
0345 // dump_
0346 //
0347 template<typename Derived>
0348 inline void enable_reference_tracking<Derived>::dump_(std::ostream &sout) const
0349 {
0350     shared_ptr<Derived> this_ = this->self_;
0351     sout << "0x" << (void*)this << " cnt=" << this_.use_count()-1 << " refs={";
0352     typename references_type::const_iterator cur1 = this->refs_.begin();
0353     typename references_type::const_iterator end1 = this->refs_.end();
0354     for(; cur1 != end1; ++cur1)
0355     {
0356         sout << "0x" << (void*)&**cur1 << ',';
0357     }
0358     sout << "} deps={";
0359     typename dependents_type::const_iterator cur2 = this->deps_.begin();
0360     typename dependents_type::const_iterator end2 = this->deps_.end();
0361     for(; cur2 != end2; ++cur2)
0362     {
0363         // ericne, 27/nov/05: CW9_4 doesn't like if(shared_ptr x = y)
0364         shared_ptr<Derived> dep = cur2->lock();
0365         if(dep.get())
0366         {
0367             sout << "0x" << (void*)&*dep << ',';
0368         }
0369     }
0370     sout << '}';
0371 }
0372 #endif
0373 //}}AFX_DEBUG
0374 
0375 ///////////////////////////////////////////////////////////////////////////////
0376 // tracking_ptr
0377 //   holder for a reference-tracked type. Does cycle-breaking, lazy initialization
0378 //   and copy-on-write. TODO: implement move semantics.
0379 //
0380 template<typename Type>
0381 struct tracking_ptr
0382 {
0383     BOOST_MPL_ASSERT((is_base_and_derived<enable_reference_tracking<Type>, Type>));
0384     typedef Type element_type;
0385 
0386     tracking_ptr()
0387       : impl_()
0388     {
0389     }
0390 
0391     tracking_ptr(tracking_ptr<element_type> const &that)
0392       : impl_()
0393     {
0394         this->operator =(that);
0395     }
0396 
0397     tracking_ptr<element_type> &operator =(tracking_ptr<element_type> const &that)
0398     {
0399         // Note: the copy-and-swap idiom doesn't work here if has_deps_()==true
0400         // because it invalidates references to the element_type object.
0401         if(this != &that)
0402         {
0403             if(that)
0404             {
0405                 if(that.has_deps_() || this->has_deps_())
0406                 {
0407                     this->fork_(); // deep copy, forks data if necessary
0408                     this->impl_->tracking_copy(*that);
0409                 }
0410                 else
0411                 {
0412                     this->impl_ = that.impl_; // shallow, copy-on-write
0413                 }
0414             }
0415             else if(*this)
0416             {
0417                 this->impl_->tracking_clear();
0418             }
0419         }
0420         return *this;
0421     }
0422 
0423     // NOTE: this does *not* do tracking. Can't provide a non-throwing swap that tracks references
0424     void swap(tracking_ptr<element_type> &that) // throw()
0425     {
0426         this->impl_.swap(that.impl_);
0427     }
0428 
0429     // calling this forces this->impl_ to fork.
0430     shared_ptr<element_type> const &get() const
0431     {
0432         if(intrusive_ptr<element_type> impl = this->fork_())
0433         {
0434             this->impl_->tracking_copy(*impl);
0435         }
0436         return this->impl_->self_;
0437     }
0438 
0439     // smart-pointer operators
0440     #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
0441 
0442     operator bool() const
0443     {
0444         return this->impl_;
0445     }
0446 
0447     #else
0448 
0449     typedef intrusive_ptr<element_type> tracking_ptr::* unspecified_bool_type;
0450 
0451     operator unspecified_bool_type() const
0452     {
0453         return this->impl_ ? &tracking_ptr::impl_ : 0;
0454     }
0455 
0456     #endif
0457 
0458     bool operator !() const
0459     {
0460         return !this->impl_;
0461     }
0462 
0463     // Since this does not un-share the data, it returns a ptr-to-const
0464     element_type const *operator ->() const
0465     {
0466         return get_pointer(this->impl_);
0467     }
0468 
0469     // Since this does not un-share the data, it returns a ref-to-const
0470     element_type const &operator *() const
0471     {
0472         return *this->impl_;
0473     }
0474 
0475 private:
0476 
0477     // calling this forces impl_ to fork.
0478     intrusive_ptr<element_type> fork_() const
0479     {
0480         intrusive_ptr<element_type> impl;
0481         if(!this->impl_ || 1 != this->impl_->use_count())
0482         {
0483             impl = this->impl_;
0484             BOOST_ASSERT(!this->has_deps_());
0485             shared_ptr<element_type> simpl(new element_type);
0486             this->impl_ = get_pointer(simpl->self_ = simpl);
0487         }
0488         return impl;
0489     }
0490 
0491     // does anybody have a dependency on us?
0492     bool has_deps_() const
0493     {
0494         return this->impl_ && this->impl_->has_deps_();
0495     }
0496 
0497     // mutable to allow lazy initialization
0498     mutable intrusive_ptr<element_type> impl_;
0499 };
0500 
0501 }}} // namespace boost::xpressive::detail
0502 
0503 #endif