93 lines
2.4 KiB
C++
93 lines
2.4 KiB
C++
#include <boost/test/unit_test.hpp>
|
|
|
|
#include <array>
|
|
#include <atomic>
|
|
#include <barrier>
|
|
#include <memory>
|
|
#include <thread>
|
|
|
|
#include "detail/render_snapshot.hpp"
|
|
|
|
|
|
namespace {
|
|
|
|
struct snapshot {
|
|
std::atomic<int> &live;
|
|
std::array<int, 64> samples{};
|
|
explicit snapshot(std::atomic<int> &count, int value = 0)
|
|
: live(count) {
|
|
++live;
|
|
samples.fill(value);
|
|
}
|
|
~snapshot() {
|
|
--live;
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(sonus_snapshots_are_reclaimed_without_rendering) {
|
|
auto live = std::atomic<int>{0};
|
|
auto state = sonus::detail::render_snapshot<snapshot>{};
|
|
for (auto index = 0; index < 1000; ++index) {
|
|
state.publish(std::make_unique<snapshot>(live, index));
|
|
BOOST_TEST(live.load() == 1);
|
|
}
|
|
state.publish(nullptr);
|
|
BOOST_TEST(live.load() == 0);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(sonus_snapshots_outlive_readers_and_are_collected_on_control_thread) {
|
|
auto live = std::atomic<int>{0};
|
|
auto state = sonus::detail::render_snapshot<snapshot>{};
|
|
state.publish(std::make_unique<snapshot>(live, 42));
|
|
{
|
|
auto first = state.read();
|
|
state.publish(std::make_unique<snapshot>(live, 43));
|
|
{
|
|
auto second = state.read();
|
|
state.publish(std::make_unique<snapshot>(live, 44));
|
|
state.collect();
|
|
BOOST_TEST(live.load() == 3);
|
|
BOOST_TEST(second.get()->samples.front() == 43);
|
|
}
|
|
state.collect();
|
|
BOOST_TEST(live.load() == 3);
|
|
BOOST_TEST(first.get()->samples.back() == 42);
|
|
}
|
|
BOOST_TEST(live.load() == 3);
|
|
state.collect();
|
|
BOOST_TEST(live.load() == 1);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(sonus_snapshot_publication_overlaps_readers) {
|
|
auto live = std::atomic<int>{0};
|
|
auto state = sonus::detail::render_snapshot<snapshot>{};
|
|
state.publish(std::make_unique<snapshot>(live));
|
|
auto start = std::barrier{3};
|
|
auto failed = std::atomic<bool>{false};
|
|
auto reader = [&] {
|
|
start.arrive_and_wait();
|
|
for (auto index = 0; index < 20000; ++index) {
|
|
auto guard = state.read();
|
|
auto const *value = guard.get();
|
|
for (auto sample : value->samples) {
|
|
if (sample != value->samples.front()) {
|
|
failed.store(true);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
auto first = std::thread{reader};
|
|
auto second = std::thread{reader};
|
|
start.arrive_and_wait();
|
|
for (auto index = 0; index < 20000; ++index) {
|
|
state.publish(std::make_unique<snapshot>(live, index));
|
|
}
|
|
first.join();
|
|
second.join();
|
|
state.collect();
|
|
BOOST_TEST(!failed.load());
|
|
BOOST_TEST(live.load() == 1);
|
|
}
|