diff --git a/boost/unordered/detail/fwd.hpp b/boost/unordered/detail/fwd.hpp index c1c31ff..a4fdae1 100644 --- a/boost/unordered/detail/fwd.hpp +++ b/boost/unordered/detail/fwd.hpp @@ -233,16 +233,31 @@ namespace boost { namespace unordered_detail { return node::get_value(node_); } - void increment_bucket(node_ptr n) { - while(!n) { - ++bucket_; - n = bucket_->next_; + void increment_bucket() { + if(!node_) { + do { + ++bucket_; + node_ = bucket_->next_; + } while(!node_); + + if(bucket_ == node_) { + bucket_ = bucket_ptr(); + node_ = node_ptr(); + } } - node_ = bucket_ == n ? node_ptr() : n; } void increment() { - increment_bucket(node_->next_); + node_ = node_->next_; + increment_bucket(); + } + + void lazy_increment() { + node_ = node_->next_; + } + + void check_increment() { + if(bucket_) increment_bucket(); } }; @@ -738,6 +753,7 @@ namespace boost { namespace unordered_detail { static BOOST_DEDUCED_TYPENAME Iterator::base const& get(Iterator const& it) { + it.base_.check_increment(); return it.base_; } }; @@ -876,34 +892,41 @@ namespace boost { namespace unordered_detail { typedef BOOST_DEDUCED_TYPENAME buckets::iterator_base base; typedef hash_const_iterator const_iterator; friend class hash_const_iterator; - base base_; + mutable base base_; public: hash_iterator() : base_() {} explicit hash_iterator(base const& x) : base_(x) {} BOOST_DEDUCED_TYPENAME A::reference operator*() const { + base_.check_increment(); return *base_; } value_type* operator->() const { + base_.check_increment(); return &*base_; } hash_iterator& operator++() { - base_.increment(); return *this; + base_.check_increment(); base_.increment(); return *this; } hash_iterator operator++(int) { - hash_iterator tmp(base_); base_.increment(); return tmp; + base_.check_increment(); hash_iterator tmp(base_); + base_.increment(); return tmp; } bool operator==(hash_iterator const& x) const { + base_.check_increment(); x.base_.check_increment(); return base_ == x.base_; } bool operator==(const_iterator const& x) const { + base_.check_increment(); x.base_.check_increment(); return base_ == x.base_; } bool operator!=(hash_iterator const& x) const { + base_.check_increment(); x.base_.check_increment(); return base_ != x.base_; } bool operator!=(const_iterator const& x) const { + base_.check_increment(); x.base_.check_increment(); return base_ != x.base_; } }; @@ -927,7 +950,7 @@ namespace boost { namespace unordered_detail { typedef hash_iterator iterator; friend class hash_iterator; friend class iterator_access; - base base_; + mutable base base_; public: @@ -935,27 +958,34 @@ namespace boost { namespace unordered_detail { explicit hash_const_iterator(base const& x) : base_(x) {} hash_const_iterator(iterator const& x) : base_(x.base_) {} BOOST_DEDUCED_TYPENAME A::const_reference operator*() const { + base_.check_increment(); return *base_; } value_type const* operator->() const { + base_.check_increment(); return &*base_; } hash_const_iterator& operator++() { - base_.increment(); return *this; + base_.check_increment(); base_.increment(); return *this; } hash_const_iterator operator++(int) { - hash_const_iterator tmp(base_); base_.increment(); return tmp; + base_.check_increment(); hash_const_iterator tmp(base_); + base_.increment(); return tmp; } bool operator==(iterator const& x) const { + base_.check_increment(); x.base_.check_increment(); return base_ == x.base_; } bool operator==(hash_const_iterator const& x) const { + base_.check_increment(); x.base_.check_increment(); return base_ == x.base_; } bool operator!=(iterator const& x) const { + base_.check_increment(); x.base_.check_increment(); return base_ != x.base_; } bool operator!=(hash_const_iterator const& x) const { + base_.check_increment(); x.base_.check_increment(); return base_ != x.base_; } }; diff --git a/boost/unordered/detail/table.hpp b/boost/unordered/detail/table.hpp index 198548d..7546edc 100644 --- a/boost/unordered/detail/table.hpp +++ b/boost/unordered/detail/table.hpp @@ -634,7 +634,8 @@ namespace boost { namespace unordered_detail { if (BOOST_UNORDERED_BORLAND_BOOL(it)) { iterator_base first(iterator_base(bucket, it)); iterator_base second(first); - second.increment_bucket(node::next_group(second.node_)); + // Note: this is a lazy increment. + second.node_ = node::next_group(second.node_); return iterator_pair(first, second); } else { @@ -702,12 +703,16 @@ namespace boost { namespace unordered_detail { { BOOST_ASSERT(r.node_); iterator_base next = r; - next.increment(); + next.lazy_increment(); --this->size_; node::unlink_node(*r.bucket_, r.node_); this->delete_node(r.node_); // r has been invalidated but its bucket is still valid - this->recompute_begin_bucket(r.bucket_, next.bucket_); + //this->recompute_begin_bucket(r.bucket_, next.bucket_); + if(next.bucket_ == this->cached_begin_bucket_ && !next.bucket_->next_) { + next.check_increment(); + this->cached_begin_bucket_ = next.bucket_; + } return next; }