You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

50 lines
2.3 KiB

/* MPSC: резерв управляющих сообщений, публикация слота и порядок каждого producer. */
#include "../src/audio_event_queue.h"
#include <thread>
#include <vector>
#include <cstdio>
#include <cstdlib>
#define REQUIRE(x) do { if (!(x)) { fprintf(stderr, "queue:%d %s\n", __LINE__, #x); abort(); } } while (0)
static std::atomic<bool> entered{false}, releaseCopy{false};
struct Item {
int producer = 0, sequence = 0;
bool block = false;
Item& operator=(const Item& other) {
if (other.block) { entered = true; while (!releaseCopy) std::this_thread::yield(); }
producer = other.producer; sequence = other.sequence; block = other.block; return *this;
}
};
int main() {
AudioEventQueue<Item, 16> queue;
Item item{};
for (int i = 0; i < 8; ++i) REQUIRE(queue.push(item));
REQUIRE(!queue.push(item));
for (int i = 0; i < 8; ++i) REQUIRE(queue.push(item, true));
REQUIRE(!queue.push(item, true));
for (int i = 0; i < 16; ++i) REQUIRE(queue.pop(item));
REQUIRE(!queue.pop(item));
std::thread first([&] { REQUIRE(queue.push({0, 123, true})); });
while (!entered) std::this_thread::yield();
REQUIRE(queue.push({1, 456, false}, true));
REQUIRE(!queue.pop(item)); // Второй слот опубликован, первый ещё принадлежит producer.
releaseCopy = true; first.join();
REQUIRE(queue.pop(item) && item.sequence == 123);
REQUIRE(queue.pop(item) && item.sequence == 456);
queue.reset();
constexpr int producers = 4, count = 20000;
std::vector<std::thread> threads;
for (int p = 0; p < producers; ++p) threads.emplace_back([&, p] {
for (int i = 0; i < count; ++i) while (!queue.push({p, i, false}, i % 7 == 0)) std::this_thread::yield();
});
int expected[producers]{};
for (int total = 0; total < producers * count;) {
if (!queue.pop(item)) { std::this_thread::yield(); continue; }
REQUIRE(queue.size() <= 16);
REQUIRE(item.producer >= 0 && item.producer < producers);
REQUIRE(item.sequence == expected[item.producer]++); ++total;
}
for (auto& thread : threads) thread.join();
REQUIRE(queue.size() == 0);
puts("audio queue: control reserve, unpublished slot, 80000 ordered messages PASS");
}