From 3adf0df9c7851a42840809b04222cb3efa12dc45 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Tue, 25 Jun 2019 00:32:53 -0500 Subject: [PATCH] [ox/ptrarith] Fix NodeBuffer to properly handle removing only node --- deps/ox/src/ox/ptrarith/CMakeLists.txt | 2 + deps/ox/src/ox/ptrarith/nodebuffer.hpp | 43 +++++++++---- deps/ox/src/ox/ptrarith/ptr.hpp | 2 +- deps/ox/src/ox/ptrarith/test/CMakeLists.txt | 11 ++++ deps/ox/src/ox/ptrarith/test/tests.cpp | 69 +++++++++++++++++++++ 5 files changed, 113 insertions(+), 14 deletions(-) create mode 100644 deps/ox/src/ox/ptrarith/test/CMakeLists.txt create mode 100644 deps/ox/src/ox/ptrarith/test/tests.cpp diff --git a/deps/ox/src/ox/ptrarith/CMakeLists.txt b/deps/ox/src/ox/ptrarith/CMakeLists.txt index 0ca4d29b..a3a44531 100644 --- a/deps/ox/src/ox/ptrarith/CMakeLists.txt +++ b/deps/ox/src/ox/ptrarith/CMakeLists.txt @@ -5,3 +5,5 @@ install( DESTINATION include/ox/ptrarith ) + +add_subdirectory(test) diff --git a/deps/ox/src/ox/ptrarith/nodebuffer.hpp b/deps/ox/src/ox/ptrarith/nodebuffer.hpp index 980a53b2..776e5aae 100644 --- a/deps/ox/src/ox/ptrarith/nodebuffer.hpp +++ b/deps/ox/src/ox/ptrarith/nodebuffer.hpp @@ -19,7 +19,7 @@ class __attribute__((packed)) NodeBuffer { public: struct __attribute__((packed)) Header { - ox::LittleEndian size = sizeof(Header); + ox::LittleEndian size = sizeof(Header); // capacity ox::LittleEndian bytesUsed = sizeof(Header); ox::LittleEndian firstItem = 0; }; @@ -67,7 +67,7 @@ class __attribute__((packed)) NodeBuffer { return m_current; } - bool valid() const noexcept { + [[nodiscard]] bool valid() const noexcept { return m_current.valid(); } @@ -113,22 +113,29 @@ class __attribute__((packed)) NodeBuffer { template Ptr dataOf(ItemPtr); - ItemPtr prev(Item *item); + [[nodiscard]] ItemPtr prev(Item *item); - ItemPtr next(Item *item); + [[nodiscard]] ItemPtr next(Item *item); - ItemPtr ptr(size_t offset); + [[nodiscard]] ItemPtr ptr(size_t offset); - ItemPtr ptr(void *item); + [[nodiscard]] ItemPtr ptr(void *item); - ItemPtr malloc(size_t size); + [[nodiscard]] ItemPtr malloc(size_t size); - Error free(ItemPtr item); + [[nodiscard]] ox::Error free(ItemPtr item); - bool valid(size_t maxSize); + [[nodiscard]] bool valid(size_t maxSize); - Error setSize(size_t size); + /** + * Set size, capacity. + */ + [[nodiscard]] ox::Error setSize(size_t size); + /** + * Get size, capacity. + * @return capacity + */ size_t size(); /** @@ -278,16 +285,26 @@ Error NodeBuffer::free(ItemPtr item) { auto prev = this->prev(item); auto next = this->next(item); if (prev.valid() && next.valid()) { - prev->next = next.offset(); - next->prev = prev.offset(); + if (next != item) { + prev->next = next.offset(); + next->prev = prev.offset(); + if (item.offset() == m_header.firstItem) { + m_header.firstItem = next; + } + } else { + // only one item, null out first + oxTrace("ox::ptrarith::NodeBuffer::free") << "Nulling out firstItem."; + m_header.firstItem = 0; + } } else { if (!prev.valid()) { oxTrace("ox::ptrarith::NodeBuffer::free::fail") << "NodeBuffer free failed due to invalid prev element pointer:" << prev.offset(); + return OxError(1); } if (!next.valid()) { oxTrace("ox::ptrarith::NodeBuffer::free::fail") << "NodeBuffer free failed due to invalid next element pointer:" << next.offset(); + return OxError(1); } - return OxError(1); } m_header.bytesUsed -= item.size(); return OxError(0); diff --git a/deps/ox/src/ox/ptrarith/ptr.hpp b/deps/ox/src/ox/ptrarith/ptr.hpp index 3bbae10c..6c9154e2 100644 --- a/deps/ox/src/ox/ptrarith/ptr.hpp +++ b/deps/ox/src/ox/ptrarith/ptr.hpp @@ -31,7 +31,7 @@ class Ptr { inline Ptr(void *dataStart, size_t dataSize, size_t itemStart, size_t itemSize = sizeof(T), size_t itemTypeSize = sizeof(T)); - inline bool valid() const; + [[nodiscard]] inline bool valid() const; inline size_t size() const; diff --git a/deps/ox/src/ox/ptrarith/test/CMakeLists.txt b/deps/ox/src/ox/ptrarith/test/CMakeLists.txt new file mode 100644 index 00000000..d9c69203 --- /dev/null +++ b/deps/ox/src/ox/ptrarith/test/CMakeLists.txt @@ -0,0 +1,11 @@ +add_executable( + PtrArithTests + tests.cpp +) + +target_link_libraries( + PtrArithTests + OxStd +) + +add_test("Test\\ PtrArith::setSize" PtrArithTests PtrArith::setSize) diff --git a/deps/ox/src/ox/ptrarith/test/tests.cpp b/deps/ox/src/ox/ptrarith/test/tests.cpp new file mode 100644 index 00000000..991187a8 --- /dev/null +++ b/deps/ox/src/ox/ptrarith/test/tests.cpp @@ -0,0 +1,69 @@ +/* + * Copyright 2015 - 2018 gtalent2@gmail.com + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// make sure asserts are enabled for the test file +#undef NDEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace std; +using namespace ox; + +template +struct __attribute__((packed)) NodeType: public ox::ptrarith::Item { + public: + int i = 0; + size_t fullSize() const { + return this->size() + sizeof(*this); + } +}; + +map tests = { + { + { + "PtrArith::setSize", + [](string) { + using BuffPtr_t = uint32_t; + std::vector buff(5 * ox::units::MB); + auto buffer = new (buff.data()) ox::ptrarith::NodeBuffer>(buff.size()); + auto a1 = buffer->malloc(50); + auto a2 = buffer->malloc(50); + oxAssert(buffer->free(a1), "Free failed."); + oxAssert(buffer->free(a2), "Free failed."); + oxAssert(buffer->setSize(buffer->size() - buffer->available()), "Resize failed."); + return 0; + } + }, + }, +}; + +int main(int argc, const char **args) { + int retval = -1; + if (argc > 1) { + auto testName = args[1]; + string testArg = ""; + if (args[2]) { + testArg = args[2]; + } + if (tests.find(testName) != tests.end()) { + retval = tests[testName](testArg); + } + } + return retval; +}