Changed unit_map to not store invalidated iterators.
Added incremental recovery of invalidated but reference counted unit_map::iterators.
This commit is contained in:
parent
53d83051de
commit
f92dd22281
8 changed files with 268 additions and 171 deletions
|
@ -2263,7 +2263,7 @@ WML_HANDLER_FUNCTION(heal_unit, event_info, cfg)
|
|||
const bool animate = cfg["animate"].to_bool(false);
|
||||
|
||||
const vconfig healed_filter = cfg.child("filter");
|
||||
unit_map::const_unit_iterator u;
|
||||
unit_map::unit_iterator u;
|
||||
bool only_unit_at_loc1 = healed_filter.null();
|
||||
bool heal_amount_to_set = true;
|
||||
for(u = units->begin(); u != units->end(); ++u) {
|
||||
|
|
|
@ -1689,7 +1689,7 @@ void menu_handler::continue_move(mouse_handler &mousehandler, int side_num)
|
|||
side_num, mousehandler);
|
||||
}
|
||||
|
||||
void menu_handler::move_unit_to_loc(const unit_map::const_iterator &ui,
|
||||
void menu_handler::move_unit_to_loc(const unit_map::iterator &ui,
|
||||
const map_location& target, bool continue_move, int side_num,
|
||||
mouse_handler &mousehandler)
|
||||
{
|
||||
|
|
|
@ -91,7 +91,7 @@ public:
|
|||
unit_map::iterator current_unit();
|
||||
unit_map::const_iterator current_unit() const
|
||||
{ return const_cast<menu_handler *>(this)->current_unit(); }
|
||||
void move_unit_to_loc(const unit_map::const_iterator& ui, const map_location& target,
|
||||
void move_unit_to_loc(const unit_map::iterator& ui, const map_location& target,
|
||||
bool continue_move, int side_num, mouse_handler &mousehandler);
|
||||
///@return Whether or not the recruit was successful
|
||||
bool do_recruit(const std::string& name, int side_num, const map_location& last_hex);
|
||||
|
|
159
src/unit_map.cpp
159
src/unit_map.cpp
|
@ -29,12 +29,15 @@ static lg::log_domain log_engine("engine");
|
|||
#define LOG_NG LOG_STREAM(info, log_engine)
|
||||
#define DBG_NG LOG_STREAM(debug, log_engine)
|
||||
|
||||
|
||||
unit_map::unit_map(const unit_map& that) :
|
||||
map_(),
|
||||
umap_(),
|
||||
lmap_(),
|
||||
ilist_(),
|
||||
num_iters_(0),
|
||||
num_invalid_(0)
|
||||
{
|
||||
init_end();
|
||||
for (const_unit_iterator i = that.begin(); i != that.end(); i++) {
|
||||
add(i->get_location(), *i);
|
||||
}
|
||||
|
@ -47,38 +50,24 @@ unit_map &unit_map::operator=(const unit_map &that)
|
|||
return *this;
|
||||
}
|
||||
|
||||
void unit_map::swap(unit_map &o)
|
||||
{
|
||||
assert(num_iters_ == 0 && o.num_iters_ == 0);
|
||||
std::swap(map_, o.map_);
|
||||
void unit_map::swap(unit_map &o) {
|
||||
assert(num_iters()==0 && o.num_iters() == 0);
|
||||
|
||||
std::swap(umap_, o.umap_);
|
||||
std::swap(lmap_, o.lmap_);
|
||||
std::swap(ilist_, o.ilist_);
|
||||
std::swap(the_end_, o.the_end_);
|
||||
std::swap(num_invalid_, o.num_invalid_);
|
||||
}
|
||||
|
||||
unit_map::~unit_map() {
|
||||
clear();
|
||||
clear(true);
|
||||
}
|
||||
|
||||
unit_map::unit_iterator unit_map::begin() {
|
||||
// This call just needs to go somewhere that is likely to be
|
||||
// called when num_iters_ == 0. This seems as good a place as any.
|
||||
clean_invalid();
|
||||
|
||||
umap::iterator i = map_.begin();
|
||||
while (i != map_.end() && !is_valid(i)) {
|
||||
++i;
|
||||
}
|
||||
|
||||
return unit_iterator(i, this);
|
||||
}
|
||||
|
||||
unit_map::const_unit_iterator unit_map::begin() const {
|
||||
umap::const_iterator i = map_.begin();
|
||||
while (i != map_.end() && !is_valid(i)) {
|
||||
++i;
|
||||
}
|
||||
|
||||
return const_unit_iterator(i, this);
|
||||
unit_map::t_ilist::iterator unit_map::begin_core() const {
|
||||
t_ilist::iterator i = ilist_.begin();
|
||||
while (i != the_end_ && (i->unit_ == NULL)) { ++i; }
|
||||
return i;
|
||||
}
|
||||
|
||||
void unit_map::add(const map_location &l, const unit &u) {
|
||||
|
@ -88,11 +77,23 @@ void unit_map::add(const map_location &l, const unit &u) {
|
|||
}
|
||||
|
||||
void unit_map::move(const map_location &src, const map_location &dst) {
|
||||
DBG_NG << "Unit map: Moving unit from " << src << " to " << dst << "\n";
|
||||
unit *p = extract(src);
|
||||
assert(p);
|
||||
p->set_location(dst);
|
||||
insert(p);
|
||||
DBG_NG << "Unit map: Moving unit from " << src << " to " << dst << "\n";
|
||||
|
||||
if(src != dst){
|
||||
t_lmap::iterator i = lmap_.find(src);
|
||||
assert(i != lmap_.end()) ;
|
||||
|
||||
unit *p = i->second->unit_;
|
||||
assert(p);
|
||||
|
||||
p->set_location(dst);
|
||||
|
||||
std::pair<t_lmap::iterator,bool> res = lmap_.insert(std::make_pair(dst, i->second));
|
||||
assert(res.second);
|
||||
|
||||
///@todo upgrade to quick_erase when boost 1.42 supported by wesnoth
|
||||
lmap_.erase(i);
|
||||
}
|
||||
}
|
||||
|
||||
void unit_map::insert(unit *p)
|
||||
|
@ -107,15 +108,21 @@ void unit_map::insert(unit *p)
|
|||
return;
|
||||
}
|
||||
|
||||
std::pair<umap::iterator, bool> biter =
|
||||
map_.insert(std::make_pair(unit_id, p));
|
||||
unit_pod upod;
|
||||
upod.unit_ = p;
|
||||
ilist_.push_front(upod);
|
||||
|
||||
t_ilist::iterator lit(ilist_.begin());
|
||||
|
||||
std::pair<t_umap::iterator, bool> biter =
|
||||
umap_.insert(std::make_pair(unit_id, lit ));
|
||||
|
||||
if (biter.second) {
|
||||
} else if (!biter.first->second) {
|
||||
biter.first->second = p;
|
||||
} else if (! biter.first->second->unit_) {
|
||||
biter.first->second->unit_ = p;
|
||||
--num_invalid_;
|
||||
} else {
|
||||
unit *q = biter.first->second;
|
||||
unit *q = biter.first->second->unit_;
|
||||
ERR_NG << "Trying to add " << p->name()
|
||||
<< " - " << p->id() << " - " << p->underlying_id()
|
||||
<< " (" << loc << ") over " << q->name()
|
||||
|
@ -132,7 +139,7 @@ void unit_map::insert(unit *p)
|
|||
DBG_NG << "Adding unit " << p->underlying_id() << " - " << p->id()
|
||||
<< " to location: (" << loc << ")\n";
|
||||
|
||||
std::pair<lmap::iterator,bool> res = lmap_.insert(std::make_pair(loc, p));
|
||||
std::pair<t_lmap::iterator,bool> res = lmap_.insert(std::make_pair(loc, lit ));
|
||||
assert(res.second);
|
||||
|
||||
}
|
||||
|
@ -148,35 +155,49 @@ void unit_map::replace(const map_location &l, const unit &u)
|
|||
add(loc, u);
|
||||
}
|
||||
|
||||
void unit_map::clear()
|
||||
{
|
||||
assert(num_iters_ == 0);
|
||||
size_t unit_map::num_iters() const {
|
||||
//Check for outstanding iterators
|
||||
size_t num_iters(0);
|
||||
t_ilist::const_iterator ii(ilist_.begin());
|
||||
for( ; ii != the_end_ ; ++ii){
|
||||
if(ii->ref_count_ < 0){
|
||||
bool a_reference_counter_overflowed(false);
|
||||
assert(a_reference_counter_overflowed); }
|
||||
num_iters += ii->ref_count_; }
|
||||
|
||||
for (umap::iterator i = map_.begin(); i != map_.end(); ++i) {
|
||||
return num_iters;
|
||||
}
|
||||
|
||||
void unit_map::clear(bool force) {
|
||||
assert(force || (num_iters() == 0));
|
||||
|
||||
for (t_ilist::iterator i = ilist_.begin(); i != the_end_; ++i) {
|
||||
if (is_valid(i)) {
|
||||
DBG_NG << "Delete unit " << i->second->underlying_id() << "\n";
|
||||
delete i->second;
|
||||
DBG_NG << "Delete unit " << i->unit_->underlying_id() << "\n";
|
||||
delete i->unit_;
|
||||
}
|
||||
}
|
||||
|
||||
lmap_.clear();
|
||||
map_.clear();
|
||||
umap_.clear();
|
||||
ilist_.clear();
|
||||
}
|
||||
|
||||
unit *unit_map::extract(const map_location &loc)
|
||||
{
|
||||
lmap::iterator i = lmap_.find(loc);
|
||||
unit *unit_map::extract(const map_location &loc) {
|
||||
t_lmap::iterator i = lmap_.find(loc);
|
||||
if (i == lmap_.end()) {
|
||||
return NULL; }
|
||||
|
||||
unit *res = i->second;
|
||||
unit *res = i->second->unit_;
|
||||
|
||||
DBG_NG << "Extract unit " << res->underlying_id() << " - " << res->id()
|
||||
<< " from location: (" << loc << ")\n";
|
||||
i->second = NULL;
|
||||
++num_invalid_;
|
||||
map_.erase(res->underlying_id());
|
||||
///todo replace with quick_erase(i) when boost min version supports it
|
||||
|
||||
i->second->unit_ = NULL;
|
||||
if(i->second->ref_count_ == 0){ ilist_.erase( i->second ); }
|
||||
|
||||
///@todo replace with quick_erase(i) when wesnoth supports boost 1.42 min version
|
||||
umap_.erase(res->underlying_id());
|
||||
lmap_.erase(i);
|
||||
|
||||
return res;
|
||||
|
@ -190,39 +211,17 @@ size_t unit_map::erase(const map_location &loc)
|
|||
return 1;
|
||||
}
|
||||
|
||||
void unit_map::clean_invalid() {
|
||||
if (num_iters_ > 0 || num_invalid_ < lmap_.size())
|
||||
return;
|
||||
|
||||
size_t num_cleaned = 0;
|
||||
|
||||
umap::iterator iter = map_.begin();
|
||||
while (iter != map_.end()) {
|
||||
if (!is_valid(iter)) {
|
||||
iter = map_.erase(iter);
|
||||
++num_cleaned;
|
||||
} else {
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
num_invalid_ -= num_cleaned;
|
||||
|
||||
LOG_NG << "unit_map::clean_invalid - removed " << num_cleaned << " invalid map entries.\n";
|
||||
}
|
||||
|
||||
unit_map::unit_iterator unit_map::find(size_t id) {
|
||||
umap::iterator iter = map_.find(id);
|
||||
if (!is_valid(iter)) iter = map_.end();
|
||||
return unit_iterator(iter, this);
|
||||
t_umap::iterator iter = umap_.find(id);
|
||||
if (!is_valid(iter)) { iter = umap_.end(); }
|
||||
return unit_iterator(iter, & ilist_);
|
||||
}
|
||||
|
||||
unit_map::unit_iterator unit_map::find(const map_location &loc) {
|
||||
lmap::const_iterator i = lmap_.find(loc);
|
||||
t_lmap::iterator i = lmap_.find(loc);
|
||||
if (i == lmap_.end()) {
|
||||
return unit_iterator(map_.end(), this);
|
||||
}
|
||||
return(find(i->second->underlying_id()));
|
||||
return unit_iterator(the_end_, & ilist_); }
|
||||
return unit_iterator(i, & ilist_);
|
||||
}
|
||||
|
||||
unit_map::unit_iterator unit_map::find_leader(int side)
|
||||
|
|
195
src/unit_map.hpp
195
src/unit_map.hpp
|
@ -19,10 +19,11 @@
|
|||
#ifndef UNIT_MAP_H_INCLUDED
|
||||
#define UNIT_MAP_H_INCLUDED
|
||||
|
||||
#include "utils/reference_counter.hpp"
|
||||
#include "map_location.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
class unit;
|
||||
|
@ -43,133 +44,143 @@ class unit;
|
|||
* never be stored into data structures, as it will cause slowdowns!
|
||||
*/
|
||||
class unit_map {
|
||||
public:
|
||||
typedef boost::unordered_map<size_t, unit *> umap;
|
||||
typedef boost::unordered_map<map_location, unit *> lmap;
|
||||
struct unit_pod {
|
||||
unit * unit_;
|
||||
mutable n_ref_counter::t_ref_counter<signed int> ref_count_;
|
||||
};
|
||||
typedef std::list<unit_pod> t_ilist;
|
||||
typedef boost::unordered_map<size_t, typename t_ilist::iterator> t_umap;
|
||||
typedef boost::unordered_map<map_location, typename t_ilist::iterator> t_lmap;
|
||||
|
||||
|
||||
unit_map() : map_(), lmap_(), num_iters_(0), num_invalid_(0) { };
|
||||
public:
|
||||
unit_map() : umap_(), lmap_(), ilist_(), num_iters_(0), num_invalid_(0) { init_end();};
|
||||
unit_map(const unit_map &that);
|
||||
unit_map& operator=(const unit_map &that);
|
||||
|
||||
/** A unit map with a copy of a single unit in it. */
|
||||
unit_map(const map_location &loc, const unit &u);
|
||||
~unit_map();
|
||||
|
||||
void swap(unit_map& o);
|
||||
|
||||
// ~~~ Begin iterator code ~~~
|
||||
|
||||
template<typename iter_types>
|
||||
struct iterator_base
|
||||
{
|
||||
typedef unit value_type;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef int difference_type;
|
||||
typedef unit *pointer;
|
||||
typedef unit &reference;
|
||||
typedef typename iter_types::map_type map_type;
|
||||
typedef typename iter_types::value_type value_type;
|
||||
typedef typename iter_types::pointer_type pointer;
|
||||
typedef typename iter_types::reference_type reference;
|
||||
typedef typename iter_types::container_type container_type;
|
||||
typedef typename iter_types::iterator_type iterator_type;
|
||||
|
||||
iterator_base(): map_(NULL), i_() { }
|
||||
iterator_base(): tank_(NULL), i_() { }
|
||||
|
||||
iterator_base(iterator_type i, map_type *m)
|
||||
: map_(m), i_(i)
|
||||
{ map_->add_iter(); }
|
||||
iterator_base(iterator_type i, container_type *m)
|
||||
: tank_(m), i_(i) {
|
||||
inc(); }
|
||||
|
||||
~iterator_base()
|
||||
{ if (map_) map_->remove_iter(); }
|
||||
~iterator_base() { dec(); }
|
||||
|
||||
template<typename that_types>
|
||||
iterator_base(const iterator_base<that_types> &that)
|
||||
: map_(that.map_), i_(that.i_)
|
||||
{ if (map_) map_->add_iter(); }
|
||||
: tank_(that.tank_), i_(that.i_)
|
||||
{ inc(); }
|
||||
|
||||
template<typename that_types>
|
||||
iterator_base &operator=(const iterator_base<that_types> &that)
|
||||
{
|
||||
if (map_) map_->remove_iter();
|
||||
map_ = that.map_;
|
||||
iterator_base &operator=(const iterator_base<that_types> &that) {
|
||||
dec();
|
||||
tank_ = that.tank_;
|
||||
i_ = that.i_;
|
||||
if (map_) map_->add_iter();
|
||||
inc();
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator_base(const iterator_base &that)
|
||||
: map_(that.map_), i_(that.i_)
|
||||
{ if (map_) map_->add_iter(); }
|
||||
private:
|
||||
iterator_base(t_umap::iterator ui, container_type *m)
|
||||
: tank_(m), i_(ui->second) {
|
||||
inc(); }
|
||||
|
||||
iterator_base &operator=(const iterator_base &that)
|
||||
{
|
||||
if (map_) map_->remove_iter();
|
||||
map_ = that.map_;
|
||||
i_ = that.i_;
|
||||
if (map_) map_->add_iter();
|
||||
iterator_base(t_lmap::iterator ui, container_type *m)
|
||||
: tank_(m), i_(ui->second) {
|
||||
inc(); }
|
||||
|
||||
void inc() { if(valid()){ ++(i_->ref_count_); } }
|
||||
void dec() {
|
||||
if( valid() && (--(i_->ref_count_) == 0) && (i_->unit_ == NULL) ){
|
||||
i_ = tank_->erase(i_); } }
|
||||
iterator_type the_end() const {return --tank_->end();}
|
||||
|
||||
public:
|
||||
pointer operator->() const { assert(valid()); return i_->unit_; }
|
||||
reference operator*() const { assert(valid()); return *i_->unit_; }
|
||||
|
||||
iterator_base& operator++() {
|
||||
assert( valid() );
|
||||
iterator_type new_i(i_);
|
||||
++new_i;
|
||||
while (new_i != the_end() && (new_i->unit_ == NULL)) {
|
||||
++new_i;
|
||||
}
|
||||
dec();
|
||||
i_ = new_i;
|
||||
inc();
|
||||
return *this;
|
||||
}
|
||||
|
||||
pointer operator->() const
|
||||
{ assert(valid()); return i_->second; }
|
||||
reference operator*() const
|
||||
{ assert(valid()); return *i_->second; }
|
||||
|
||||
iterator_base& operator++()
|
||||
{
|
||||
assert(map_ && i_ != map_->map_.end());
|
||||
do ++i_;
|
||||
while (i_ != map_->map_.end() && !i_->second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator_base operator++(int)
|
||||
{
|
||||
iterator_base operator++(int) {
|
||||
iterator_base temp(*this);
|
||||
operator++();
|
||||
return temp;
|
||||
}
|
||||
|
||||
iterator_base& operator--()
|
||||
{
|
||||
assert(map_ && i_ != map_->map_.begin());
|
||||
iterator_type next(map_->map_.begin()), oldi(i_);
|
||||
do { i_ = ++next;
|
||||
}while(next != oldi );
|
||||
iterator_base& operator--() {
|
||||
assert( tank_ && i_ != tank_->begin() );
|
||||
iterator_type begin(tank_->begin());
|
||||
dec();
|
||||
do {
|
||||
--i_ ;
|
||||
}while(i_ != begin && (i_->unit_ == NULL));
|
||||
inc();
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator_base operator--(int)
|
||||
{
|
||||
iterator_base operator--(int) {
|
||||
iterator_base temp(*this);
|
||||
operator--();
|
||||
return temp;
|
||||
}
|
||||
|
||||
bool valid() const
|
||||
{ return map_ && map_->is_valid(i_); }
|
||||
bool valid() const { return tank_ && i_ != the_end(); }
|
||||
|
||||
bool operator==(const iterator_base &rhs) const
|
||||
{ assert(map_ == rhs.map_); return i_ == rhs.i_; }
|
||||
{ assert(tank_ == rhs.tank_); return i_ == rhs.i_; }
|
||||
bool operator!=(const iterator_base &rhs) const
|
||||
{ return !operator==(rhs); }
|
||||
|
||||
map_type* get_map() const { return map_; }
|
||||
// container_type* get_map() const { return tank_; }
|
||||
|
||||
template<typename Y> friend struct iterator_base;
|
||||
|
||||
private:
|
||||
map_type* map_;
|
||||
friend class unit_map;
|
||||
container_type* tank_;
|
||||
iterator_type i_;
|
||||
};
|
||||
|
||||
struct standard_iter_types {
|
||||
typedef unit_map map_type;
|
||||
typedef unit_map::umap::iterator iterator_type;
|
||||
typedef unit_map::t_ilist container_type;
|
||||
typedef unit_map::t_ilist::iterator iterator_type;
|
||||
typedef unit value_type;
|
||||
typedef value_type* pointer_type;
|
||||
typedef value_type& reference_type;
|
||||
};
|
||||
|
||||
struct const_iter_types {
|
||||
typedef const unit_map map_type;
|
||||
typedef unit_map::umap::const_iterator iterator_type;
|
||||
typedef unit_map::t_ilist container_type;
|
||||
typedef unit_map::t_ilist::iterator iterator_type;
|
||||
typedef const unit value_type;
|
||||
typedef value_type* pointer_type;
|
||||
typedef value_type& reference_type;
|
||||
|
@ -188,14 +199,11 @@ public:
|
|||
|
||||
unit_iterator find(const map_location &loc);
|
||||
|
||||
const_unit_iterator find(const map_location &loc) const
|
||||
{ return const_cast<unit_map *>(this)->find(loc); }
|
||||
const_unit_iterator find(size_t id) const
|
||||
{ return const_cast<unit_map *>(this)->find(id); }
|
||||
const_unit_iterator find(const map_location &loc) const { return const_cast<unit_map *>(this)->find(loc); }
|
||||
const_unit_iterator find(size_t id) const { return const_cast<unit_map *>(this)->find(id); }
|
||||
|
||||
unit_iterator find_leader(int side);
|
||||
const_unit_iterator find_leader(int side) const
|
||||
{ return const_cast<unit_map *>(this)->find_leader(side); }
|
||||
const_unit_iterator find_leader(int side) const { return const_cast<unit_map *>(this)->find_leader(side); }
|
||||
unit_iterator find_first_leader(int side);
|
||||
|
||||
std::vector<unit_iterator> find_leaders(int side);
|
||||
|
@ -203,15 +211,16 @@ public:
|
|||
|
||||
size_t count(const map_location& loc) const { return static_cast<size_t>(lmap_.count(loc)); }
|
||||
|
||||
unit_iterator begin();
|
||||
const_unit_iterator begin() const;
|
||||
unit_iterator begin() { return unit_iterator( begin_core(), & ilist_); }
|
||||
const_unit_iterator begin() const { return const_unit_iterator( begin_core(), & ilist_); }
|
||||
|
||||
unit_iterator end() { return iterator(map_.end(), this); }
|
||||
const_unit_iterator end() const { return const_iterator(map_.end(), this); }
|
||||
unit_iterator end() { return iterator(the_end_, & ilist_); }
|
||||
const_unit_iterator end() const { return const_iterator(the_end_, & ilist_); }
|
||||
|
||||
size_t size() const { return lmap_.size(); }
|
||||
size_t num_iters() const ;
|
||||
|
||||
void clear();
|
||||
void clear(bool force = false);
|
||||
|
||||
/**
|
||||
* Adds a copy of unit @a u at location @a l of the map.
|
||||
|
@ -258,28 +267,42 @@ public:
|
|||
*/
|
||||
unit *extract(const map_location &loc);
|
||||
|
||||
void swap(unit_map& o);
|
||||
|
||||
private:
|
||||
void init_end(){
|
||||
assert(ilist_.empty());
|
||||
ilist_.push_front(unit_pod());
|
||||
the_end_ = ilist_.begin();
|
||||
};
|
||||
|
||||
t_ilist::iterator begin_core() const ;
|
||||
|
||||
/** Removes invalid entries in map_ if safe and needed. */
|
||||
void clean_invalid();
|
||||
// void clean_invalid();
|
||||
|
||||
void add_iter() const { ++num_iters_; }
|
||||
void remove_iter() const { --num_iters_; }
|
||||
// void add_iter() const { ++num_iters_; }
|
||||
// void remove_iter() const { --num_iters_; }
|
||||
|
||||
bool is_valid(const umap::const_iterator &i) const
|
||||
{ return i != map_.end() && i->second; }
|
||||
bool is_valid(const t_ilist::const_iterator &i) const
|
||||
{ return i != the_end_ && (i->unit_ != NULL); }
|
||||
bool is_valid(const t_umap::const_iterator &i) const
|
||||
{ return i != umap_.end() && (i->second->unit_ != NULL); }
|
||||
|
||||
/**
|
||||
* underlying_id -> unit. This requires that underlying_id be
|
||||
* underlying_id -> ilist::iterator. This requires that underlying_id be
|
||||
* unique (which is enforced in unit_map::insert).
|
||||
*/
|
||||
umap map_;
|
||||
t_umap umap_;
|
||||
|
||||
/**
|
||||
* location -> underlying_id.
|
||||
* location -> ilist::iterator.
|
||||
*/
|
||||
lmap lmap_;
|
||||
t_lmap lmap_;
|
||||
|
||||
/**
|
||||
* List of unit pointers and ref counts for the iterators
|
||||
*/
|
||||
mutable t_ilist ilist_;
|
||||
t_ilist::iterator the_end_; /// Last list item
|
||||
|
||||
mutable size_t num_iters_;
|
||||
size_t num_invalid_;
|
||||
|
|
75
src/utils/reference_counter.hpp
Normal file
75
src/utils/reference_counter.hpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
/* $Id: tstring.hpp 48153 2011-01-01 15:57:50Z mordante $ */
|
||||
/*
|
||||
Copyright (C) 2004 - 2011 by Philippe Plantier <ayin@anathas.org>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#ifndef UTILS_REFERENCE_COUTER_H_INCLUDED
|
||||
#define UTILS_REFERENCE_COUTER_H_INCLUDED
|
||||
|
||||
/**
|
||||
* @file
|
||||
*/
|
||||
|
||||
|
||||
#include <limits>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
//debug
|
||||
#include <iostream> //std::cerr
|
||||
|
||||
namespace n_ref_counter {
|
||||
|
||||
|
||||
/**
|
||||
@class t_ref_counter
|
||||
@brief t_ref_counter is a reference counter. If the counter overflows it stops counting.
|
||||
So any negative count disables reference counting.
|
||||
**/
|
||||
template <typename T_integral> class t_ref_counter {
|
||||
BOOST_STATIC_ASSERT( std::numeric_limits<T_integral>::is_signed);
|
||||
|
||||
T_integral count_;
|
||||
|
||||
public:
|
||||
enum {NEW=0, NOT_COUNTED = -1};
|
||||
|
||||
explicit t_ref_counter(T_integral x = 0){count_=x;}
|
||||
t_ref_counter(t_ref_counter const &a){count_ = a.count_;}
|
||||
t_ref_counter & operator=(t_ref_counter const a){count_ = a.count_; return *this;}
|
||||
|
||||
operator T_integral const () const {return count_;}
|
||||
|
||||
T_integral const set(T_integral const a) { count_=a; return count_; }
|
||||
T_integral const inc(){
|
||||
if (count_ >= 0) { count_ += 1; }
|
||||
return count_; }
|
||||
T_integral const dec(){
|
||||
if( count_ > 0) { count_ -= 1; }
|
||||
return count_; }
|
||||
T_integral const enable_count(){
|
||||
if (count_ < 0) {count_ = 0;}
|
||||
return count_; }
|
||||
T_integral const disable_count(){
|
||||
count_= NOT_COUNTED;
|
||||
return count_; }
|
||||
|
||||
T_integral const operator++(){return inc();}
|
||||
T_integral const operator++(int){T_integral ret(count_); inc(); return ret;}
|
||||
T_integral const operator--(){return dec();}
|
||||
T_integral const operator--(int){T_integral ret(count_); dec(); return ret;}
|
||||
};
|
||||
|
||||
|
||||
}//end namepace
|
||||
|
||||
#endif
|
|
@ -67,7 +67,7 @@ void highlight_visitor::set_mouseover_hex(const map_location& hex)
|
|||
scoped_real_unit_map ensure_real_map;
|
||||
mouseover_hex_ = hex;
|
||||
//if we're right over a unit, just highlight all of this unit's actions
|
||||
unit_map::const_iterator it = unit_map_.find(hex);
|
||||
unit_map::iterator it = unit_map_.find(hex);
|
||||
if (it != unit_map_.end())
|
||||
{
|
||||
selection_candidate_ = &(*it);
|
||||
|
|
|
@ -86,7 +86,7 @@ validate_visitor::VALIDITY validate_visitor::evaluate_move_validity(move_ptr m_p
|
|||
return WORTHLESS;
|
||||
|
||||
//Check that the unit still exists in the source hex
|
||||
unit_map::const_iterator unit_it;
|
||||
unit_map::iterator unit_it;
|
||||
unit_it = resources::units->find(m.get_source_hex());
|
||||
if (unit_it == resources::units->end())
|
||||
return WORTHLESS;
|
||||
|
|
Loading…
Add table
Reference in a new issue