summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-11-10 23:00:21 +0100
committerAndreas Kling <kling@serenityos.org>2021-11-11 01:27:46 +0100
commit9d1f2384505f08bb5b041990627eb50f2a6b941c (patch)
treec4eb2dac6b9ada5e3a5aa1a96fb4ca76f2ca9ea4
parent4eaa95769d40e1838ea5a0577d41f005540fe92e (diff)
downloadserenity-9d1f2384505f08bb5b041990627eb50f2a6b941c.zip
AK: Make HashTable and HashMap try_* functions return ErrorOr<T>
This allows us to use TRY() and MUST() with them.
-rw-r--r--AK/HashMap.h6
-rw-r--r--AK/HashTable.h48
-rw-r--r--Kernel/PerformanceEventBuffer.cpp5
3 files changed, 22 insertions, 37 deletions
diff --git a/AK/HashMap.h b/AK/HashMap.h
index 9c9b9d972a..733a7057cc 100644
--- a/AK/HashMap.h
+++ b/AK/HashMap.h
@@ -49,8 +49,8 @@ public:
HashSetResult set(const K& key, const V& value) { return m_table.set({ key, value }); }
HashSetResult set(const K& key, V&& value) { return m_table.set({ key, move(value) }); }
- HashSetResult try_set(const K& key, const V& value) { return m_table.try_set({ key, value }); }
- HashSetResult try_set(const K& key, V&& value) { return m_table.try_set({ key, move(value) }); }
+ ErrorOr<HashSetResult> try_set(const K& key, const V& value) { return m_table.try_set({ key, value }); }
+ ErrorOr<HashSetResult> try_set(const K& key, V&& value) { return m_table.try_set({ key, move(value) }); }
bool remove(const K& key)
{
@@ -91,7 +91,7 @@ public:
}
void ensure_capacity(size_t capacity) { m_table.ensure_capacity(capacity); }
- bool try_ensure_capacity(size_t capacity) { return m_table.try_ensure_capacity(capacity); }
+ ErrorOr<void> try_ensure_capacity(size_t capacity) { return m_table.try_ensure_capacity(capacity); }
Optional<typename Traits<V>::PeekType> get(const K& key) const requires(!IsPointer<typename Traits<V>::PeekType>)
{
diff --git a/AK/HashTable.h b/AK/HashTable.h
index b50d4486d5..7af8f89e07 100644
--- a/AK/HashTable.h
+++ b/AK/HashTable.h
@@ -6,6 +6,7 @@
#pragma once
+#include <AK/Error.h>
#include <AK/Forward.h>
#include <AK/HashFunctions.h>
#include <AK/StdLibExtras.h>
@@ -16,7 +17,6 @@
namespace AK {
enum class HashSetResult {
- Failed = 0,
InsertedNewEntry,
ReplacedExistingEntry,
KeptExistingEntry
@@ -186,19 +186,16 @@ public:
[[nodiscard]] size_t capacity() const { return m_capacity; }
template<typename U, size_t N>
- bool try_set_from(U (&from_array)[N])
+ ErrorOr<void> try_set_from(U (&from_array)[N])
{
- for (size_t i = 0; i < N; ++i) {
- if (try_set(from_array[i]) == HashSetResult::Failed)
- return false;
- }
- return true;
+ for (size_t i = 0; i < N; ++i)
+ TRY(try_set(from_array[i]));
+ return {};
}
template<typename U, size_t N>
void set_from(U (&from_array)[N])
{
- bool result = try_set_from(from_array);
- VERIFY(result);
+ MUST(try_set_from(from_array));
}
void ensure_capacity(size_t capacity)
@@ -260,11 +257,9 @@ public:
}
template<typename U = T>
- HashSetResult try_set(U&& value, HashSetExistingEntryBehavior existing_entry_behavior = HashSetExistingEntryBehavior::Replace)
+ ErrorOr<HashSetResult> try_set(U&& value, HashSetExistingEntryBehavior existing_entry_behavior = HashSetExistingEntryBehavior::Replace)
{
- auto* bucket = try_lookup_for_writing(value);
- if (!bucket)
- return HashSetResult::Failed;
+ auto* bucket = TRY(try_lookup_for_writing(value));
if (bucket->used) {
if (existing_entry_behavior == HashSetExistingEntryBehavior::Keep)
return HashSetResult::KeptExistingEntry;
@@ -295,9 +290,7 @@ public:
template<typename U = T>
HashSetResult set(U&& value, HashSetExistingEntryBehavior existing_entry_behaviour = HashSetExistingEntryBehavior::Replace)
{
- auto result = try_set(forward<U>(value), existing_entry_behaviour);
- VERIFY(result != HashSetResult::Failed);
- return result;
+ return MUST(try_set(forward<U>(value), existing_entry_behaviour));
}
template<typename TUnaryPredicate>
@@ -388,7 +381,7 @@ private:
}
}
- bool try_rehash(size_t new_capacity)
+ ErrorOr<void> try_rehash(size_t new_capacity)
{
new_capacity = max(new_capacity, static_cast<size_t>(4));
new_capacity = kmalloc_good_size(new_capacity * sizeof(BucketType)) / sizeof(BucketType);
@@ -399,7 +392,7 @@ private:
auto new_buckets = kmalloc(size_in_bytes(new_capacity));
if (!new_buckets)
- return false;
+ return Error::from_errno(ENOMEM);
m_buckets = (BucketType*)new_buckets;
__builtin_memset(m_buckets, 0, size_in_bytes(new_capacity));
@@ -413,7 +406,7 @@ private:
m_buckets[m_capacity].end = true;
if (!old_buckets)
- return true;
+ return {};
for (auto it = move(old_iter); it != end(); ++it) {
insert_during_rehash(move(*it));
@@ -421,12 +414,11 @@ private:
}
kfree_sized(old_buckets, size_in_bytes(old_capacity));
- return true;
+ return {};
}
void rehash(size_t new_capacity)
{
- bool result = try_rehash(new_capacity);
- VERIFY(result);
+ MUST(try_rehash(new_capacity));
}
template<typename TUnaryPredicate>
@@ -448,15 +440,13 @@ private:
}
}
- [[nodiscard]] BucketType* try_lookup_for_writing(T const& value)
+ ErrorOr<BucketType*> try_lookup_for_writing(T const& value)
{
// FIXME: Maybe overrun the "allowed" load factor to avoid OOM
// If we are allowed to do that, separate that logic from
// the normal lookup_for_writing
- if (should_grow()) {
- if (!try_rehash(capacity() * 2))
- return nullptr;
- }
+ if (should_grow())
+ TRY(try_rehash(capacity() * 2));
auto hash = TraitsForT::hash(value);
BucketType* first_empty_bucket = nullptr;
for (;;) {
@@ -478,9 +468,7 @@ private:
}
[[nodiscard]] BucketType& lookup_for_writing(T const& value)
{
- auto* item = try_lookup_for_writing(value);
- VERIFY(item);
- return *item;
+ return *MUST(try_lookup_for_writing(value));
}
[[nodiscard]] size_t used_bucket_count() const { return m_size + m_deleted_count; }
diff --git a/Kernel/PerformanceEventBuffer.cpp b/Kernel/PerformanceEventBuffer.cpp
index fc8e10f3da..7bf55726fb 100644
--- a/Kernel/PerformanceEventBuffer.cpp
+++ b/Kernel/PerformanceEventBuffer.cpp
@@ -315,10 +315,7 @@ void PerformanceEventBuffer::add_process(const Process& process, ProcessEventTyp
ErrorOr<FlatPtr> PerformanceEventBuffer::register_string(NonnullOwnPtr<KString> string)
{
FlatPtr string_id = m_strings.size();
-
- if (m_strings.try_set(move(string)) == AK::HashSetResult::Failed)
- return ENOBUFS;
-
+ TRY(m_strings.try_set(move(string)));
return string_id;
}