From 147ea49a3abb3555246bf98b1196d34cbdf7a463 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 6 Mar 2020 18:07:29 -0800 Subject: [PATCH] util: add boundedmap --- .../stratosphere/ncm/ncm_bounded_map.hpp | 57 +------- .../lr/lr_location_resolver_manager_impl.cpp | 4 +- libraries/libvapours/include/vapours/util.hpp | 1 + .../include/vapours/util/util_bounded_map.hpp | 129 ++++++++++++++++++ 4 files changed, 133 insertions(+), 58 deletions(-) create mode 100644 libraries/libvapours/include/vapours/util/util_bounded_map.hpp diff --git a/libraries/libstratosphere/include/stratosphere/ncm/ncm_bounded_map.hpp b/libraries/libstratosphere/include/stratosphere/ncm/ncm_bounded_map.hpp index 9f4eb47f0..4d72c653b 100644 --- a/libraries/libstratosphere/include/stratosphere/ncm/ncm_bounded_map.hpp +++ b/libraries/libstratosphere/include/stratosphere/ncm/ncm_bounded_map.hpp @@ -19,61 +19,6 @@ namespace ams::ncm { template - class BoundedMap { - private: - std::array, N> keys; - std::array values; - public: - Value *Find(const Key &key) { - for (size_t i = 0; i < N; i++) { - if (this->keys[i] && this->keys[i].value() == key) { - return &this->values[i]; - } - } - return nullptr; - } - - void Remove(const Key &key) { - for (size_t i = 0; i < N; i++) { - if (this->keys[i] && this->keys[i].value() == key) { - this->keys[i].reset(); - } - } - } - - void RemoveAll() { - for (size_t i = 0; i < N; i++) { - this->keys[i].reset(); - } - } - - bool IsFull() { - for (size_t i = 0; i < N; i++) { - if (!this->keys[i]) { - return false; - } - } - - return true; - } - - Value &operator[](const Key &key) { - /* Try to find an existing value. */ - if (Value *value = this->Find(key); value != nullptr) { - return *value; - } - - /* Reference a new value. */ - for (size_t i = 0; i < N; i++) { - if (!this->keys[i]) { - this->keys[i] = key; - return this->values[i]; - } - } - - /* We ran out of space in the map. */ - AMS_ABORT(); - } - }; + using BoundedMap = util::BoundedMap; } diff --git a/libraries/libstratosphere/source/lr/lr_location_resolver_manager_impl.cpp b/libraries/libstratosphere/source/lr/lr_location_resolver_manager_impl.cpp index 4dec7b1cd..0167a5515 100644 --- a/libraries/libstratosphere/source/lr/lr_location_resolver_manager_impl.cpp +++ b/libraries/libstratosphere/source/lr/lr_location_resolver_manager_impl.cpp @@ -30,11 +30,11 @@ namespace ams::lr { /* No existing resolver is present, create one. */ if (!resolver) { if (storage_id == ncm::StorageId::Host) { - this->location_resolvers[storage_id] = std::make_shared(); + AMS_ABORT_UNLESS(this->location_resolvers.Insert(storage_id, std::make_shared())); } else { auto content_resolver = std::make_shared(storage_id); R_TRY(content_resolver->Refresh()); - this->location_resolvers[storage_id] = std::move(content_resolver); + AMS_ABORT_UNLESS(this->location_resolvers.Insert(storage_id, std::move(content_resolver))); } /* Acquire the newly-created resolver. */ diff --git a/libraries/libvapours/include/vapours/util.hpp b/libraries/libvapours/include/vapours/util.hpp index b1d000fea..f3dbdb62d 100644 --- a/libraries/libvapours/include/vapours/util.hpp +++ b/libraries/libvapours/include/vapours/util.hpp @@ -32,3 +32,4 @@ #include #include #include +#include diff --git a/libraries/libvapours/include/vapours/util/util_bounded_map.hpp b/libraries/libvapours/include/vapours/util/util_bounded_map.hpp new file mode 100644 index 000000000..d76f7a6d7 --- /dev/null +++ b/libraries/libvapours/include/vapours/util/util_bounded_map.hpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include +#include +#include + +namespace ams::util { + + template + class BoundedMap { + private: + std::array, N> keys; + std::array values; + private: + ALWAYS_INLINE void FreeEntry(size_t i) { + this->keys[i].reset(); + GetReference(this->values[i]).~Value(); + } + public: + Value *Find(const Key &key) { + for (size_t i = 0; i < N; i++) { + if (this->keys[i] && this->keys[i].value() == key) { + return GetPointer(this->values[i]); + } + } + return nullptr; + } + + void Remove(const Key &key) { + for (size_t i = 0; i < N; i++) { + if (this->keys[i] && this->keys[i].value() == key) { + this->FreeEntry(i); + break; + } + } + } + + void RemoveAll() { + for (size_t i = 0; i < N; i++) { + this->FreeEntry(i); + } + } + + bool IsFull() { + for (size_t i = 0; i < N; i++) { + if (!this->keys[i]) { + return false; + } + } + + return true; + } + + bool Insert(const Key &key, Value &&value) { + /* We can't insert if the key is used. */ + if (this->Find(key) != nullptr) { + return false; + } + + /* Find a free value. */ + for (size_t i = 0; i < N; i++) { + if (!this->keys[i]) { + this->keys[i] = key; + new (GetPointer(this->values[i])) Value(std::move(value)); + return true; + } + } + + return false; + } + + bool InsertOrAssign(const Key &key, Value &&value) { + /* Try to find and assign an existing value. */ + for (size_t i = 0; i < N; i++) { + if (this->keys[i] && this->keys[i].value() == key) { + GetReference(this->values[i]) = std::move(value); + return true; + } + } + + /* Find a free value. */ + for (size_t i = 0; i < N; i++) { + if (!this->keys[i]) { + this->keys[i] = key; + new (GetPointer(this->values[i])) Value(std::move(value)); + return true; + } + } + + return false; + } + + template + bool Emplace(const Key &key, Args&&... args) { + /* We can't emplace if the key is used. */ + if (this->Find(key) != nullptr) { + return false; + } + + /* Find a free value. */ + for (size_t i = 0; i < N; i++) { + this->keys[i] = key; + if (!this->keys[i]) { + this->keys[i] = key; + new (GetPointer(this->values[i])) Value(std::forward(args)...); + return true; + } + } + + return false; + } + }; + +}