From 5ed4eb72b631bb85be1e0e738904ceec005d0053 Mon Sep 17 00:00:00 2001 From: bcumming <bcumming@cscs.ch> Date: Tue, 2 Aug 2016 17:15:06 +0200 Subject: [PATCH] add double_buffer type --- src/util/double_buffer.hpp | 57 ++++++++++++++++++++++++++++++ tests/unit/CMakeLists.txt | 1 + tests/unit/test_double_buffer.cpp | 58 +++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 src/util/double_buffer.hpp create mode 100644 tests/unit/test_double_buffer.cpp diff --git a/src/util/double_buffer.hpp b/src/util/double_buffer.hpp new file mode 100644 index 00000000..34dceb7f --- /dev/null +++ b/src/util/double_buffer.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include <array> +#include <atomic> + +#include <util/debug.hpp> + +namespace nest { +namespace mc { +namespace util { + +template <typename T> +class double_buffer { +private: + std::atomic<int> index_; + std::array<T, 2> buffers_; + + int other_index() { + return index_ ? 0 : 1; + } + +public: + using value_type = T; + + double_buffer() : + index_(0) + {} + + double_buffer(double_buffer&&) = delete; + double_buffer(const double_buffer&) = delete; + double_buffer& operator=(const double_buffer&) = delete; + double_buffer& operator=(double_buffer&&) = delete; + + void exchange() { + index_ ^= 1; + } + + value_type& get() { + return buffers_[index_]; + } + + const value_type& get() const { + return buffers_[index_]; + } + + value_type& other() { + return buffers_[other_index()]; + } + + const value_type& other() const { + return buffers_[other_index()]; + } +}; + +} // namespace util +} // namespace mc +} // namespace nest diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index a3a2d553..81976dd2 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -11,6 +11,7 @@ set(HEADERS set(TEST_SOURCES # unit tests test_algorithms.cpp + test_double_buffer.cpp test_cell.cpp test_compartments.cpp test_event_queue.cpp diff --git a/tests/unit/test_double_buffer.cpp b/tests/unit/test_double_buffer.cpp new file mode 100644 index 00000000..1689cc2f --- /dev/null +++ b/tests/unit/test_double_buffer.cpp @@ -0,0 +1,58 @@ +#include "gtest.h" + +#include <util/double_buffer.hpp> + +// not much to test here: just test that values passed into the constructor +// are correctly stored in members +TEST(double_buffer, exchange_and_get) +{ + using namespace nest::mc::util; + + double_buffer<int> buf; + + buf.get() = 2134; + buf.exchange(); + buf.get() = 8990; + buf.exchange(); + + EXPECT_EQ(buf.get(), 2134); + EXPECT_EQ(buf.other(), 8990); + buf.exchange(); + EXPECT_EQ(buf.get(), 8990); + EXPECT_EQ(buf.other(), 2134); + buf.exchange(); + EXPECT_EQ(buf.get(), 2134); + EXPECT_EQ(buf.other(), 8990); +} + +TEST(double_buffer, assign_get_other) +{ + using namespace nest::mc::util; + + double_buffer<std::string> buf; + + buf.get() = "1"; + buf.other() = "2"; + + EXPECT_EQ(buf.get(), "1"); + EXPECT_EQ(buf.other(), "2"); +} + +TEST(double_buffer, non_pod) +{ + using namespace nest::mc::util; + + double_buffer<std::string> buf; + + buf.get() = "1"; + buf.other() = "2"; + + EXPECT_EQ(buf.get(), "1"); + EXPECT_EQ(buf.other(), "2"); + buf.exchange(); + EXPECT_EQ(buf.get(), "2"); + EXPECT_EQ(buf.other(), "1"); + buf.exchange(); + EXPECT_EQ(buf.get(), "1"); + EXPECT_EQ(buf.other(), "2"); +} -- GitLab