From 484708d5d6c234d7e282898eb05895d988569fc5 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 7 Mar 2009 21:21:10 +0000 Subject: [PATCH] Removed the OpenHashTable implementation the UserlandFS used. Adjusted the HashMap and HashSet classes to use the kernel utils OpenHashTable instead. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29429 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/userlandfs/shared/HashMap.h | 242 ++++----- headers/private/userlandfs/shared/HashSet.h | 239 ++++---- .../private/userlandfs/shared/OpenHashTable.h | 512 ------------------ .../userlandfs/server/haiku/Jamfile | 2 +- 4 files changed, 243 insertions(+), 752 deletions(-) delete mode 100644 headers/private/userlandfs/shared/OpenHashTable.h diff --git a/headers/private/userlandfs/shared/HashMap.h b/headers/private/userlandfs/shared/HashMap.h index fbd0dc74c3..7a748e938a 100644 --- a/headers/private/userlandfs/shared/HashMap.h +++ b/headers/private/userlandfs/shared/HashMap.h @@ -1,72 +1,61 @@ -// HashMap.h -// -// Copyright (c) 2004, Ingo Weinhold (bonefish@cs.tu-berlin.de) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -// -// Except as contained in this notice, the name of a copyright holder shall -// not be used in advertising or otherwise to promote the sale, use or other -// dealings in this Software without prior written authorization of the -// copyright holder. - +/* + * Copyright 2004-2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ #ifndef HASH_MAP_H #define HASH_MAP_H //#include +#include + #include "AutoLocker.h" #include "Locker.h" -#include "OpenHashTable.h" + // HashMapElement template -class HashMapElement : public OpenHashElement { +class HashMapElement : public HashTableLink > { private: typedef HashMapElement Element; + public: - - HashMapElement() : OpenHashElement(), fKey(), fValue() + HashMapElement() + : + fKey(), + fValue() { - fNext = -1; } - inline uint32 Hash() const + HashMapElement(const Key& key, const Value& value) + : + fKey(key), + fValue(value) { - return fKey.GetHashCode(); - } - - inline bool operator==(const OpenHashElement &_element) const - { - const Element &element = static_cast(_element); - return (fKey == element.fKey); - } - - inline void Adopt(Element &element) - { - fKey = element.fKey; - fValue = element.fValue; } Key fKey; Value fValue; }; + +// HashMapTableDefinition +template +struct HashMapTableDefinition { + typedef Key KeyType; + typedef HashMapElement ValueType; + + size_t HashKey(const KeyType& key) const + { return key.GetHashCode(); } + size_t Hash(const ValueType* value) const + { return HashKey(value->fKey); } + bool Compare(const KeyType& key, const ValueType* value) const + { return value->fKey == key; } + HashTableLink* GetLink(ValueType* value) const + { return value; } +}; + + // HashMap template class HashMap { @@ -85,77 +74,65 @@ public: typedef HashMapElement Element; public: Iterator(const Iterator& other) - : fMap(other.fMap), - fIndex(other.fIndex), - fElement(other.fElement), - fLastElement(other.fElement) + : + fMap(other.fMap), + fIterator(other.fIterator), + fElement(other.fElement) { } - + bool HasNext() const { - return fElement; + return fIterator.HasNext(); } - + Entry Next() { - if (!fElement) + fElement = fIterator.Next(); + if (fElement == NULL) return Entry(); - Entry result(fElement->fKey, fElement->fValue); - _FindNext(); - return result; + + return Entry(fElement->fKey, fElement->fValue); } - + Entry Remove() { - if (!fLastElement) + if (fElement == NULL) return Entry(); - Entry result(fLastElement->fKey, fLastElement->fValue); - fMap->fTable.Remove(fLastElement, true); - fLastElement = NULL; + + Entry result(fElement->fKey, fElement->fValue); + + fMap->fTable.RemoveUnchecked(fElement); + delete fElement; + fElement = NULL; + return result; } - + Iterator& operator=(const Iterator& other) { fMap = other.fMap; - fIndex = other.fIndex; + fIterator = other.fIterator; fElement = other.fElement; - fLastElement = other.fLastElement; return *this; } - + private: Iterator(HashMap* map) - : fMap(map), - fIndex(0), - fElement(NULL), - fLastElement(NULL) + : + fMap(map), + fIterator(map->fTable.GetIterator()), + fElement(NULL) { - // find first - _FindNext(); } - - void _FindNext() - { - fLastElement = fElement; - if (fElement && fElement->fNext >= 0) { - fElement = fMap->fTable.ElementAt(fElement->fNext); - return; - } - fElement = NULL; - int32 arraySize = fMap->fTable.ArraySize(); - for (; !fElement && fIndex < arraySize; fIndex++) - fElement = fMap->fTable.FindFirst(fIndex); - } - + private: friend class HashMap; - + typedef OpenHashTable > ElementTable; + HashMap* fMap; - int32 fIndex; + ElementTable::Iterator fIterator; Element* fElement; - Element* fLastElement; }; HashMap(); @@ -163,7 +140,7 @@ public: status_t InitCheck() const; - status_t Put(const Key& key, Value value); + status_t Put(const Key& key, const Value& value); Value Remove(const Key& key); void Clear(); Value Get(const Key& key) const; @@ -175,17 +152,15 @@ public: Iterator GetIterator(); protected: + typedef OpenHashTable > ElementTable; typedef HashMapElement Element; friend class Iterator; -private: - Element *_FindElement(const Key& key) const; - protected: - OpenHashElementArray fElementArray; - OpenHashTable > fTable; + ElementTable fTable; }; + // SynchronizedHashMap template class SynchronizedHashMap : public Locker { @@ -201,7 +176,7 @@ public: return fMap.InitCheck(); } - status_t Put(const Key& key, Value value) + status_t Put(const Key& key, const Value& value) { MapLocker locker(this); if (!locker.IsLocked()) @@ -331,85 +306,107 @@ struct HashKey64 { // constructor template HashMap::HashMap() - : fElementArray(1000), - fTable(1000, &fElementArray) + : + fTable() { + fTable.Init(); } + // destructor template HashMap::~HashMap() { + Clear(); } + // InitCheck template status_t HashMap::InitCheck() const { - return (fTable.InitCheck() && fElementArray.InitCheck() - ? B_OK : B_NO_MEMORY); + return (fTable.TableSize() > 0 ? B_OK : B_NO_MEMORY); } + // Put template status_t -HashMap::Put(const Key& key, Value value) +HashMap::Put(const Key& key, const Value& value) { - Element* element = _FindElement(key); + Element* element = fTable.Lookup(key); if (element) { // already contains the key: just set the new value element->fValue = value; return B_OK; } - // does not contain the key yet: add an element - element = fTable.Add(key.GetHashCode()); + + // does not contain the key yet: create an element and add it + element = new(std::nothrow) Element(key, value); if (!element) return B_NO_MEMORY; - element->fKey = key; - element->fValue = value; - return B_OK; + + status_t error = fTable.Insert(element); + if (error != B_OK) + delete element; + + return error; } + // Remove template Value HashMap::Remove(const Key& key) { - Value value = Value(); - if (Element* element = _FindElement(key)) { - value = element->fValue; - fTable.Remove(element); - } + Element* element = fTable.Lookup(key); + if (element == NULL) + return Value(); + + fTable.Remove(element); + Value value = element->fValue; + delete element; + return value; } + // Clear template void HashMap::Clear() { - fTable.RemoveAll(); + // clear the table and delete the elements + Element* element = fTable.Clear(true); + while (element != NULL) { + Element* next = element->fNext; + delete element; + element = next; + } } + // Get template Value HashMap::Get(const Key& key) const { - if (Element* element = _FindElement(key)) + if (Element* element = fTable.Lookup(key)) return element->fValue; return Value(); } + // ContainsKey template bool HashMap::ContainsKey(const Key& key) const { - return _FindElement(key); + return fTable.Lookup(key) != NULL; } + // Size template int32 @@ -418,6 +415,7 @@ HashMap::Size() const return fTable.CountElements(); } + // GetIterator template typename HashMap::Iterator @@ -426,19 +424,5 @@ HashMap::GetIterator() return Iterator(this); } -// _FindElement -template -typename HashMap::Element * -HashMap::_FindElement(const Key& key) const -{ - Element* element = fTable.FindFirst(key.GetHashCode()); - while (element && element->fKey != key) { - if (element->fNext >= 0) - element = fTable.ElementAt(element->fNext); - else - element = NULL; - } - return element; -} #endif // HASH_MAP_H diff --git a/headers/private/userlandfs/shared/HashSet.h b/headers/private/userlandfs/shared/HashSet.h index 9c5e39cfb1..373f127ae8 100644 --- a/headers/private/userlandfs/shared/HashSet.h +++ b/headers/private/userlandfs/shared/HashSet.h @@ -1,68 +1,56 @@ -// HashSet.h -// -// Copyright (c) 2004, Ingo Weinhold (bonefish@cs.tu-berlin.de) -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -// -// Except as contained in this notice, the name of a copyright holder shall -// not be used in advertising or otherwise to promote the sale, use or other -// dealings in this Software without prior written authorization of the -// copyright holder. - +/* + * Copyright 2004-2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ #ifndef HASH_SET_H #define HASH_SET_H +#include + #include "AutoLocker.h" #include "Locker.h" -#include "OpenHashTable.h" + // HashSetElement template -class HashSetElement : public OpenHashElement { +class HashSetElement : public HashTableLink > { private: typedef HashSetElement Element; + public: - - HashSetElement() : OpenHashElement(), fKey() + HashSetElement() + : + fKey() { - fNext = -1; } - inline uint32 Hash() const + HashSetElement(const Key& key) + : + fKey(key) { - return fKey.GetHashCode(); - } - - inline bool operator==(const OpenHashElement &_element) const - { - const Element &element = static_cast(_element); - return (fKey == element.fKey); - } - - inline void Adopt(Element &element) - { - fKey = element.fKey; } Key fKey; }; + +// HashSetTableDefinition +template +struct HashSetTableDefinition { + typedef Key KeyType; + typedef HashSetElement ValueType; + + size_t HashKey(const KeyType& key) const + { return key.GetHashCode(); } + size_t Hash(const ValueType* value) const + { return HashKey(value->fKey); } + bool Compare(const KeyType& key, const ValueType* value) const + { return value->fKey == key; } + HashTableLink* GetLink(ValueType* value) const + { return value; } +}; + + // HashSet template class HashSet { @@ -72,76 +60,66 @@ public: typedef HashSetElement Element; public: Iterator(const Iterator& other) - : fSet(other.fSet), - fIndex(other.fIndex), - fElement(other.fElement), - fLastElement(other.fElement) + : + fSet(other.fSet), + fIterator(other.fIterator), + fElement(other.fElement) { } - + bool HasNext() const { - return fElement; + return fIterator.HasNext(); } - + Key Next() { - if (!fElement) + fElement = fIterator.Next(); + if (fElement == NULL) return Key(); - Key result(fElement->fKey); - _FindNext(); - return result; + + return fElement->fKey; } - + bool Remove() { - if (!fLastElement) + if (fElement == NULL) return false; - fSet->fTable.Remove(fLastElement); - fLastElement = NULL; + + fSet->fTable.RemoveUnchecked(fElement); + delete fElement; + fElement = NULL; + return true; } - + Iterator& operator=(const Iterator& other) { fSet = other.fSet; - fIndex = other.fIndex; + fIterator = other.fIterator; fElement = other.fElement; - fLastElement = other.fLastElement; return *this; } - + private: - Iterator(HashSet* map) - : fSet(map), - fIndex(0), - fElement(NULL), - fLastElement(NULL) + Iterator(HashSet* set) + : + fSet(set), + fIterator(set->fTable.GetIterator()), + fElement(NULL) { - // find first - _FindNext(); } - - void _FindNext() - { - fLastElement = fElement; - if (fElement && fElement->fNext >= 0) { - fElement = fSet->fTable.ElementAt(fElement->fNext); - return; - } - fElement = NULL; - int32 arraySize = fSet->fTable.ArraySize(); - for (; !fElement && fIndex < arraySize; fIndex++) - fElement = fSet->fTable.FindFirst(fIndex); - } - + + private: + friend class HashMap; + typedef OpenHashTable > ElementTable; + + HashSet* fSet; + ElementTable::Iterator fIterator; + Element* fElement; + private: friend class HashSet; - - HashSet* fSet; - int32 fIndex; - Element* fElement; - Element* fLastElement; }; HashSet(); @@ -151,6 +129,7 @@ public: status_t Add(const Key& key); bool Remove(const Key& key); + void Clear(); bool Contains(const Key& key) const; int32 Size() const; @@ -158,24 +137,22 @@ public: Iterator GetIterator(); protected: + typedef OpenHashTable > ElementTable; typedef HashSetElement Element; friend class Iterator; -private: - Element *_FindElement(const Key& key) const; - protected: - OpenHashElementArray fElementArray; - OpenHashTable > fTable; + ElementTable fTable; }; + // SynchronizedHashSet template class SynchronizedHashSet : public Locker { public: typedef HashSet::Iterator Iterator; - SynchronizedHashSet() : Locker("synchronized hash map") {} + SynchronizedHashSet() : Locker("synchronized hash set") {} ~SynchronizedHashSet() { Lock(); } status_t InitCheck() const @@ -199,6 +176,12 @@ public: return fSet.Remove(key); } + void Clear() + { + MapLocker locker(this); + fSet.Clear(); + } + bool Contains(const Key& key) const { const Locker* lock = this; @@ -230,65 +213,100 @@ protected: HashSet fSet; }; + // HashSet // constructor template HashSet::HashSet() - : fElementArray(1000), - fTable(1000, &fElementArray) + : + fTable() { + fTable.Init(); } + // destructor template HashSet::~HashSet() { + Clear(); } + // InitCheck template status_t HashSet::InitCheck() const { - return (fTable.InitCheck() && fElementArray.InitCheck() - ? B_OK : B_NO_MEMORY); + return (fTable.TableSize() > 0 ? B_OK : B_NO_MEMORY); } + // Add template status_t HashSet::Add(const Key& key) { - if (Contains(key)) + Element* element = fTable.Lookup(key); + if (element) { + // already contains the value return B_OK; - Element* element = fTable.Add(key.GetHashCode()); + } + + // does not contain the key yet: create an element and add it + element = new(std::nothrow) Element(key); if (!element) return B_NO_MEMORY; - element->fKey = key; - return B_OK; + + status_t error = fTable.Insert(element); + if (error != B_OK) + delete element; + + return error; } + // Remove template bool HashSet::Remove(const Key& key) { - if (Element* element = _FindElement(key)) { - fTable.Remove(element); - return true; - } - return false; + Element* element = fTable.Lookup(key); + if (element == NULL) + return false; + + fTable.Remove(element); + delete element; + + return true; } + +// Clear +template +void +HashSet::Clear() +{ + // clear the table and delete the elements + Element* element = fTable.Clear(true); + while (element != NULL) { + Element* next = element->fNext; + delete element; + element = next; + } +} + + // Contains template bool HashSet::Contains(const Key& key) const { - return _FindElement(key); + return fTable.Lookup(key) != NULL; } + // Size template int32 @@ -320,4 +338,5 @@ HashSet::_FindElement(const Key& key) const return element; } + #endif // HASH_SET_H diff --git a/headers/private/userlandfs/shared/OpenHashTable.h b/headers/private/userlandfs/shared/OpenHashTable.h deleted file mode 100644 index 026287974c..0000000000 --- a/headers/private/userlandfs/shared/OpenHashTable.h +++ /dev/null @@ -1,512 +0,0 @@ -/* -Open Tracker License - -Terms and Conditions - -Copyright (c) 1991-2000, Be Incorporated. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice applies to all licensees -and shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of Be Incorporated shall not be -used in advertising or otherwise to promote the sale, use or other dealings in -this Software without prior written authorization from Be Incorporated. - -Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks -of Be Incorporated in the United States and other countries. Other brand product -names are registered trademarks or trademarks of their respective holders. -All rights reserved. -*/ - -// bonefish: -// * removed need for exceptions -// * fixed warnings -// * implemented rehashing -// * added RemoveAll() -// TODO: -// * shrinking of element vectors - -// Hash table with open addresssing - -#ifndef __OPEN_HASH_TABLE__ -#define __OPEN_HASH_TABLE__ - -#include -#include - -// don't include -#ifndef ASSERT -# define ASSERT(E) (void)0 -#endif -#define TRESPASS() (void)0 - -//namespace BPrivate { - -template -class ElementVector { - // element vector for OpenHashTable needs to implement this - // interface -public: - Element &At(int32 index); - Element *Add(); - int32 IndexOf(const Element &) const; - void Remove(int32 index); -}; - -class OpenHashElement { -public: - uint32 Hash() const; - bool operator==(const OpenHashElement &) const; - void Adopt(OpenHashElement &); - // low overhead copy, original element is in undefined state - // after call (calls Adopt on BString members, etc.) - int32 fNext; -}; - -const uint32 kPrimes [] = { - 509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139, - 524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393, 67108859, - 134217689, 268435399, 536870909, 1073741789, 2147483647, 0 -}; - -template > -class OpenHashTable { -public: - OpenHashTable(int32 minSize, ElementVec *elementVector = 0, - float maxLoadFactor = 0.8); - // it is up to the subclass of OpenHashTable to supply - // elementVector - ~OpenHashTable(); - - bool InitCheck() const; - - void SetElementVector(ElementVec *elementVector); - - Element *FindFirst(uint32 elementHash) const; - Element *Add(uint32 elementHash); - - void Remove(Element *element, bool dontRehash = false); - void RemoveAll(); - - // when calling Add, any outstanding element pointer may become - // invalid; to deal with this, get the element index and restore - // it after the add - int32 ElementIndex(const Element *) const; - Element *ElementAt(int32 index) const; - - int32 ArraySize() const; - int32 VectorSize() const; - int32 CountElements() const; - -protected: - static int32 OptimalSize(int32 minSize); - -private: - bool _RehashIfNeeded(); - bool _Rehash(); - - int32 fArraySize; - int32 fInitialSize; - int32 fElementCount; - int32 *fHashArray; - ElementVec *fElementVector; - float fMaxLoadFactor; -}; - -template -class OpenHashElementArray : public ElementVector { - // this is a straightforward implementation of an element vector - // deleting is handled by linking deleted elements into a free list - // the vector never shrinks -public: - OpenHashElementArray(int32 initialSize); - ~OpenHashElementArray(); - - bool InitCheck() const; - - Element &At(int32 index); - const Element &At(int32 index) const; - Element *Add(const Element &); - Element *Add(); - void Remove(int32 index); - int32 IndexOf(const Element &) const; - int32 Size() const; - -private: - Element *fData; - int32 fSize; - int32 fNextFree; - int32 fNextDeleted; -}; - - -//----------------------------------- - -template -OpenHashTable::OpenHashTable(int32 minSize, - ElementVec *elementVector, float maxLoadFactor) - : fArraySize(OptimalSize(minSize)), - fInitialSize(fArraySize), - fElementCount(0), - fElementVector(elementVector), - fMaxLoadFactor(maxLoadFactor) -{ - // sanity check the maximal load factor - if (fMaxLoadFactor < 0.5) - fMaxLoadFactor = 0.5; - // allocate and init the array - fHashArray = (int32*)calloc(fArraySize, sizeof(int32)); - if (fHashArray) { - for (int32 index = 0; index < fArraySize; index++) - fHashArray[index] = -1; - } -} - -template -OpenHashTable::~OpenHashTable() -{ - RemoveAll(); - free(fHashArray); -} - -template -bool -OpenHashTable::InitCheck() const -{ - return (fHashArray && fElementVector); -} - -template -int32 -OpenHashTable::OptimalSize(int32 minSize) -{ - for (int32 index = 0; ; index++) - if (!kPrimes[index] || kPrimes[index] >= (uint32)minSize) - return (int32)kPrimes[index]; - - return 0; -} - -template -Element * -OpenHashTable::FindFirst(uint32 hash) const -{ - ASSERT(fElementVector); - hash %= fArraySize; - if (fHashArray[hash] < 0) - return 0; - - return &fElementVector->At(fHashArray[hash]); -} - -template -int32 -OpenHashTable::ElementIndex(const Element *element) const -{ - return fElementVector->IndexOf(*element); -} - -template -Element * -OpenHashTable::ElementAt(int32 index) const -{ - return &fElementVector->At(index); -} - -template -int32 -OpenHashTable::ArraySize() const -{ - return fArraySize; -} - -template -int32 -OpenHashTable::VectorSize() const -{ - return fElementVector->Size(); -} - -template -int32 -OpenHashTable::CountElements() const -{ - return fElementCount; -} - - -template -Element * -OpenHashTable::Add(uint32 hash) -{ - ASSERT(fElementVector); - _RehashIfNeeded(); - hash %= fArraySize; - Element *result = fElementVector->Add(); - if (result) { - result->fNext = fHashArray[hash]; - fHashArray[hash] = fElementVector->IndexOf(*result); - fElementCount++; - } - return result; -} - -template -void -OpenHashTable::Remove(Element *element, bool dontRehash) -{ - if (!dontRehash) - _RehashIfNeeded(); - uint32 hash = element->Hash() % fArraySize; - int32 next = fHashArray[hash]; - ASSERT(next >= 0); - - if (&fElementVector->At(next) == element) { - fHashArray[hash] = element->fNext; - fElementVector->Remove(next); - fElementCount--; - return; - } - - for (int32 index = next; index >= 0; ) { - // look for an existing match in table - next = fElementVector->At(index).fNext; - if (next < 0) { - TRESPASS(); - return; - } - - if (&fElementVector->At(next) == element) { - fElementVector->At(index).fNext = element->fNext; - fElementVector->Remove(next); - fElementCount--; - return; - } - index = next; - } -} - -template -void -OpenHashTable::RemoveAll() -{ - for (int32 i = 0; fElementCount > 0 && i < fArraySize; i++) { - int32 index = fHashArray[i]; - while (index >= 0) { - Element* element = &fElementVector->At(index); - int32 next = element->fNext; - fElementVector->Remove(index); - fElementCount--; - index = next; - } - fHashArray[i] = -1; - } - _RehashIfNeeded(); -} - -template -void -OpenHashTable::SetElementVector(ElementVec *elementVector) -{ - fElementVector = elementVector; -} - -// _RehashIfNeeded -template -bool -OpenHashTable::_RehashIfNeeded() -{ - // The load factor range [fMaxLoadFactor / 3, fMaxLoadFactor] is fine, - // I think. After rehashing the load factor will be about - // fMaxLoadFactor * 2 / 3, respectively fMaxLoadFactor / 2. - float loadFactor = (float)fElementCount / (float)fArraySize; - if (loadFactor > fMaxLoadFactor - || (fArraySize > fInitialSize && loadFactor < fMaxLoadFactor / 3)) { - return _Rehash(); - } - return true; -} - -// _Rehash -template -bool -OpenHashTable::_Rehash() -{ - bool result = true; - int32 newSize = int32(fElementCount * 1.73 * fMaxLoadFactor); - newSize = (fInitialSize > newSize ? fInitialSize : newSize); - if (newSize != fArraySize) { - // allocate a new array - int32 *newHashArray = (int32*)calloc(newSize, sizeof(int32)); - if (newHashArray) { - // init the new hash array - for (int32 index = 0; index < newSize; index++) - newHashArray[index] = -1; - // iterate through all elements and put them into the new - // hash array - for (int i = 0; i < fArraySize; i++) { - int32 index = fHashArray[i]; - while (index >= 0) { - // insert the element in the new array - Element &element = fElementVector->At(index); - int32 next = element.fNext; - uint32 hash = (element.Hash() % newSize); - element.fNext = newHashArray[hash]; - newHashArray[hash] = index; - // next element in old list - index = next; - } - } - // delete the old array and set the new one - free(fHashArray); - fHashArray = newHashArray; - fArraySize = newSize; - } else - result = false; - } - return result; -} - - -template -OpenHashElementArray::OpenHashElementArray(int32 initialSize) - : fSize(initialSize), - fNextFree(0), - fNextDeleted(-1) -{ - fData = (Element*)calloc((size_t)initialSize, sizeof(Element)); -} - -template -OpenHashElementArray::~OpenHashElementArray() -{ - free(fData); -} - -template -bool -OpenHashElementArray::InitCheck() const -{ - return fData; -} - -template -Element & -OpenHashElementArray::At(int32 index) -{ - ASSERT(index < fSize); - return fData[index]; -} - -template -const Element & -OpenHashElementArray::At(int32 index) const -{ - ASSERT(index < fSize); - return fData[index]; -} - -template -int32 -OpenHashElementArray::IndexOf(const Element &element) const -{ - int32 result = &element - fData; - if (result < 0 || result > fSize) - return -1; - - return result; -} - -template -int32 -OpenHashElementArray::Size() const -{ - return fSize; -} - - -template -Element * -OpenHashElementArray::Add(const Element &newElement) -{ - Element *element = Add(); - if (element) - element.Adopt(newElement); - return element; -} - -#if DEBUG -const int32 kGrowChunk = 10; -#else -const int32 kGrowChunk = 1024; -#endif - -template -Element * -OpenHashElementArray::Add() -{ - int32 index = fNextFree; - if (fNextDeleted >= 0) { - index = fNextDeleted; - fNextDeleted = At(index).fNext; - } else if (fNextFree >= fSize - 1) { - int32 newSize = fSize + kGrowChunk; -/* - Element *newData = (Element *)calloc((size_t)newSize , sizeof(Element)); - if (!newData) - return NULL; - memcpy(newData, fData, fSize * sizeof(Element)); - free(fData); -*/ - Element *newData = (Element*)realloc(fData, - (size_t)newSize * sizeof(Element)); - if (!newData) - return NULL; - - fData = newData; - fSize = newSize; - index = fNextFree; - fNextFree++; - } else - fNextFree++; - - new (&At(index)) Element; - // call placement new to initialize the element properly - ASSERT(At(index).fNext == -1); - - return &At(index); -} - -template -void -OpenHashElementArray::Remove(int32 index) -{ - // delete by chaining empty elements in a single linked - // list, reusing the next field - ASSERT(index < fSize); - At(index).~Element(); - // call the destructor explicitly to destroy the element - // properly - At(index).fNext = fNextDeleted; - fNextDeleted = index; -} - -//} // namespace BPrivate - -//using namespace BPrivate; - -#endif diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/Jamfile b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/Jamfile index 78b4ac9f07..3b05f6615f 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/Jamfile +++ b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/Jamfile @@ -9,7 +9,7 @@ SubDirHdrs [ FDirName $(userlandFSIncludes) private ] ; SubDirHdrs [ FDirName $(userlandFSIncludes) shared ] ; UsePrivateSystemHeaders ; -UsePrivateHeaders libroot shared ; +UsePrivateHeaders kernel libroot shared ; SEARCH_SOURCE += [ FDirName $(userlandFSTop) private ] ; SEARCH_SOURCE += [ FDirName $(userlandFSTop) shared ] ;