fix graph and white background added
This commit is contained in:
@@ -29,7 +29,7 @@ class ShmRing {
|
||||
|
||||
// Pushes payload with overwrite-oldest policy on overflow.
|
||||
[[nodiscard]] auto push(std::span<const std::uint8_t> payload) -> bool;
|
||||
// Pops the next payload if available.
|
||||
// Pops the next unread payload; false only when none remains.
|
||||
[[nodiscard]] auto pop(std::vector<std::uint8_t>& payload) -> bool;
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "shm_ring.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <cerrno>
|
||||
@@ -220,41 +221,43 @@ auto ShmRing::pop(std::vector<std::uint8_t>& payload) -> bool {
|
||||
throw std::runtime_error("Ring is not open");
|
||||
}
|
||||
|
||||
const auto read_seq = header_->read_seq.load(std::memory_order_relaxed);
|
||||
const auto write_seq = header_->write_seq.load(std::memory_order_acquire);
|
||||
if (read_seq >= write_seq) {
|
||||
return false;
|
||||
while (true) {
|
||||
const auto read_seq = header_->read_seq.load(std::memory_order_relaxed);
|
||||
const auto write_seq = header_->write_seq.load(std::memory_order_acquire);
|
||||
if (read_seq >= write_seq) {
|
||||
return false;
|
||||
}
|
||||
// A lapped, torn or corrupt slot is skipped with the backlog behind the newest
|
||||
// payload, which is read next (latest-wins); a bad slot never stops the consumer.
|
||||
const auto resync = std::max(read_seq + 1U, write_seq - 1U);
|
||||
|
||||
auto* slot = slot_header(read_seq);
|
||||
if (std::atomic_ref(slot->sequence).load(std::memory_order_acquire) != read_seq + 1U) {
|
||||
advance_read_seq(resync); // Overwritten before this read (lapped).
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto payload_size = slot->payload_size;
|
||||
if (payload_size > header_->slot_size_bytes) {
|
||||
advance_read_seq(resync);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
payload.resize(payload_size);
|
||||
std::memcpy(payload.data(), slot_payload(slot), payload_size);
|
||||
|
||||
// Seqlock verify: if the slot sequence changed during the copy, the producer
|
||||
// lapped us mid-read and the payload is torn.
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
if (std::atomic_ref(slot->sequence).load(std::memory_order_acquire) != read_seq + 1U) {
|
||||
advance_read_seq(resync);
|
||||
continue;
|
||||
}
|
||||
|
||||
advance_read_seq(read_seq + 1U);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto* slot = slot_header(read_seq);
|
||||
if (std::atomic_ref(slot->sequence).load(std::memory_order_acquire) != read_seq + 1U) {
|
||||
// Slot not published for this seq, or already overwritten (lapped). Resync.
|
||||
advance_read_seq(write_seq);
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto payload_size = slot->payload_size;
|
||||
if (payload_size > header_->slot_size_bytes) {
|
||||
// Corrupt/torn slot: skip it (resync) rather than throw — a single bad slot
|
||||
// must never abort the long-running consumer.
|
||||
advance_read_seq(write_seq);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
payload.resize(payload_size);
|
||||
std::memcpy(payload.data(), slot_payload(slot), payload_size);
|
||||
|
||||
// Seqlock verify: if the slot sequence changed during the copy, the producer
|
||||
// lapped us mid-read and the payload is torn — discard and resync.
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
if (std::atomic_ref(slot->sequence).load(std::memory_order_acquire) != read_seq + 1U) {
|
||||
advance_read_seq(write_seq);
|
||||
return false;
|
||||
}
|
||||
|
||||
advance_read_seq(read_seq + 1U);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShmRing::advance_read_seq(std::uint64_t target) {
|
||||
|
||||
Reference in New Issue
Block a user