utils: RefCountedInternPool/RefCountedMap (#9284)

* utils: RefCountedInternPool/RefCountedMap

First, introduce RefCountedInternPool, a reference counted intern pool of
Slice<const T>. Just acquire() a slice that you want and you're guaranteed to
get exactly one canonical value-equal Slice<const T> back.

Additionally, introduce the concept of NullValue to RefCountedMap. A NullValue
defines what should be considered an uninitialized value; by default, it's the
default value of that type (0 for ints, nullptr for pointers, etc). This allows
us to lazily-initialize values in the map. A client can acquire() a bunch of
different resources which will be initialized only when get(factory) is called.
If a client attempts to get() a value without specifying a factory, and the
value is not initialized (i.e. equal to NullValue{}()), RefCountedMap will
panic.

* utils: add unit tests for ref-counted collections

* utils: remove C++20 features, fix memory issue

* utils: remove RefCounted from InternPool
This commit is contained in:
Eliza
2025-10-03 11:21:02 -07:00
committed by GitHub
parent 075726db8b
commit 7fe1ee3fd5
5 changed files with 406 additions and 31 deletions

View File

@@ -77,6 +77,12 @@ TEST(RefCountedMapTest, ValueType_GetsValue) {
EXPECT_EQ(v1const, 1);
}
TEST(RefCountedMapTest, ValueType_CanReleaseNullValue) {
RefCountedMap<KeyType, ValueType> map;
map.acquire(1);
map.release(1, [](ValueType& it) { ADD_FAILURE(); });
}
#ifdef GTEST_HAS_DEATH_TEST
TEST(RefCountedMapTest, ValueType_PanicsIfReleaseMissing) {
RefCountedMap<KeyType, ValueType> map;
@@ -87,6 +93,12 @@ TEST(RefCountedMapTest, ValueType_PanicsIfGetsMissing) {
RefCountedMap<KeyType, ValueType> map;
ASSERT_DEATH(map.get(1), "");
}
TEST(RefCountedMapTest, ValueType_PanicsIfGetsNullValue) {
RefCountedMap<KeyType, ValueType> map;
map.acquire(1);
ASSERT_DEATH(map.get(1), "");
}
#endif // GTEST_HAS_DEATH_TEST
/* Plain pointer types */
@@ -149,6 +161,12 @@ TEST(RefCountedMapTest, PlainPointerType_GetsValue) {
delete a1;
}
TEST(RefCountedMapTest, PlainPointerType_CanReleaseNullValue) {
RefCountedMap<KeyType, PlainPointerType> map;
map.acquire(1);
map.release(1, [](ValueType& it) { ADD_FAILURE(); });
}
#ifdef GTEST_HAS_DEATH_TEST
TEST(RefCountedMapTest, PlainPointerType_PanicsIfReleaseMissing) {
RefCountedMap<KeyType, PlainPointerType> map;
@@ -159,6 +177,12 @@ TEST(RefCountedMapTest, PlainPointerType_PanicsIfGetsMissing) {
RefCountedMap<KeyType, PlainPointerType> map;
ASSERT_DEATH(map.get(1), "");
}
TEST(RefCountedMapTest, PlainPointerType_PanicsIfGetsNullValue) {
RefCountedMap<KeyType, PlainPointerType> map;
map.acquire(1);
ASSERT_DEATH(map.get(1), "");
}
#endif // GTEST_HAS_DEATH_TEST
/* Smart pointer types */
@@ -214,6 +238,12 @@ TEST(RefCountedMapTest, SmartPointerType_GetsValue) {
EXPECT_EQ(v1const, 1);
}
TEST(RefCountedMapTest, SmartPointerType_CanReleaseNullValue) {
RefCountedMap<KeyType, SmartPointerType> map;
map.acquire(1);
map.release(1, [](ValueType& it) { ADD_FAILURE(); });
}
#ifdef GTEST_HAS_DEATH_TEST
TEST(RefCountedMapTest, SmartPointerType_PanicsIfReleaseMissing) {
RefCountedMap<KeyType, SmartPointerType> map;
@@ -224,4 +254,10 @@ TEST(RefCountedMapTest, SmartPointerType_PanicsIfGetsMissing) {
RefCountedMap<KeyType, SmartPointerType> map;
ASSERT_DEATH(map.get(1), "");
}
TEST(RefCountedMapTest, SmartPointerType_PanicsIfGetsNullValue) {
RefCountedMap<KeyType, SmartPointerType> map;
map.acquire(1);
ASSERT_DEATH(map.get(1), "");
}
#endif // GTEST_HAS_DEATH_TEST