blob: 25b28793cd5f91677d00443de96bc86624ea1d01 [file] [log] [blame]
// Copyright 2025 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "buffer.h"
#include <zircon/assert.h>
size_t DurableBuffer::BytesAllocated() const {
return bytes_allocated_.load(std::memory_order_relaxed);
}
void DurableBuffer::Set(std::span<uint8_t> data) {
data_ = data;
bytes_allocated_.store(0, std::memory_order_relaxed);
}
size_t DurableBuffer::MaxSize() const { return data_.size(); }
void DurableBuffer::Reset() { bytes_allocated_.store(0, std::memory_order_relaxed); }
uint64_t* DurableBuffer::AllocRecord(size_t num_bytes) {
ZX_DEBUG_ASSERT((num_bytes & 7) == 0);
// We need to use a cmpxchg loop here instead of a fetch_add. Since we don't have a
// commit pointer and rely on the writer to actually write the bytes, we don't want to modify the
// bytes_allocated unless we know the writer is also going to be able to write to the allocated
// space.
uint64_t allocated = bytes_allocated_.load(std::memory_order_relaxed);
while (true) {
const uint64_t desired = allocated + num_bytes;
if (unlikely(desired > data_.size())) {
return nullptr;
}
const bool success = bytes_allocated_.compare_exchange_weak(
allocated, desired, std::memory_order_relaxed, std::memory_order_relaxed);
if (success) {
uint8_t* ptr = data_.data() + allocated;
return reinterpret_cast<uint64_t*>(ptr);
}
}
}