File indexing completed on 2025-01-18 09:53:52
0001
0002
0003
0004
0005
0006
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
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
0044
0045
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
0112
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
0135 template<typename T>
0136 void adl_swap(T &t1, T &t2)
0137 {
0138 swap(t1, t2);
0139 }
0140
0141
0142
0143
0144
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
0167
0168 void tracking_update()
0169 {
0170
0171 this->update_references_();
0172
0173 this->update_dependents_();
0174 }
0175
0176 void track_reference(enable_reference_tracking<Derived> &that)
0177 {
0178
0179
0180 that.purge_stale_deps_();
0181
0182 this->refs_.insert(that.self_);
0183
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
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
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
0272 (*cur)->track_dependency_(*this);
0273 }
0274 }
0275
0276 void update_dependents_()
0277 {
0278
0279
0280
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)
0293 return;
0294
0295
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
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
0319 #ifdef BOOST_XPRESSIVE_DEBUG_TRACKING_POINTER
0320 void dump_(std::ostream &sout) const;
0321 #endif
0322
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
0343 #ifdef BOOST_XPRESSIVE_DEBUG_TRACKING_POINTER
0344
0345
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
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
0374
0375
0376
0377
0378
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
0400
0401 if(this != &that)
0402 {
0403 if(that)
0404 {
0405 if(that.has_deps_() || this->has_deps_())
0406 {
0407 this->fork_();
0408 this->impl_->tracking_copy(*that);
0409 }
0410 else
0411 {
0412 this->impl_ = that.impl_;
0413 }
0414 }
0415 else if(*this)
0416 {
0417 this->impl_->tracking_clear();
0418 }
0419 }
0420 return *this;
0421 }
0422
0423
0424 void swap(tracking_ptr<element_type> &that)
0425 {
0426 this->impl_.swap(that.impl_);
0427 }
0428
0429
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
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
0464 element_type const *operator ->() const
0465 {
0466 return get_pointer(this->impl_);
0467 }
0468
0469
0470 element_type const &operator *() const
0471 {
0472 return *this->impl_;
0473 }
0474
0475 private:
0476
0477
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
0492 bool has_deps_() const
0493 {
0494 return this->impl_ && this->impl_->has_deps_();
0495 }
0496
0497
0498 mutable intrusive_ptr<element_type> impl_;
0499 };
0500
0501 }}}
0502
0503 #endif