SummaryThe code operates three memory mapped file segments:just finishedcurrently activenext to writePotentially slow operations of closing just finished and opening next to write are done in a dedicated background thread.Concurrent writers know how much they need for a single operation and request that much from the segmented buffer at a time.The writer that fails to check out the required size finalizes the currently active file (writing a marker and requesting background thread to close the file and prepare one more).Source code on github: audit_buffer.hpp, the respective benchmark with usage demonstration: audit_benchmarks.cppThe central part (which I am primarily concerned about) is below. I would appreciate general feedback on the implementation (specifically, code simplification and speedup), and also ideas on getting rid of the spin-lock./** * Reserves the  requred space in the buffer, jumping to the next segment if required */std::shared_ptr<char> reserve(size_t required_size) {    if (unlikely(required_size > filesize_ - 1))        throw std::runtime_error(too much memory requested);    std::shared_ptr<log_segment> segment;    size_t pos = 0u;    do {        auto const segment_idx = segment_idx_.load(std::memory_order_acquire);        auto const psegment = &segments_[segment_idx % segments_.size()];        { // effectively std::atomic_load with custom spinlock            guard_t guard {mutex_};            segment = *psegment;        }        if (likely(segment)) {            pos = segment->reserve(required_size);            auto const last_pos = segment->size() - 1;            if (unlikely(pos < last_pos && (pos + required_size >= last_pos))) {                // it's this request that crossed the segment capacity                { // effectively std::atomic_store with custom spinlock                    guard_t guard {mutex_};                    psegment->reset();                }                request_next_segment_();                *(segment->memory() + pos) = 0x19; // End-of-Media                segment.reset();                // publish the next segment                segment_idx_.store(segment_idx + 1, std::memory_order_release);            }            else if (unlikely(pos >= last_pos)) {                segment.reset();            }        }    } while (unlikely(!segment));    return {segment, segment->memory() + pos}; // aliased shared_ptr to hold the segment alive}
Lock-free segmented shared memory buffer in C++
c++;c++11;c++14;lock free;c++17