summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--asl/handle_pool/BUILD.bazel33
-rw-r--r--asl/handle_pool/index_pool.hpp56
-rw-r--r--asl/handle_pool/index_pool_tests.cpp49
3 files changed, 138 insertions, 0 deletions
diff --git a/asl/handle_pool/BUILD.bazel b/asl/handle_pool/BUILD.bazel
new file mode 100644
index 0000000..e5048d3
--- /dev/null
+++ b/asl/handle_pool/BUILD.bazel
@@ -0,0 +1,33 @@
+# Copyright 2025 Steven Le Rouzic
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+package(
+ default_applicable_licenses = ["//:license"],
+)
+
+cc_library(
+ name = "index_pool",
+ hdrs = [
+ "index_pool.hpp",
+ ],
+ deps = [
+ "//asl/memory",
+ "//asl/memory:allocator",
+ "//asl/base",
+ "//asl/containers:chunked_buffer",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+cc_test(
+ name = "index_pool_tests",
+ srcs = [
+ "index_pool_tests.cpp",
+ ],
+ deps = [
+ ":index_pool",
+ "//asl/tests:utils",
+ "//asl/testing",
+ ],
+)
diff --git a/asl/handle_pool/index_pool.hpp b/asl/handle_pool/index_pool.hpp
new file mode 100644
index 0000000..f874386
--- /dev/null
+++ b/asl/handle_pool/index_pool.hpp
@@ -0,0 +1,56 @@
+// Copyright 2025 Steven Le Rouzic
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+#include "asl/base/integers.hpp"
+#include "asl/base/meta.hpp"
+#include "asl/containers/chunked_buffer.hpp"
+#include "asl/memory/allocator.hpp"
+
+namespace asl
+{
+
+// @Todo Uniquely represented for the handle?
+
+template<
+ int kIndexBits_,
+ int kGenBits_,
+ typename UserType_ = empty,
+ int kUserBits_ = 0
+>
+requires (kIndexBits_ > 0 && kGenBits_ > 0 && kUserBits_ >= 0)
+struct index_pool_config
+{
+ static constexpr bool kHasUser = !same_as<UserType_, empty>;
+
+ using UserType = UserType_;
+ using PrimitiveUserType = smallest_unsigned_integer_type_for_width<size_of<UserType> * 8>;
+
+ static_assert(trivially_copy_constructible<UserType>);
+ static_assert(size_of<UserType> == size_of<PrimitiveUserType>, "UserType should be of size 1, 2 or 4");
+
+ static constexpr int kUserBits = []() static -> int {
+ if constexpr (!kHasUser) { return 0; };
+ return kUserBits_ == 0 ? size_of<UserType> * 8 : kUserBits_;
+ }();
+
+ static_assert(kUserBits <= size_of<UserType> * 8);
+
+ static constexpr int kIndexBits = kIndexBits_;
+ static constexpr int kGenBits = kGenBits_;
+
+ static_assert(kIndexBits + kGenBits + kUserBits <= 63);
+
+ using HandleType = smallest_unsigned_integer_type_for_width<kIndexBits + kGenBits + kUserBits + 1>;
+
+ static constexpr int kGenShift = kIndexBits;
+ static constexpr int kUserShift = kIndexBits + kGenBits;
+
+ static constexpr HandleType kValidMask = HandleType{1} << (size_of<HandleType> * 8 - 1);
+ static constexpr HandleType kIndexMask = (HandleType{1} << kIndexBits) - 1;
+ static constexpr HandleType kGenMask = ((HandleType{1} << kGenBits) - 1) << kGenShift;
+ static constexpr HandleType kUserMask = ((HandleType{1} << kUserBits) - 1) << kUserShift;
+};
+
+} // namespace asl
+
diff --git a/asl/handle_pool/index_pool_tests.cpp b/asl/handle_pool/index_pool_tests.cpp
new file mode 100644
index 0000000..b49d0b9
--- /dev/null
+++ b/asl/handle_pool/index_pool_tests.cpp
@@ -0,0 +1,49 @@
+// Copyright 2025 Steven Le Rouzic
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+#include "asl/testing/testing.hpp"
+#include "asl/handle_pool/index_pool.hpp"
+
+enum Flags: uint8_t {
+ kFlag0 = 0,
+ kFlag1 = 1,
+ kFlag2 = 2,
+};
+
+using Cfg1 = asl::index_pool_config<4, 3>;
+static_assert(!Cfg1::kHasUser);
+static_assert(Cfg1::kUserBits == 0);
+static_assert(asl::same_as<Cfg1::HandleType, uint8_t>);
+static_assert(Cfg1::kValidMask == uint8_t{0x80});
+static_assert(Cfg1::kIndexMask == uint8_t{0x0f});
+static_assert(Cfg1::kGenMask == uint8_t{0x70});
+static_assert(Cfg1::kGenShift == 4);
+
+using Cfg2 = asl::index_pool_config<5, 5, Flags>;
+static_assert(Cfg2::kHasUser);
+static_assert(Cfg2::kUserBits == 8);
+static_assert(asl::same_as<Cfg2::PrimitiveUserType, uint8_t>);
+static_assert(asl::same_as<Cfg2::HandleType, uint32_t>);
+static_assert(Cfg2::kValidMask == uint32_t{0x8000'0000});
+static_assert(Cfg2::kIndexMask == uint32_t{0x0000'001f});
+static_assert(Cfg2::kGenMask == uint32_t{0x0000'03e0});
+static_assert(Cfg2::kUserMask == uint32_t{0x0003'fc00});
+static_assert(Cfg2::kGenShift == 5);
+static_assert(Cfg2::kUserShift == 10);
+
+using Cfg3 = asl::index_pool_config<5, 6, Flags, 4>;
+static_assert(Cfg3::kHasUser);
+static_assert(Cfg3::kUserBits == 4);
+static_assert(asl::same_as<Cfg3::PrimitiveUserType, uint8_t>);
+static_assert(asl::same_as<Cfg3::HandleType, uint16_t>);
+static_assert(Cfg3::kValidMask == uint16_t{0x8000});
+static_assert(Cfg3::kIndexMask == uint16_t{0x001f});
+static_assert(Cfg3::kGenMask == uint16_t{0x07e0});
+static_assert(Cfg3::kUserMask == uint16_t{0x7800});
+static_assert(Cfg3::kGenShift == 5);
+static_assert(Cfg3::kUserShift == 11);
+
+ASL_TEST(test)
+{
+}