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>
|
template<class T, class Key, class Hash>
|
||||||
bool Foam::HashTbl<T, Key, Hash>::erase(const iterator& cit)
|
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_)
|
if (cit.elmtPtr_)
|
||||||
{
|
{
|
||||||
// Search element before 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()
|
// assign an non-NULL value so it doesn't look like end()/cend()
|
||||||
iter.elmtPtr_ = reinterpret_cast<hashedEntry*>(this);
|
iter.elmtPtr_ = reinterpret_cast<hashedEntry*>(this);
|
||||||
|
|
||||||
// mark with special hashIndex value to signal it has been rewound
|
// Mark with special hashIndex value to signal it has been rewound.
|
||||||
// the next increment will bring it back to the present location
|
// 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;
|
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>
|
template<class T, class Key, class Hash>
|
||||||
bool Foam::HashTbl<T, Key, Hash>::erase(const Key& key)
|
bool Foam::HashTbl<T, Key, Hash>::erase(const Key& key)
|
||||||
{
|
{
|
||||||
|
// we could also simply do: erase(find(key));
|
||||||
iterator fnd = find(key);
|
iterator fnd = find(key);
|
||||||
|
|
||||||
if (fnd != end())
|
if (fnd != end())
|
||||||
@ -429,19 +441,17 @@ bool Foam::HashTbl<T, Key, Hash>::erase(const Key& key)
|
|||||||
template<class T, class Key, class Hash>
|
template<class T, class Key, class Hash>
|
||||||
Foam::label Foam::HashTbl<T, Key, Hash>::erase(const UList<Key>& keys)
|
Foam::label Foam::HashTbl<T, Key, Hash>::erase(const UList<Key>& keys)
|
||||||
{
|
{
|
||||||
|
const label nTotal = nElmts_;
|
||||||
label count = 0;
|
label count = 0;
|
||||||
|
|
||||||
// Remove listed keys from this table
|
// Remove listed keys from this table - terminates early if possible
|
||||||
if (this->size())
|
for (label keyI = 0; count < nTotal && keyI < keys.size(); ++keyI)
|
||||||
{
|
|
||||||
forAll(keys, keyI)
|
|
||||||
{
|
{
|
||||||
if (erase(keys[keyI]))
|
if (erase(keys[keyI]))
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@ -456,10 +466,8 @@ Foam::label Foam::HashTbl<T, Key, Hash>::erase
|
|||||||
{
|
{
|
||||||
label count = 0;
|
label count = 0;
|
||||||
|
|
||||||
// Remove rhs elements from this table
|
// Remove rhs keys from this table - terminates early if possible
|
||||||
if (this->size())
|
// Could optimize depending on which hash is smaller ...
|
||||||
{
|
|
||||||
// NOTE: could further optimize depending on which hash is smaller
|
|
||||||
for (iterator iter = begin(); iter != end(); ++iter)
|
for (iterator iter = begin(); iter != end(); ++iter)
|
||||||
{
|
{
|
||||||
if (rhs.found(iter.key()) && erase(iter))
|
if (rhs.found(iter.key()) && erase(iter))
|
||||||
@ -467,7 +475,6 @@ Foam::label Foam::HashTbl<T, Key, Hash>::erase
|
|||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@ -618,18 +625,12 @@ bool Foam::HashTbl<T, Key, Hash>::operator==
|
|||||||
const HashTbl<T, Key, Hash>& rhs
|
const HashTbl<T, Key, Hash>& rhs
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
// Are all my elements in rhs?
|
// sizes (ie, number of keys) must match
|
||||||
for (const_iterator iter = cbegin(); iter != cend(); ++iter)
|
if (size() != rhs.size())
|
||||||
{
|
|
||||||
const_iterator fnd = rhs.find(iter.key());
|
|
||||||
|
|
||||||
if (fnd == rhs.cend() || fnd() != iter())
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Are all rhs elements in me?
|
|
||||||
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
||||||
{
|
{
|
||||||
const_iterator fnd = find(iter.key());
|
const_iterator fnd = find(iter.key());
|
||||||
@ -639,6 +640,7 @@ bool Foam::HashTbl<T, Key, Hash>::operator==
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -269,9 +269,8 @@ public:
|
|||||||
//- Assignment
|
//- Assignment
|
||||||
void operator=(const HashTbl<T, Key, Hash>&);
|
void operator=(const HashTbl<T, Key, Hash>&);
|
||||||
|
|
||||||
//- Equality. Two hash tables are equal if all contents of first are
|
//- Equality. Hash tables are equal if the keys and values are equal.
|
||||||
// also in second and vice versa. So does not depend on table size or
|
// Independent of table storage size and table order.
|
||||||
// order!
|
|
||||||
bool operator==(const HashTbl<T, Key, Hash>&) const;
|
bool operator==(const HashTbl<T, Key, Hash>&) const;
|
||||||
|
|
||||||
//- The opposite of the equality operation. Takes linear time.
|
//- The opposite of the equality operation. Takes linear time.
|
||||||
|
|||||||
@ -261,10 +261,12 @@ inline
|
|||||||
typename Foam::HashTbl<T, Key, Hash>::iterator&
|
typename Foam::HashTbl<T, Key, Hash>::iterator&
|
||||||
Foam::HashTbl<T, Key, Hash>::iterator::operator++()
|
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)
|
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_)
|
else if (elmtPtr_ && elmtPtr_->next_)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user