From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- xpcom/ds/nsCheapSets.h | 171 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 xpcom/ds/nsCheapSets.h (limited to 'xpcom/ds/nsCheapSets.h') diff --git a/xpcom/ds/nsCheapSets.h b/xpcom/ds/nsCheapSets.h new file mode 100644 index 000000000..d75e60d20 --- /dev/null +++ b/xpcom/ds/nsCheapSets.h @@ -0,0 +1,171 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef __nsCheapSets_h__ +#define __nsCheapSets_h__ + +#include "nsTHashtable.h" +#include + +enum nsCheapSetOperator +{ + OpNext = 0, // enumerator says continue + OpRemove = 1, // enumerator says remove and continue +}; + +/** + * A set that takes up minimal size when there are 0 or 1 entries in the set. + * Use for cases where sizes of 0 and 1 are even slightly common. + */ +template +class nsCheapSet +{ +public: + typedef typename EntryType::KeyType KeyType; + typedef nsCheapSetOperator (*Enumerator)(EntryType* aEntry, void* userArg); + + nsCheapSet() : mState(ZERO) {} + ~nsCheapSet() { Clear(); } + + /** + * Remove all entries. + */ + void Clear() + { + switch (mState) { + case ZERO: + break; + case ONE: + GetSingleEntry()->~EntryType(); + break; + case MANY: + delete mUnion.table; + break; + default: + NS_NOTREACHED("bogus state"); + break; + } + mState = ZERO; + } + + void Put(const KeyType aVal); + + void Remove(const KeyType aVal); + + bool Contains(const KeyType aVal) + { + switch (mState) { + case ZERO: + return false; + case ONE: + return GetSingleEntry()->KeyEquals(EntryType::KeyToPointer(aVal)); + case MANY: + return !!mUnion.table->GetEntry(aVal); + default: + NS_NOTREACHED("bogus state"); + return false; + } + } + + uint32_t EnumerateEntries(Enumerator aEnumFunc, void* aUserArg) + { + switch (mState) { + case ZERO: + return 0; + case ONE: + if (aEnumFunc(GetSingleEntry(), aUserArg) == OpRemove) { + GetSingleEntry()->~EntryType(); + mState = ZERO; + } + return 1; + case MANY: { + uint32_t n = mUnion.table->Count(); + for (auto iter = mUnion.table->Iter(); !iter.Done(); iter.Next()) { + auto entry = static_cast(iter.Get()); + if (aEnumFunc(entry, aUserArg) == OpRemove) { + iter.Remove(); + } + } + return n; + } + default: + NS_NOTREACHED("bogus state"); + return 0; + } + } + +private: + EntryType* GetSingleEntry() + { + return reinterpret_cast(&mUnion.singleEntry[0]); + } + + enum SetState + { + ZERO, + ONE, + MANY + }; + + union + { + nsTHashtable* table; + char singleEntry[sizeof(EntryType)]; + } mUnion; + enum SetState mState; +}; + +template +void +nsCheapSet::Put(const KeyType aVal) +{ + switch (mState) { + case ZERO: + new (GetSingleEntry()) EntryType(EntryType::KeyToPointer(aVal)); + mState = ONE; + return; + case ONE: { + nsTHashtable* table = new nsTHashtable(); + EntryType* entry = GetSingleEntry(); + table->PutEntry(entry->GetKey()); + entry->~EntryType(); + mUnion.table = table; + mState = MANY; + } + MOZ_FALLTHROUGH; + + case MANY: + mUnion.table->PutEntry(aVal); + return; + default: + NS_NOTREACHED("bogus state"); + return; + } +} + +template +void +nsCheapSet::Remove(const KeyType aVal) +{ + switch (mState) { + case ZERO: + break; + case ONE: + if (Contains(aVal)) { + GetSingleEntry()->~EntryType(); + mState = ZERO; + } + break; + case MANY: + mUnion.table->RemoveEntry(aVal); + break; + default: + NS_NOTREACHED("bogus state"); + break; + } +} + +#endif -- cgit v1.2.3