diff --git a/src/unit_map.cpp b/src/unit_map.cpp index 422bec275b53..349e5ee0b850 100644 --- a/src/unit_map.cpp +++ b/src/unit_map.cpp @@ -33,19 +33,13 @@ static lg::log_domain log_engine("engine"); unit_map::unit_map() : umap_() , lmap_() - , ilist_() - , the_end_() { - init_end(); } unit_map::unit_map(const unit_map& that) : umap_() , lmap_() - , ilist_() - , the_end_() { - init_end(); for (const_unit_iterator i = that.begin(); i != that.end(); ++i) { add(i->get_location(), *i); } @@ -62,18 +56,16 @@ void unit_map::swap(unit_map &o) { std::swap(umap_, o.umap_); std::swap(lmap_, o.lmap_); - std::swap(ilist_, o.ilist_); - std::swap(the_end_, o.the_end_); } unit_map::~unit_map() { clear(true); } -unit_map::t_ilist::iterator unit_map::begin_core() const { +unit_map::t_umap::iterator unit_map::begin_core() const { self_check(); - t_ilist::iterator i = ilist_.begin(); - while (i != the_end_ && (i->unit == NULL)) { ++i; } + t_umap::iterator i = umap_.begin(); + while (i != umap_.end() && (i->second.unit == NULL)) { ++i; } return i; } @@ -92,32 +84,32 @@ std::pair unit_map::move(const map_location &src, //Find the unit at the src location t_lmap::iterator i = lmap_.find(src); - if(i == lmap_.end()) { return std::make_pair(make_unit_iterator(the_end_), false);} + if(i == lmap_.end()) { return std::make_pair(make_unit_iterator(i), false);} - t_ilist::iterator lit(i->second); + t_umap::iterator uit(i->second); - if(src == dst){ return std::make_pair(make_unit_iterator(lit),true);} + if(src == dst){ return std::make_pair(make_unit_iterator(uit), true);} //Fail if there is no unit to move - unit *p = lit->unit; - if(p == NULL){ return std::make_pair(make_unit_iterator(lit), false);} + unit *p = uit->second.unit; + if(p == NULL){ return std::make_pair(make_unit_iterator(uit), false);} p->set_location(dst); lmap_.erase(i); - std::pair res = lmap_.insert(std::make_pair(dst, lit)); + std::pair res = lmap_.insert(std::make_pair(dst, uit)); //Fail and don't move if the destination is already occupied if(res.second == false) { p->set_location(src); - lmap_.insert(std::make_pair(src, lit)); - return std::make_pair(make_unit_iterator(lit), false); + lmap_.insert(std::make_pair(src, uit)); + return std::make_pair(make_unit_iterator(uit), false); } self_check(); - return std::make_pair(make_unit_iterator(lit), true); + return std::make_pair(make_unit_iterator(uit), true); } @@ -125,9 +117,9 @@ std::pair unit_map::move(const map_location &src, It needs to succeed on the insertion to the umap and to the lmap otherwise all operations are reverted. -1. Insert a unit_pod into the list -2. Try insertion into the umap and remove the list item on failure -3. Try insertion in the lmap and remove the umap and the list item on failure +1. Construct a unit_pod +2. Try insertion into the umap +3. Try insertion in the lmap and remove the umap entry on failure The one oddity is that to facilitate non-invalidating iterators the list sometimes has NULL pointers which should be used when they correspond @@ -143,29 +135,25 @@ std::pair unit_map::insert(unit *p) { if (!loc.valid()) { ERR_NG << "Trying to add " << p->name() << " - " << p->id() << " at an invalid location; Discarding.\n"; - return std::make_pair(make_unit_iterator(the_end_), false); + return std::make_pair(make_unit_iterator(umap_.end()), false); } unit_pod upod; upod.unit = p; - upod.deleted_uid = unit_id; - ilist_.push_front(upod); - t_ilist::iterator lit(ilist_.begin()); DBG_NG << "Adding unit " << p->underlying_id() << " - " << p->id() << " to location: (" << loc << ")\n"; - std::pair uinsert = umap_.insert(std::make_pair(unit_id, lit )); + std::pair uinsert = umap_.insert(std::make_pair(unit_id, upod )); if (! uinsert.second) { - //If the UID is empty reinsert the unit in the same list element - if ( uinsert.first->second->unit == NULL) { - ilist_.pop_front(); - lit = uinsert.first->second; - lit->unit = p; - assert(lit->ref_count != 0); + //If the pod is empty reinsert the unit in the same list element + if ( uinsert.first->second.unit == NULL) { + unit_pod &opod = uinsert.first->second; + opod.unit = p; + assert(opod.ref_count != 0); } else { - unit *q = uinsert.first->second->unit; + unit *q = uinsert.first->second.unit; ERR_NG << "Trying to add " << p->name() << " - " << p->id() << " - " << p->underlying_id() << " (" << loc << ") over " << q->name() @@ -176,7 +164,7 @@ std::pair unit_map::insert(unit *p) { << " to prevent duplicate id conflicts.\n"; p->clone(false); - uinsert = umap_.insert(std::make_pair(p->underlying_id(), lit )); + uinsert = umap_.insert(std::make_pair(p->underlying_id(), upod )); int guard(0); while (!uinsert.second && (++guard < 1e6) ) { if(guard % 10 == 9){ @@ -188,33 +176,32 @@ std::pair unit_map::insert(unit *p) { "\nThank you for your help in fixing this bug.\n"; } p->clone(false); - uinsert = umap_.insert(std::make_pair(p->underlying_id(), lit )); } + uinsert = umap_.insert(std::make_pair(p->underlying_id(), upod )); } if (!uinsert.second) { - throw "One million collisions in unit_map"; } + throw game::error("One million collisions in unit_map"); } } } - std::pair linsert = lmap_.insert(std::make_pair(loc, lit )); + std::pair linsert = lmap_.insert(std::make_pair(loc, uinsert.first )); //Fail if the location is occupied if(! linsert.second) { - if(lit->ref_count == 0) { + if(upod.ref_count == 0) { //Undo a virgin insertion - ilist_.pop_front(); umap_.erase(uinsert.first); } else { //undo a reinsertion - uinsert.first->second->unit = NULL; + uinsert.first->second.unit = NULL; } DBG_NG << "Trying to add " << p->name() << " - " << p->id() << " at location ("<second)->unit->name()<< " - " << linsert.first->second->unit->id() <<"\n"; + <<(linsert.first->second->second).unit->name()<< " - " << linsert.first->second->second.unit->id() <<"\n"; - return std::make_pair(make_unit_iterator(the_end_), false); + return std::make_pair(make_unit_iterator(umap_.end()), false); } self_check(); - return std::make_pair( make_unit_iterator( lit ), true); + return std::make_pair( make_unit_iterator( uinsert.first ), true); } std::pair unit_map::replace(const map_location &l, const unit &u) { @@ -231,13 +218,16 @@ std::pair unit_map::replace(const map_location &l size_t unit_map::num_iters() const { ///Add up number of extant iterators size_t num_iters(0); - t_ilist::const_iterator ii(ilist_.begin()); - for( ; ii != the_end_ ; ++ii){ - if(ii->ref_count < 0) { + t_umap::const_iterator ui = umap_.begin(); + t_umap::const_iterator uend = umap_.end(); + for( ; ui != uend ; ++ui){ + if(ui->second.ref_count < 0) { //Somewhere, someone generated 2^31 iterators to this unit bool a_reference_counter_overflowed(false); - assert(a_reference_counter_overflowed); } - num_iters += ii->ref_count; } + assert(a_reference_counter_overflowed); + } + num_iters += ui->second.ref_count; + } return num_iters; } @@ -245,16 +235,15 @@ size_t unit_map::num_iters() const { void unit_map::clear(bool force) { assert(force || (num_iters() == 0)); - for (t_ilist::iterator i = ilist_.begin(); i != the_end_; ++i) { + for (t_umap::iterator i = umap_.begin(); i != umap_.end(); ++i) { if (is_valid(i)) { - DBG_NG << "Delete unit " << i->unit->underlying_id() << "\n"; - delete i->unit; + DBG_NG << "Delete unit " << i->second.unit->underlying_id() << "\n"; + delete i->second.unit; } } lmap_.clear(); umap_.clear(); - ilist_.clear(); } unit *unit_map::extract(const map_location &loc) { @@ -262,24 +251,20 @@ unit *unit_map::extract(const map_location &loc) { t_lmap::iterator i = lmap_.find(loc); if (i == lmap_.end()) { return NULL; } - t_ilist::iterator lit(i->second); + t_umap::iterator uit(i->second); - unit *u = lit->unit; + unit *u = uit->second.unit; size_t uid( u->underlying_id() ); DBG_NG << "Extract unit " << uid << " - " << u->id() << " from location: (" << loc << ")\n"; - if(lit->ref_count == 0){ - assert(lit != the_end_); - if(umap_.erase(uid) != 1){ - error_recovery_externally_changed_uid(lit); } - ilist_.erase( lit ); + assert(uit->first == uit->second.unit->underlying_id()); + if(uit->second.ref_count == 0){ + umap_.erase(uit); } else { //Soft extraction keeps the old lit item if any iterators reference it - lit->unit = NULL; - lit->deleted_uid = uid; - assert( uid != 0); + uit->second.unit = NULL; } lmap_.erase(i); @@ -288,41 +273,6 @@ unit *unit_map::extract(const map_location &loc) { return u; } -/** error_recovery_externally_changed_uid is called when an attempt is made to - delete a umap_ element, which fails because the underlying_id() has been changed externally. - It searches the entire umap_ to for a matching ilist_ element to erase. - */ -void unit_map::error_recovery_externally_changed_uid(t_ilist::iterator const & lit) const { - std::string name, id ; - size_t uid; - if(lit->unit != NULL){ - unit const * u(lit->unit); - name = u->name(); - id = u->id(); - uid = u->underlying_id(); - } else { - name = "unknown"; - id = "unknown"; - uid = lit->deleted_uid; - } - t_umap::iterator uit(umap_.begin()); - for(; uit != umap_.end(); ++uit){ - if(uit->second == lit){ break; } - } - std::stringstream oldidss; - if (uit != umap_.end()) { - size_t olduid = uit->first ; - umap_.erase(uit); - oldidss << olduid; - } else { - oldidss << "unknown"; - } - - ERR_NG << "Extracting " << name << " - " << id - << " from unit map. Underlying ID changed from "<< oldidss.str() << " to " << uid - << " between insertion and extraction, requiring an exhaustive search of umap_.\n"; -} - size_t unit_map::erase(const map_location &loc) { self_check(); @@ -335,12 +285,14 @@ size_t unit_map::erase(const map_location &loc) { unit_map::unit_iterator unit_map::find(size_t id) { self_check(); t_umap::iterator i(umap_.find(id)); - if((i != umap_.end()) && i->second->unit==NULL){ i = umap_.end() ;} - return make_unit_iterator( i ); } + if((i != umap_.end()) && i->second.unit==NULL){ i = umap_.end() ;} + return make_unit_iterator( i ); +} unit_map::unit_iterator unit_map::find(const map_location &loc) { self_check(); - return make_unit_iterator(lmap_.find(loc) ); } + return make_unit_iterator(lmap_.find(loc) ); +} unit_map::unit_iterator unit_map::find_leader(int side) { unit_map::iterator i = begin(), i_end = end(); @@ -384,53 +336,40 @@ std::vector unit_map::find_leaders(int side)const #ifdef DEBUG bool unit_map::self_check() const { - bool found_the_end(false), good(true); - t_ilist::const_iterator lit(ilist_.begin()); - for(; lit != ilist_.end(); ++lit){ - if(lit == the_end_){ found_the_end = true; continue; } - if(lit->ref_count < 0){ - good=false; - ERR_NG << "unit_map list element ref_count <0 is " << lit->ref_count<<"\n"; } - if(lit->unit != NULL){ - lit->unit->id(); //crash if bad pointer - } else { - if(lit->ref_count <= 0){ - good=false; - ERR_NG << "unit_map list element ref_count <=0 is " << lit->ref_count<<", when unit deleted.\n"; } - if(lit->deleted_uid <= 0 ){ - good=false; - ERR_NG << "unit_map list element deleted_uid <=0 is " << lit->deleted_uid<<"\n"; } - } - } - - if(!found_the_end){ - good=false; - ERR_NG << "unit_map list the_end_ is missing. " <<"\n";} + bool good(true); t_umap::const_iterator uit(umap_.begin()); for(; uit != umap_.end(); ++uit){ - if(uit->first <= 0){ + if(uit->second.ref_count < 0){ good=false; - ERR_NG << "unit_map umap uid <=0 is " << uit->first <<"\n"; } - if(uit->second == the_end_ ){ + ERR_NG << "unit_map pod ref_count <0 is " << uit->second.ref_count<<"\n"; + } + if(uit->second.unit != NULL){ + uit->second.unit->id(); //crash if bad pointer + } + if(uit->first <= 0){ good=false; - ERR_NG << "unit_map umap element == the_end_ "<<"\n"; } - if(uit->second->unit == NULL && uit->second->ref_count == 0 ){ + ERR_NG << "unit_map umap uid <=0 is " << uit->first <<"\n"; + } + if(uit->second.unit == NULL && uit->second.ref_count == 0 ){ good=false; - ERR_NG << "unit_map umap unit==NULL when refcount == 0 uid="<second->deleted_uid<<"\n"; + ERR_NG << "unit_map umap unit==NULL when refcount == 0\n"; } - if(uit->second->unit && uit->second->unit->underlying_id() != uit->first){ + if(uit->second.unit && uit->second.unit->underlying_id() != uit->first){ good=false; - ERR_NG << "unit_map umap uid("<first<<") != underlying_id()["<< uit->second->unit->underlying_id()<< "]\n"; } + ERR_NG << "unit_map umap uid("<first<<") != underlying_id()["<< uit->second.unit->underlying_id()<< "]\n"; + } } t_lmap::const_iterator locit(lmap_.begin()); for(; locit != lmap_.end(); ++locit){ - if(locit->second == the_end_ ){ + if(locit->second == umap_.end() ){ good=false; - ERR_NG << "unit_map lmap element == the_end_ "<<"\n"; } - if(locit->first != locit->second->unit->get_location()){ + ERR_NG << "unit_map lmap element == umap_.end() "<<"\n"; + } + if(locit->first != locit->second->second.unit->get_location()){ good=false; - ERR_NG << "unit_map lmap location != unit->get_location() " <<"\n"; } + ERR_NG << "unit_map lmap location != unit->get_location() " <<"\n"; + } } //assert(good); return good; @@ -442,8 +381,8 @@ bool unit_map::has_unit(const unit * const u) { assert(u); - BOOST_FOREACH(const unit_pod& item, ilist_) { - if(item.unit == u) { + BOOST_FOREACH(const t_umap::value_type& item, umap_) { + if(item.second.unit == u) { return true; } } diff --git a/src/unit_map.hpp b/src/unit_map.hpp index bb255cdf4ab0..299afbdf1105 100644 --- a/src/unit_map.hpp +++ b/src/unit_map.hpp @@ -23,6 +23,7 @@ #include #include +#include #include class unit; @@ -33,12 +34,12 @@ class unit; * stay valid even if WML modifies or moves units on the fly. They even stay * valid if a unit is erased from the map and another unit with the same * underlying id is inserted in the map. In other words it is a doubly indexed ordered map - with persistent iterators (that never invalidate) + * with persistent iterators (that never invalidate) - @note The unit_map is implemented as 2 unordered maps storing iterators from a list of reference counted pointers to units. - The unordered maps provide O(1) find times. The list allows arbitrary ordering of units (not yet implemented). + @note The unit_map is implemented as 2 maps, one unordered map that stores iterators from the ordered map of reference counted pointers to units. + The unordered map provides O(1) find times. The ordered map ensures ordering of units by underlying_id. The reference counting is what guarantees the persistent iterators. - Storing an iterator prevents only that dead unit's list location from being recovered. + Storing an iterator prevents only that dead unit's id-map entry from being recovered. @note Prefered usages for tight loops follows. Use the std::pair format which checks the preconditions and returns @@ -82,8 +83,8 @@ if(try_add.second){i = try_add.first;} * iterated upon may be skipped or visited twice. * @note Iterators prevent ghost units from being collected. So they should * never be stored into data structures, as it will cause slowdowns! - @note By popular demand iterators are effectively permanent. They are handles and not iterators. - Any access might cause a full lookup. Keeping iterators around holds onto memory. + * @note By popular demand iterators are effectively permanent. They are handles and not iterators. + * Any access might cause a full lookup. Keeping iterators around holds onto memory. */ class unit_map { /// The pointer to the unit and a reference counter to record the number of extant iterators @@ -93,25 +94,19 @@ class unit_map { unit_pod() : unit(NULL) , ref_count() - , deleted_uid(0) { } class unit * unit; mutable n_ref_counter::t_ref_counter ref_count; - - unsigned deleted_uid; ///UID of the deleted, moved, added, or otherwise invalidated iterator to facilitate a new lookup. }; - /// A list pointing to unit and their reference counters. Dead units have a unit pointer equal to NULL. - /// The list element is remove iff the reference counter equals zero and there are no more + ///Map of underlying_id to unit and a reference counter. Dead units have a unit pointer equal to NULL. + ///The map entry is removed iff the reference counter equals zero and there are no more ///iterators pointing to this unit. - typedef std::list t_ilist; - - ///Maps of id and location to list iterator. - ///@note list iterators never invalidate due to resizing or deletion. - typedef boost::unordered_map t_umap; - typedef boost::unordered_map t_lmap; + typedef std::map t_umap; + ///Map of location to umap iterator. + typedef boost::unordered_map t_lmap; public: @@ -119,13 +114,13 @@ class unit_map { struct standard_iter_types { typedef unit_map container_type; - typedef unit_map::t_ilist::iterator iterator_type; + typedef unit_map::t_umap::iterator iterator_type; typedef unit value_type; }; struct const_iter_types { typedef unit_map const container_type; - typedef unit_map::t_ilist::iterator iterator_type; + typedef unit_map::t_umap::iterator iterator_type; typedef const unit value_type; }; @@ -170,12 +165,6 @@ class unit_map { } private: - ///Construct an iterator from the uid map - iterator_base(t_umap::iterator ui, container_type *m) : i_(ui->second), tank_(m) { - inc(); - valid_exit(); - } - ///Construct an iterator from the location map iterator_base(t_lmap::iterator ui, container_type *m) : i_(ui->second), tank_(m) { inc(); @@ -186,19 +175,11 @@ class unit_map { pointer operator->() const { assert(valid()); tank_->self_check(); - return i_->unit; } + return i_->second.unit; } reference operator*() const { tank_->self_check(); -#if 0 - // debug! - if(!valid()){ - if(!tank_){std::cerr<<"tank is NULL"<<"\n";} - if(i_==the_end()){std::cerr<<"i_ is the end"<<"\n";} - if(i_->unit==NULL){std::cerr<<"i_ unit is NULL with uid="<deleted_uid<<"\n";} - } -#endif assert(valid()); - return *i_->unit; } + return *i_->second.unit; } iterator_base& operator++() { assert( valid_entry() ); @@ -206,7 +187,7 @@ class unit_map { iterator_type new_i(i_); do{ ++new_i; - }while ((new_i->unit == NULL) && (new_i != the_end() )) ; + }while ((new_i->second.unit == NULL) && (new_i != the_map().end() )) ; dec(); i_ = new_i; inc(); @@ -221,13 +202,13 @@ class unit_map { } iterator_base& operator--() { - assert( tank_ && i_ != the_list().begin() ); + assert( tank_ && i_ != the_map().begin() ); tank_->self_check(); - iterator_type begin(the_list().begin()); + iterator_type begin(the_map().begin()); dec(); do { --i_ ; - }while(i_ != begin && (i_->unit == NULL)); + }while(i_ != begin && (i_->second.unit == NULL)); inc(); valid_exit(); @@ -242,64 +223,44 @@ class unit_map { bool valid() const { if(valid_for_dereference()) { - if(i_->unit == NULL){ - recover_unit_iterator(); } - return i_->unit != NULL; + return i_->second.unit != NULL; } - return false; } + return false; + } bool operator==(const iterator_base &rhs) const { return (tank_ == rhs.tank_) && ( i_ == rhs.i_ ); } bool operator!=(const iterator_base &rhs) const { return !operator==(rhs); } - // container_type* get_map() const { return tank_; } - template friend struct iterator_base; private: - bool valid_for_dereference() const { return (tank_ != NULL) && (i_ != the_end()); } - bool valid_entry() const { return ((tank_ != NULL) && (i_ != the_end())) ; } + bool valid_for_dereference() const { return (tank_ != NULL) && (i_ != the_map().end()); } + bool valid_entry() const { return ((tank_ != NULL) && (i_ != the_map().end())) ; } void valid_exit() const { - if(tank_ != NULL) { - assert(!the_list().empty()); - assert(i_ != the_list().end()); - if(i_ != the_end()){ - assert(i_->ref_count > 0); - } else { - assert(i_->ref_count == 1); - } - }} - bool valid_ref_count() const { return (tank_ != NULL) && (i_ != the_end()) ; } + if((tank_ != NULL) && i_ != the_map().end()){ + assert(i_->second.ref_count > 0); + } + } + bool valid_ref_count() const { return (tank_ != NULL) && (i_ != the_map().end()) ; } ///Increment the reference counter - void inc() { if(valid_ref_count()) { ++(i_->ref_count); } } + void inc() { if(valid_ref_count()) { ++(i_->second.ref_count); } } ///Decrement the reference counter - ///Delete the list element and the dangling umap reference if the unit is gone and the reference counter is zero - ///@note this deletion will advance i_ to the next list element. + ///Delete the umap entry if the unit is gone and the reference counter is zero + ///@note this deletion will advance i_ to the next umap entry. void dec() { if( valid_ref_count() ){ - assert(i_->ref_count != 0); - if( (--(i_->ref_count) == 0) && (i_->unit == NULL) ){ - if(tank_->umap_.erase(i_->deleted_uid) != 1){ - tank_->error_recovery_externally_changed_uid(i_); } - i_ = the_list().erase(i_); - } } } - - unit_map::t_ilist & the_list() const { return tank_->ilist_; } - - ///Returns the sentinel at the end of the list. - ///This provides a stable unit_iterator for hoisting out of loops - iterator_type the_end() const { return tank_->the_end_; } - - /** - * Attempt to find a deleted unit in the unit_map, by looking up the stored UID. - * @pre deleted_uid != 0 - */ - void recover_unit_iterator() const { - assert(i_->deleted_uid != 0); - iterator_base new_this( tank_->find( i_->deleted_uid )); - const_cast(this)->operator=( new_this ); + assert(i_->second.ref_count != 0); + if( (--(i_->second.ref_count) == 0) && (i_->second.unit == NULL) ){ + iterator_type old = i_++; + tank_->umap_.erase(old); + } + } } + + unit_map::t_umap & the_map() const { return tank_->umap_; } + friend class unit_map; iterator_type i_; ///local iterator @@ -342,8 +303,8 @@ class unit_map { unit_iterator begin() { return make_unit_iterator( begin_core() ); } const_unit_iterator begin() const { return make_const_unit_iterator( begin_core() ); } - unit_iterator end() { return make_unit_iterator(the_end_); } - const_unit_iterator end() const { return make_const_unit_iterator(the_end_); } + unit_iterator end() { return make_unit_iterator(umap_.end()); } + const_unit_iterator end() const { return make_const_unit_iterator(umap_.end()); } size_t size() const { return lmap_.size(); } size_t num_iters() const ; @@ -429,62 +390,40 @@ class unit_map { bool has_unit(const unit * const u); private: - ///Creates and inserts a unit_pod called the_end_ as a sentinel in the ilist - void init_end(){ - assert(ilist_.empty()); - unit_pod upod; - upod.unit = NULL; - upod.deleted_uid = 0; - ++upod.ref_count; //dummy count - ilist_.push_front(upod); - the_end_ = ilist_.begin(); - }; + t_umap::iterator begin_core() const ; - t_ilist::iterator begin_core() const ; - - bool is_valid(const t_ilist::const_iterator &i) const { - return i != the_end_ && is_found(i) && (i->unit != NULL); } bool is_valid(const t_umap::const_iterator &i) const { - return is_found(i) && (i->second->unit != NULL); } + return is_found(i) && (i->second.unit != NULL); + } bool is_valid(const t_lmap::const_iterator &i) const { - return is_found(i) && (i->second->unit != NULL); } + return is_found(i) && (i->second->second.unit != NULL); + } - bool is_found(const t_ilist::const_iterator &i) const { return i != ilist_.end(); } - bool is_found(const t_umap::const_iterator &i) const { return i != umap_.end() ; } + bool is_found(const t_umap::const_iterator &i) const { return i != umap_.end(); } bool is_found(const t_lmap::const_iterator &i) const { return i != lmap_.end(); } template unit_map::unit_iterator make_unit_iterator(X const & i) { - if (!is_found( i )) { return unit_iterator(the_end_, this); } - return unit_iterator(i , this); } + if (!is_found( i )) { return unit_iterator(umap_.end(), this); } + return unit_iterator(i , this); + } template unit_map::const_unit_iterator make_const_unit_iterator(X const & i) const { - if (!is_found( i )) { return const_unit_iterator(the_end_, this); } - return const_unit_iterator(i , this); } - - ///Finds and deletes the umap_ item associated with @a lit when the underlying_id() - ///has been changed externally after insertion and before extraction - void error_recovery_externally_changed_uid(t_ilist::iterator const & lit) const; + if (!is_found( i )) { return const_unit_iterator(umap_.end(), this); } + return const_unit_iterator(i , this); + } /** - * underlying_id -> ilist::iterator. This requires that underlying_id be + * underlying_id -> unit_pod. This requires that underlying_id be * unique (which is enforced in unit_map::insert). */ mutable t_umap umap_; /** - * location -> ilist::iterator. + * location -> umap::iterator. */ t_lmap lmap_; - /** - * List of unit pointers and reference counts for the iterators - */ - mutable t_ilist ilist_; - - /// The last list item, a sentinel that allows BOOST::foreach to hoist end() - t_ilist::iterator the_end_; - }; template