mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
HashTbl: improve efficiency when deleting many keys and in operator==
- fix off by one error in erase/increment code
This commit is contained in:
@ -341,10 +341,15 @@ bool Foam::HashTbl<T, Key, Hash>::set
|
||||
}
|
||||
|
||||
|
||||
// NOTE:
|
||||
// We use (const iterator&) here, but manipulate its contents anyhow.
|
||||
// The parameter should be (iterator&), but then the compiler doesn't find
|
||||
// it correctly and tries to call as (iterator) instead.
|
||||
//
|
||||
template<class T, class Key, class Hash>
|
||||
bool Foam::HashTbl<T, Key, Hash>::erase(const iterator& cit)
|
||||
{
|
||||
// note: endIter_ has NULL elmtPtr_, so this also catches that
|
||||
// note: elmtPtr_ is NULL for end(), so this catches that too
|
||||
if (cit.elmtPtr_)
|
||||
{
|
||||
// Search element before elmtPtr_
|
||||
@ -378,8 +383,14 @@ bool Foam::HashTbl<T, Key, Hash>::erase(const iterator& cit)
|
||||
// assign an non-NULL value so it doesn't look like end()/cend()
|
||||
iter.elmtPtr_ = reinterpret_cast<hashedEntry*>(this);
|
||||
|
||||
// mark with special hashIndex value to signal it has been rewound
|
||||
// the next increment will bring it back to the present location
|
||||
// Mark with special hashIndex value to signal it has been rewound.
|
||||
// The next increment will bring it back to the present location.
|
||||
//
|
||||
// For the current position 'X', mark it as '-(X+1)', which is
|
||||
// written as '-X-1' to avoid overflow.
|
||||
// The extra '-1' is needed to avoid ambiguity for position '0'.
|
||||
// To retrieve the previous position 'X-1' we would later
|
||||
// use '-(-X-1) - 2'
|
||||
iter.hashIndex_ = -iter.hashIndex_ - 1;
|
||||
}
|
||||
|
||||
@ -413,6 +424,7 @@ bool Foam::HashTbl<T, Key, Hash>::erase(const iterator& cit)
|
||||
template<class T, class Key, class Hash>
|
||||
bool Foam::HashTbl<T, Key, Hash>::erase(const Key& key)
|
||||
{
|
||||
// we could also simply do: erase(find(key));
|
||||
iterator fnd = find(key);
|
||||
|
||||
if (fnd != end())
|
||||
@ -429,19 +441,17 @@ bool Foam::HashTbl<T, Key, Hash>::erase(const Key& key)
|
||||
template<class T, class Key, class Hash>
|
||||
Foam::label Foam::HashTbl<T, Key, Hash>::erase(const UList<Key>& keys)
|
||||
{
|
||||
const label nTotal = nElmts_;
|
||||
label count = 0;
|
||||
|
||||
// Remove listed keys from this table
|
||||
if (this->size())
|
||||
{
|
||||
forAll(keys, keyI)
|
||||
// Remove listed keys from this table - terminates early if possible
|
||||
for (label keyI = 0; count < nTotal && keyI < keys.size(); ++keyI)
|
||||
{
|
||||
if (erase(keys[keyI]))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
@ -456,10 +466,8 @@ Foam::label Foam::HashTbl<T, Key, Hash>::erase
|
||||
{
|
||||
label count = 0;
|
||||
|
||||
// Remove rhs elements from this table
|
||||
if (this->size())
|
||||
{
|
||||
// NOTE: could further optimize depending on which hash is smaller
|
||||
// Remove rhs keys from this table - terminates early if possible
|
||||
// Could optimize depending on which hash is smaller ...
|
||||
for (iterator iter = begin(); iter != end(); ++iter)
|
||||
{
|
||||
if (rhs.found(iter.key()) && erase(iter))
|
||||
@ -467,7 +475,6 @@ Foam::label Foam::HashTbl<T, Key, Hash>::erase
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
@ -618,18 +625,12 @@ bool Foam::HashTbl<T, Key, Hash>::operator==
|
||||
const HashTbl<T, Key, Hash>& rhs
|
||||
) const
|
||||
{
|
||||
// Are all my elements in rhs?
|
||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
||||
{
|
||||
const_iterator fnd = rhs.find(iter.key());
|
||||
|
||||
if (fnd == rhs.cend() || fnd() != iter())
|
||||
// sizes (ie, number of keys) must match
|
||||
if (size() != rhs.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Are all rhs elements in me?
|
||||
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
||||
{
|
||||
const_iterator fnd = find(iter.key());
|
||||
@ -639,6 +640,7 @@ bool Foam::HashTbl<T, Key, Hash>::operator==
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -269,9 +269,8 @@ public:
|
||||
//- Assignment
|
||||
void operator=(const HashTbl<T, Key, Hash>&);
|
||||
|
||||
//- Equality. Two hash tables are equal if all contents of first are
|
||||
// also in second and vice versa. So does not depend on table size or
|
||||
// order!
|
||||
//- Equality. Hash tables are equal if the keys and values are equal.
|
||||
// Independent of table storage size and table order.
|
||||
bool operator==(const HashTbl<T, Key, Hash>&) const;
|
||||
|
||||
//- The opposite of the equality operation. Takes linear time.
|
||||
|
||||
@ -261,10 +261,12 @@ inline
|
||||
typename Foam::HashTbl<T, Key, Hash>::iterator&
|
||||
Foam::HashTbl<T, Key, Hash>::iterator::operator++()
|
||||
{
|
||||
// Check for special value (from erase) - this indicates the previous bin
|
||||
// A negative index is a special value from erase
|
||||
if (hashIndex_ < 0)
|
||||
{
|
||||
hashIndex_ = -hashIndex_;
|
||||
// old position 'X' was marked as '-(X+1)'
|
||||
// but we wish to continue at 'X-1'
|
||||
hashIndex_ = -hashIndex_ - 2;
|
||||
}
|
||||
else if (elmtPtr_ && elmtPtr_->next_)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user