* src/misc/freelist.cc (free_list::remove): Work around

invalidated iterators.
* tgba/bdddict.cc (unregister_variable): New methods,
extracted from ...
(bdd_dict::unregister_all_my_variables): ... here.
* tgba/bdddict.hh (unregister_variable): Declare them.
This commit is contained in:
Alexandre Duret-Lutz 2004-03-25 15:02:57 +00:00
parent 784ccafb1b
commit 3c3b23bfa4
4 changed files with 90 additions and 60 deletions

View file

@ -1,3 +1,12 @@
2004-03-25 Alexandre Duret-Lutz <adl@src.lip6.fr>
* src/misc/freelist.cc (free_list::remove): Work around
invalidated iterators.
* tgba/bdddict.cc (unregister_variable): New methods,
extracted from ...
(bdd_dict::unregister_all_my_variables): ... here.
* tgba/bdddict.hh (unregister_variable): Declare them.
2004-03-23 Alexandre DURET-LUTZ <adl@src.lip6.fr> 2004-03-23 Alexandre DURET-LUTZ <adl@src.lip6.fr>
* src/misc/freelist.hh (free_list::remove, free_list::insert): New * src/misc/freelist.hh (free_list::remove, free_list::insert): New

View file

@ -131,13 +131,15 @@ namespace spot
void void
free_list::remove(int base, int n) free_list::remove(int base, int n)
{ {
free_list_type::iterator cur; free_list_type::iterator cur = fl.begin();
int end = base + n; int end = base + n;
for (cur = fl.begin(); cur != fl.end() && cur->first <= end; ++cur) while (cur != fl.end() && cur->first <= end)
{ {
int cend = cur->first + cur->second; int cend = cur->first + cur->second;
// Remove may invalidate the current iterator, so advance it first.
free_list_type::iterator old = cur++;
if (cend >= end) if (cend >= end)
remove(cur, base, std::max(n, cend - base)); remove(old, base, std::max(n, cend - base));
} }
} }

View file

@ -173,28 +173,30 @@ namespace spot
} }
void void
bdd_dict::unregister_all_my_variables(const void* me) bdd_dict::unregister_variable(int var, const void* me)
{ {
vr_map::iterator i; vr_map::iterator i = var_refs.find(var);
for (i = var_refs.begin(); i != var_refs.end();) assert(i != var_refs.end());
{ unregister_variable(i, me);
// Increment i++ now, we will possibly erase }
// the current node (which would invalidate the iterator).
vr_map::iterator cur = i++;
void
bdd_dict::unregister_variable(vr_map::iterator& cur, const void* me)
{
ref_set& s = cur->second; ref_set& s = cur->second;
ref_set::iterator si = s.find(me); ref_set::iterator si = s.find(me);
if (si == s.end()) if (si == s.end())
continue; return;
s.erase(si); s.erase(si);
if (! s.empty()) if (! s.empty())
continue; return;
// ME was the last user of this variable. // ME was the last user of this variable.
// Let's free it. First, we need to find // Let's free it. First, we need to find
// if this is a Now, a Var, or an Acc variable. // if this is a Now, a Var, or an Acc variable.
int var = cur->first; int var = cur->first;
int n = 1; int n = 1;
const ltl::formula* f; const ltl::formula* f = 0;
vf_map::iterator vi = var_formula_map.find(var); vf_map::iterator vi = var_formula_map.find(var);
if (vi != var_formula_map.end()) if (vi != var_formula_map.end())
{ {
@ -235,9 +237,22 @@ namespace spot
// Actually release the associated BDD variables, and the // Actually release the associated BDD variables, and the
// formula itself. // formula itself.
release_variables(var, n); release_variables(var, n);
if (f)
ltl::destroy(f); ltl::destroy(f);
var_refs.erase(cur); var_refs.erase(cur);
} }
void
bdd_dict::unregister_all_my_variables(const void* me)
{
vr_map::iterator i;
for (i = var_refs.begin(); i != var_refs.end();)
{
// Increment i++ now, we will possibly erase
// the current node (which would invalidate the iterator).
vr_map::iterator cur = i++;
unregister_variable(cur, me);
}
free_annonymous_list_of.erase(me); free_annonymous_list_of.erase(me);
} }

View file

@ -135,11 +135,14 @@ namespace spot
/// is deleted if \a from_other is still alive. /// is deleted if \a from_other is still alive.
void register_all_variables_of(const void* from_other, const void* for_me); void register_all_variables_of(const void* from_other, const void* for_me);
/// \brief Release the variables used by object. /// \brief Release all variables used by an object.
/// ///
/// Usually called in the destructor if \a me. /// Usually called in the destructor if \a me.
void unregister_all_my_variables(const void* me); void unregister_all_my_variables(const void* me);
/// \brief Release a variable used by \a me.
void unregister_variable(int var, const void* me);
/// @{ /// @{
/// Check whether formula \a f has already been registered by \a by_me. /// Check whether formula \a f has already been registered by \a by_me.
bool is_registered_proposition(const ltl::formula* f, const void* by_me); bool is_registered_proposition(const ltl::formula* f, const void* by_me);
@ -164,6 +167,7 @@ namespace spot
typedef Sgi::hash_map<int, ref_set> vr_map; typedef Sgi::hash_map<int, ref_set> vr_map;
vr_map var_refs; vr_map var_refs;
void unregister_variable(vr_map::iterator& cur, const void* me);
class annon_free_list : public spot::free_list class annon_free_list : public spot::free_list
{ {