From 6a67632af10abbed2fc8cb681ea64be1561a8c54 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Sun, 24 Jan 2016 22:39:05 -0600 Subject: [PATCH] Update RingBuffer - Add immediate read/write and some error checking asserts. --- src/xenia/base/ring_buffer.cc | 36 +++++++++++++++++++++++++++++++++++ src/xenia/base/ring_buffer.h | 27 ++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/src/xenia/base/ring_buffer.cc b/src/xenia/base/ring_buffer.cc index 9638d1301..b4e1013f8 100644 --- a/src/xenia/base/ring_buffer.cc +++ b/src/xenia/base/ring_buffer.cc @@ -17,6 +17,26 @@ namespace xe { RingBuffer::RingBuffer(uint8_t* buffer, size_t capacity) : buffer_(buffer), capacity_(capacity) {} +void RingBuffer::AdvanceRead(size_t count) { + if (read_offset_ + count < capacity_) { + read_offset_ += count; + } else { + size_t left_half = capacity_ - read_offset_; + size_t right_half = count - left_half; + read_offset_ = right_half; + } +} + +void RingBuffer::AdvanceWrite(size_t count) { + if (write_offset_ + count < capacity_) { + write_offset_ += count; + } else { + size_t left_half = capacity_ - write_offset_; + size_t right_half = count - left_half; + write_offset_ = right_half; + } +} + RingBuffer::ReadRange RingBuffer::BeginRead(size_t count) { count = std::min(count, capacity_); if (!count) { @@ -45,6 +65,14 @@ size_t RingBuffer::Read(uint8_t* buffer, size_t count) { return 0; } + // Sanity check: Make sure we don't read over the write offset. + if (read_offset_ < write_offset_) { + assert_true(read_offset_ + count <= write_offset_); + } else if (read_offset_ + count >= capacity_) { + size_t left_half = capacity_ - read_offset_; + assert_true(count - left_half <= write_offset_); + } + if (read_offset_ + count < capacity_) { std::memcpy(buffer, buffer_ + read_offset_, count); read_offset_ += count; @@ -65,6 +93,14 @@ size_t RingBuffer::Write(const uint8_t* buffer, size_t count) { return 0; } + // Sanity check: Make sure we don't write over the read offset. + if (write_offset_ < read_offset_) { + assert_true(write_offset_ + count <= read_offset_); + } else if (write_offset_ + count >= capacity_) { + size_t left_half = capacity_ - write_offset_; + assert_true(count - left_half <= read_offset_); + } + if (write_offset_ + count < capacity_) { std::memcpy(buffer_ + write_offset_, buffer, count); write_offset_ += count; diff --git a/src/xenia/base/ring_buffer.h b/src/xenia/base/ring_buffer.h index 9628c9c0c..b52f6afd0 100644 --- a/src/xenia/base/ring_buffer.h +++ b/src/xenia/base/ring_buffer.h @@ -14,6 +14,9 @@ #include #include +#include "xenia/base/assert.h" +#include "xenia/base/byte_order.h" + namespace xe { class RingBuffer { @@ -25,6 +28,7 @@ class RingBuffer { bool empty() const { return read_offset_ == write_offset_; } size_t read_offset() const { return read_offset_; } + uintptr_t read_ptr() const { return uintptr_t(buffer_) + read_offset_; } void set_read_offset(size_t offset) { read_offset_ = offset % capacity_; } size_t read_count() const { if (read_offset_ == write_offset_) { @@ -37,6 +41,7 @@ class RingBuffer { } size_t write_offset() const { return write_offset_; } + uintptr_t write_ptr() const { return uintptr_t(buffer_) + write_offset_; } void set_write_offset(size_t offset) { write_offset_ = offset % capacity_; } size_t write_count() const { if (read_offset_ == write_offset_) { @@ -48,6 +53,9 @@ class RingBuffer { } } + void AdvanceRead(size_t count); + void AdvanceWrite(size_t count); + struct ReadRange { const uint8_t* first; size_t first_length; @@ -63,12 +71,31 @@ class RingBuffer { return Read(reinterpret_cast(buffer), count); } + template + T Read(bool swap = false) { + static_assert(sizeof(T) <= 8, "Immediate read only supports basic types!"); + + T imm; + size_t read = Read(reinterpret_cast(&imm), sizeof(T)); + assert_true(read == sizeof(T)); + if (swap) { + imm = xe::byte_swap(imm); + } + + return imm; + } + size_t Write(const uint8_t* buffer, size_t count); template size_t Write(const T* buffer, size_t count) { return Write(reinterpret_cast(buffer), count); } + template + size_t Write(T& data) { + return Write(reinterpret_cast(&data), sizeof(T)); + } + private: uint8_t* buffer_ = nullptr; size_t capacity_ = 0;