From cab874305f4ee88a7c0ec06b5bdf3a4f90a1b041 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Sun, 17 Jul 2016 20:43:18 -0400 Subject: [PATCH] add PagedBuffer; use own main() for tests --- src/core/PagedBuffer.h | 79 ++++++++++++++++++++++++++++++++++++ test/src/main.cc | 9 ++++ test/src/test_PagedBuffer.cc | 45 ++++++++++++++++++++ wscript | 3 +- 4 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 src/core/PagedBuffer.h create mode 100644 test/src/main.cc create mode 100644 test/src/test_PagedBuffer.cc diff --git a/src/core/PagedBuffer.h b/src/core/PagedBuffer.h new file mode 100644 index 0000000..0ba04b0 --- /dev/null +++ b/src/core/PagedBuffer.h @@ -0,0 +1,79 @@ +#ifndef PAGEDBUFFER_H +#define PAGEDBUFFER_H + +#include "System.h" +#include +#include + +template +class PagedBuffer +{ +public: + /** + * Create a PagedBuffer. + * + * Note: sizeof(T) must be a power of 2. A single page can hold + * System::page_size / sizeof(T) entries. + */ + PagedBuffer() + { + static_assert((sizeof(T) & (sizeof(T) - 1)) == 0, + "sizeof(T) must be a power of 2"); + m_size = 0u; + } + + ~PagedBuffer() + { + for (auto it : m_pages) + { + System::free_pages(it, 1); + } + } + + const T & operator[](unsigned int index) const + { + while (index >= (m_pages.size() * n_per_page())) + { + grow(); + } + return m_pages[page_index(index)][index_in_page(index)]; + } + + T & operator[](unsigned int index) + { + while (index >= (m_pages.size() * n_per_page())) + { + grow(); + } + return m_pages[page_index(index)][index_in_page(index)]; + } + + size_t size() { return m_size; } + +protected: + unsigned int n_per_page() + { + return System::page_size / sizeof(T); + } + + unsigned int page_index(unsigned int index) + { + return index / n_per_page(); + } + + unsigned int index_in_page(unsigned int index) + { + return index % n_per_page(); + } + + void grow() + { + m_pages.push_back((T *)System::alloc_pages(1)); + m_size += n_per_page(); + } + + std::vector m_pages; + unsigned long m_size; +}; + +#endif diff --git a/test/src/main.cc b/test/src/main.cc new file mode 100644 index 0000000..55fc515 --- /dev/null +++ b/test/src/main.cc @@ -0,0 +1,9 @@ +#include "gtest/gtest.h" +#include "System.h" + +int main(int argc, char * argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + System::init(); + return RUN_ALL_TESTS(); +} diff --git a/test/src/test_PagedBuffer.cc b/test/src/test_PagedBuffer.cc new file mode 100644 index 0000000..4d1bb93 --- /dev/null +++ b/test/src/test_PagedBuffer.cc @@ -0,0 +1,45 @@ +#include "gtest/gtest.h" +#include "PagedBuffer.h" + +struct X +{ + uint64_t a; + uint32_t b; + uint32_t c; +}; + +struct Y +{ + uint32_t a; + uint32_t b; +}; + +TEST(PagedBufferTest, empty_paged_buffer_has_size_0) +{ + PagedBuffer pbx; + ASSERT_EQ(0u, pbx.size()); + + PagedBuffer pby; + ASSERT_EQ(0u, pby.size()); +} + +TEST(PagedBufferTest, allows_adding_elements) +{ + PagedBuffer pbx; + + for (uint32_t i = 0u; i < 1000u; i++) + { + X x = {i, 2u * i, 4u * i}; + pbx[i] = x; + } + + ASSERT_GE(pbx.size(), 1000u); + + for (uint32_t i = 0u; i < 1000u; i++) + { + const X & x = pbx[i]; + ASSERT_EQ(i, x.a); + ASSERT_EQ(2u * i, x.b); + ASSERT_EQ(4u * i, x.c); + } +} diff --git a/wscript b/wscript index d293d99..137488a 100644 --- a/wscript +++ b/wscript @@ -33,8 +33,7 @@ def build(bld): test_libs += ["pthread"] test_sources = bld.path.ant_glob("src/core/**/*.cc") test_sources += bld.path.ant_glob("test/src/**/*.cc") - test_sources += ["libs/googletest/src/gtest-all.cc", - "libs/googletest/src/gtest_main.cc"] + test_sources += ["libs/googletest/src/gtest-all.cc"] test_includes = ["src/core"] test_includes += ["libs/googletest/include", "libs/googletest"] bld(features = "cxx cxxprogram",