[libc][BlockStore] Add back, pop_back and empty methods

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D121656
This commit is contained in:
Alex Brachet 2022-03-15 15:11:57 +00:00
parent 4633c02eb0
commit d7c920e1a0
2 changed files with 77 additions and 0 deletions

View File

@ -13,6 +13,11 @@
#include <stdint.h>
#include <stdlib.h>
// TODO: fix our assert.h to make it useable
#define assert(x) \
if (!(x)) \
__builtin_trap()
namespace __llvm_libc {
namespace cpp {
@ -40,6 +45,22 @@ protected:
Block *current = &first;
size_t fill_count = 0;
struct Pair {
Block *first, *second;
};
Pair getLastBlocks() {
if (REVERSE_ORDER)
return {current, current->next};
Block *prev = nullptr;
Block *curr = &first;
for (; curr->next; prev = curr, curr = curr->next)
;
assert(curr == current);
return {curr, prev};
}
Block *getLastBlock() { return getLastBlocks().first; }
public:
constexpr BlockStore() = default;
~BlockStore() = default;
@ -113,6 +134,31 @@ public:
*ptr = value;
}
T &back() {
return *reinterpret_cast<T *>(getLastBlock()->data +
sizeof(T) * (fill_count - 1));
}
void pop_back() {
fill_count--;
if (fill_count || current == &first)
return;
auto [last, prev] = getLastBlocks();
if (REVERSE_ORDER) {
assert(last == current);
current = current->next;
} else {
assert(prev->next == last);
current = prev;
current->next = nullptr;
}
if (last != &first)
::free(last);
fill_count = BLOCK_SIZE;
}
bool empty() const { return current == &first && !fill_count; }
iterator begin() {
if (REVERSE_ORDER)
return iterator(current, fill_count);

View File

@ -41,6 +41,27 @@ public:
__llvm_libc::cpp::BlockStore<Element, BLOCK_SIZE, REVERSE>::destroy(
&block_store);
}
template <bool REVERSE> void back_test() {
using __llvm_libc::cpp::BlockStore;
BlockStore<int, 4, REVERSE> block_store;
for (int i = 0; i < 20; i++)
block_store.push_back(i);
for (int i = 19; i >= 0; i--, block_store.pop_back())
ASSERT_EQ(block_store.back(), i);
block_store.destroy(&block_store);
}
template <bool REVERSE> void empty_test() {
using __llvm_libc::cpp::BlockStore;
BlockStore<int, 2, REVERSE> block_store;
ASSERT_TRUE(block_store.empty());
block_store.push_back(1);
for (int i = 0; i < 10; i++, block_store.push_back(1))
ASSERT_FALSE(block_store.empty());
block_store.destroy(&block_store);
}
};
TEST_F(LlvmLibcBlockStoreTest, PopulateAndIterate4) {
@ -66,3 +87,13 @@ TEST_F(LlvmLibcBlockStoreTest, PopulateAndIterateReverse8) {
TEST_F(LlvmLibcBlockStoreTest, PopulateAndIterateReverse10) {
populate_and_iterate<4, 10, true>();
}
TEST_F(LlvmLibcBlockStoreTest, Back) {
back_test<false>();
back_test<true>();
}
TEST_F(LlvmLibcBlockStoreTest, Empty) {
empty_test<false>();
empty_test<true>();
}