Bug 1181445 (part 1) - Implement iterators for nsTHashtable and nsBaseHashtable. r=froydnj.

nsBaseHashtable has both EnumerateRead() and Enumerate(). A comment claims that
the latter locks the table, but this is false, so I removed the comment. Other
than that the only notable difference between them is that they have slightly
different types for dealing with values (|UserDataType| vs |DataType&|) so I've
implemented both GetUserData() and GetData(), allowing either type to be used.
This commit is contained in:
Nicholas Nethercote 2015-07-07 20:47:59 -07:00
parent d99c241868
commit 099f5c1870
2 changed files with 79 additions and 2 deletions

View File

@ -162,6 +162,7 @@ public:
/**
* enumerate entries in the hashtable, without allowing changes
* WARNING: this function is deprecated. Please use Iterator instead.
* @param aEnumFunc enumeration callback
* @param aUserArg passed unchanged to the EnumReadFunction
*/
@ -196,8 +197,9 @@ public:
void* aUserArg);
/**
* enumerate entries in the hashtable, allowing changes. This
* functions write-locks the hashtable.
* enumerate entries in the hashtable, allowing changes.
* WARNING: this function is deprecated. Please use Iterator and/or
* MutatingIterator instead.
* @param aEnumFunc enumeration callback
* @param aUserArg passed unchanged to the EnumFunction
*/
@ -218,6 +220,47 @@ public:
return n;
}
// This is an iterator that also allows entry removal. Example usage:
//
// for (auto iter = table.Iter(); !iter.Done(); iter.Next()) {
// const KeyType key = iter.GetKey();
// const UserDataType data = iter.GetUserData();
// // or
// const DataType& data = iter.GetData();
// // ... do stuff with |key| and/or |data| ...
// // ... possibly call iter.Remove() once ...
// }
//
class Iterator : public PLDHashTable::Iterator
{
public:
typedef PLDHashTable::Iterator Base;
explicit Iterator(nsBaseHashtable* aTable) : Base(&aTable->mTable) {}
Iterator(Iterator&& aOther) : Base(aOther.mTable) {}
~Iterator() {}
KeyType GetKey() const { return static_cast<EntryType*>(Get())->GetKey(); }
UserDataType GetUserData() const
{
return static_cast<EntryType*>(Get())->mData;
}
DataType& GetData() const { return static_cast<EntryType*>(Get())->mData; }
private:
Iterator() = delete;
Iterator(const Iterator&) = delete;
Iterator& operator=(const Iterator&) = delete;
Iterator& operator=(const Iterator&&) = delete;
};
Iterator Iter() { return Iterator(this); }
Iterator ConstIter() const
{
return Iterator(const_cast<nsBaseHashtable*>(this));
}
/**
* reset the hashtable, removing all entries
*/

View File

@ -205,6 +205,7 @@ public:
* a PL_DHASH_REMOVE return value from |aEnumFunc|, the table may be shrunk
* at the end. Use RawRemoveEntry() instead if you wish to remove an entry
* without possibly shrinking the table.
* WARNING: this function is deprecated. Please use Iterator instead.
* @param enumFunc the <code>Enumerator</code> function to call
* @param userArg a pointer to pass to the
* <code>Enumerator</code> function
@ -227,6 +228,39 @@ public:
return n;
}
// This is an iterator that also allows entry removal. Example usage:
//
// for (auto iter = table.Iter(); !iter.Done(); iter.Next()) {
// Entry* entry = iter.Get();
// // ... do stuff with |entry| ...
// // ... possibly call iter.Remove() once ...
// }
//
class Iterator : public PLDHashTable::Iterator
{
public:
typedef PLDHashTable::Iterator Base;
explicit Iterator(nsTHashtable* aTable) : Base(&aTable->mTable) {}
Iterator(Iterator&& aOther) : Base(aOther.mTable) {}
~Iterator() {}
EntryType* Get() const { return static_cast<EntryType*>(Base::Get()); }
private:
Iterator() = delete;
Iterator(const Iterator&) = delete;
Iterator& operator=(const Iterator&) = delete;
Iterator& operator=(const Iterator&&) = delete;
};
Iterator Iter() { return Iterator(this); }
Iterator ConstIter() const
{
return Iterator(const_cast<nsTHashtable*>(this));
}
/**
* Remove all entries, return hashtable to "pristine" state. It's
* conceptually the same as calling the destructor and then re-calling the