A C++ library for logging very fast and without allocating.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 

139 lignes
3.2 KiB

#include <thread>
#include "catch2/catch_all.hpp"
#include "../LibSnugLog/include/disruptor.h"
struct strategy {
static constexpr overflow_response_t on_overflow = overflow_response_t::must_wait;
void wait() {}
};
TEST_CASE("Disruptor works sequentially") {
std::array<char, 8192> buffer{};
disruptor<strategy> v{buffer.data(), buffer.size()};
SECTION("117") {
auto W = v.reserve_write(100);
v[W.start] = 117;
v.conclude_write(W);
auto R = v.reserve_read();
REQUIRE(v[R.start]== 117);
v.conclude_read(R);
}
SECTION("12") {
{
auto W = v.reserve_write(6);
v[W.start] = 12;
v.conclude_write(W);
auto R = v.reserve_read();
REQUIRE(v[R.start]== 12);
v.conclude_read(R);
}
{
auto W = v.reserve_write(6);
v[W.start] = 8;
v.conclude_write(W);
auto R = v.reserve_read();
REQUIRE(v[R.start]== 8);
v.conclude_read(R);
}
}
SECTION("Disruptor loop around") {
std::multiset<char> mset;
for(int i = 0; i != 255; i++) {
auto W = v.reserve_write(100);
v[W.start] = (char)i;
for(size_t idx = W.start; idx != W.end; idx = (idx+1)%v.size()) {
v[idx] = (char)i;
}
v.conclude_write(W);
auto R = v.reserve_read();
for(size_t idx = R.start; idx != R.end; idx = (idx+1)%v.size()) {
mset.insert(v[idx]);
}
v.conclude_read(R);
}
for(int i = 0; i != 255; i++) {
REQUIRE(mset.count((char)i) == 100);
}
}
SECTION("Disruptor concurrent odd vs even") {
std::atomic<bool> trigger = false;
std::multiset<char> mset;
std::stringstream continuity;
int acc = 0;
for(int i = 0; i<= 255; i++) {
acc+=i;
}
std::thread reader([&](){
int cnt = 0;
while (cnt != acc) {
auto R = v.reserve_read();
for (size_t idx = R.start; idx != R.end; idx = (idx + 1) % v.size()) {
mset.insert(v[idx]);
continuity << (char)v[idx];
}
v.conclude_read(R);
cnt += (R.end > R.start) * (R.end - R.start)
+ (R.end < R.start) * (v.size() - R.start + R.end);
}
});
std::thread even([&]() {
while(!trigger.load());
for (int i = 2; i <= 255; i += 2) {
auto W = v.reserve_write(i);
v[W.start] = (char) i;
for (size_t idx = W.start; idx != W.end; idx = (idx + 1) % v.size()) {
v[idx] = (char) i;
}
v.conclude_write(W);
}
});
std::thread odd([&]() {
while(!trigger.load());
for (int i = 1; i <= 255; i += 2) {
auto W = v.reserve_write(i);
v[W.start] = (char) i;
for (size_t idx = W.start; idx != W.end; idx = (idx + 1) % v.size()) {
v[idx] = (char) i;
}
v.conclude_write(W);
}
});
// byte received count test
trigger.store(true);
reader.join(); even.join(); odd.join();
for(int i = 1; i <= 255; i++) {
REQUIRE(mset.count((char)i) == i);
}
// Continuity tests
int changes = 0;
auto str = continuity.str();
char current = *str.begin();
auto it = str.begin();
for(;it != str.end();) {
while(it != str.end() && *it == current) {++it;}
changes += 1;
current = *it;
}
REQUIRE(changes == 255);
}
}
TEST_CASE("Fails if buffer too small") {
REQUIRE_THROWS_AS(disruptor<OverflowWait>(nullptr, page_size), disruptor_exception);
}
TEST_CASE("Fails if buffer size is 0") {
REQUIRE_THROWS_AS(disruptor<OverflowWait>(nullptr, 0), disruptor_exception);
}