[libc-commits] [libc] d7c920e - [libc][BlockStore] Add back, pop_back and empty methods

Alex Brachet via libc-commits libc-commits at lists.llvm.org
Tue Mar 15 08:13:58 PDT 2022


Author: Alex Brachet
Date: 2022-03-15T15:11:57Z
New Revision: d7c920e1a0eace5429e7bd191c0ec77da478f800

URL: https://github.com/llvm/llvm-project/commit/d7c920e1a0eace5429e7bd191c0ec77da478f800
DIFF: https://github.com/llvm/llvm-project/commit/d7c920e1a0eace5429e7bd191c0ec77da478f800.diff

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

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D121656

Added: 
    

Modified: 
    libc/src/__support/CPP/blockstore.h
    libc/test/src/__support/CPP/blockstore_test.cpp

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/CPP/blockstore.h b/libc/src/__support/CPP/blockstore.h
index b4c5998814820..a75f9311c6d95 100644
--- a/libc/src/__support/CPP/blockstore.h
+++ b/libc/src/__support/CPP/blockstore.h
@@ -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 @@ class BlockStore {
   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 @@ class BlockStore {
     *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);

diff  --git a/libc/test/src/__support/CPP/blockstore_test.cpp b/libc/test/src/__support/CPP/blockstore_test.cpp
index 1f44bcf7aaf07..a9f00283dad55 100644
--- a/libc/test/src/__support/CPP/blockstore_test.cpp
+++ b/libc/test/src/__support/CPP/blockstore_test.cpp
@@ -41,6 +41,27 @@ class LlvmLibcBlockStoreTest : public __llvm_libc::testing::Test {
     __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>();
+}


        


More information about the libc-commits mailing list