From f1e9c36f004febb4d983b37acd0c8c34a3fd5101 Mon Sep 17 00:00:00 2001 From: gibbed Date: Fri, 19 Jun 2015 09:50:54 -0500 Subject: [PATCH] Better ringbuffer implementation. --- src/xenia/base/ring_buffer.cc | 88 +++++++++++++++++++---------------- src/xenia/base/ring_buffer.h | 33 ++++++++++--- 2 files changed, 74 insertions(+), 47 deletions(-) diff --git a/src/xenia/base/ring_buffer.cc b/src/xenia/base/ring_buffer.cc index 7d9de5289..45225325b 100644 --- a/src/xenia/base/ring_buffer.cc +++ b/src/xenia/base/ring_buffer.cc @@ -9,59 +9,65 @@ #include "xenia/base/ring_buffer.h" +#include #include namespace xe { -RingBuffer::RingBuffer(uint8_t *raw_buffer, size_t size, size_t write_offset) - : raw_buffer_(raw_buffer), - size_(size), - write_offset_(write_offset) {} +RingBuffer::RingBuffer(uint8_t* raw_buffer, size_t size, size_t read_offset, size_t write_offset) + : raw_buffer_(raw_buffer) + , size_(size) + , read_offset_(read_offset) + , write_offset_(write_offset) {} -size_t RingBuffer::Write(uint8_t *buffer, size_t num_bytes) { - size_t bytes_written = 0; - size_t input_offset = 0; - size_t bytes_to_write = 0; - - // write offset -> end - bytes_to_write = - num_bytes < size_ - write_offset_ ? num_bytes : size_ - write_offset_; - - std::memcpy(raw_buffer_ + write_offset_, buffer, bytes_to_write); - input_offset = bytes_to_write; - write_offset_ += bytes_to_write; - - bytes_written += bytes_to_write; - - // Wraparound (begin -> num_bytes) - if (input_offset < num_bytes) { - bytes_to_write = num_bytes - input_offset; - - std::memcpy(raw_buffer_, buffer + input_offset, bytes_to_write); - write_offset_ = bytes_to_write; - - bytes_written += bytes_to_write; +size_t RingBuffer::Skip(size_t num_bytes) { + num_bytes = std::min(read_size(), num_bytes); + if (read_offset_ + num_bytes < size_) { + read_offset_ += num_bytes; + } else { + read_offset_ = num_bytes - (size_ - read_offset_); } - - return bytes_written; + return num_bytes; } -size_t RingBuffer::DistanceToOffset(size_t offset) { - // Make sure the offset is in range. - if (offset > size_) { - offset %= size_; +size_t RingBuffer::Read(uint8_t* buffer, size_t num_bytes) { + num_bytes = std::min(read_size(), num_bytes); + if (!num_bytes) { + return 0; } - if (offset < size_ && offset >= write_offset_) { - // Doesn't wraparound. - return offset - write_offset_; + if (read_offset_ + num_bytes < size_) { + std::memcpy(buffer, raw_buffer_ + read_offset_, num_bytes); + read_offset_ += num_bytes; } else { - // Wraparound. - size_t dist = size_ - write_offset_; - dist += offset; - - return dist; + size_t left_half = size_ - read_offset_; + size_t right_half = size_ - left_half; + std::memcpy(buffer, raw_buffer_ + read_offset_, left_half); + std::memcpy(buffer + left_half, raw_buffer_, right_half); + read_offset_ = right_half; } + + return num_bytes; +} + +size_t RingBuffer::Write(uint8_t* buffer, size_t num_bytes) { + num_bytes = std::min(num_bytes, write_size()); + if (!num_bytes) { + return 0; + } + + if (write_offset_ + num_bytes < size_) { + std::memcpy(raw_buffer_ + write_offset_, buffer, num_bytes); + write_offset_ += num_bytes; + } else { + size_t left_half = size_ - write_offset_; + size_t right_half = size_ - left_half; + std::memcpy(raw_buffer_ + write_offset_, buffer, left_half); + std::memcpy(raw_buffer_, buffer + left_half, right_half); + write_offset_ = right_half; + } + + return num_bytes; } } // namespace xe diff --git a/src/xenia/base/ring_buffer.h b/src/xenia/base/ring_buffer.h index 50c3e52f1..4d3830195 100644 --- a/src/xenia/base/ring_buffer.h +++ b/src/xenia/base/ring_buffer.h @@ -18,18 +18,39 @@ namespace xe { class RingBuffer { public: - RingBuffer(uint8_t *raw_buffer, size_t size, size_t write_offset = 0); + RingBuffer(uint8_t* raw_buffer, size_t size, size_t read_offset, size_t write_offset); - size_t Write(uint8_t *buffer, size_t num_bytes); + size_t Read(uint8_t* buffer, size_t num_bytes); + size_t Skip(size_t num_bytes); + size_t Write(uint8_t* buffer, size_t num_bytes); - size_t DistanceToOffset(size_t offset); - - void set_write_offset(size_t write_offset) { write_offset_ = write_offset; } + size_t read_offset() { return read_offset_; } size_t write_offset() { return write_offset_; } + size_t read_size() { + if (read_offset_ == write_offset_) { + return 0; + } + if (read_offset_ < write_offset_) { + return write_offset_ - read_offset_; + } + return (size_ - read_offset_) + write_offset_; + } + + size_t write_size() { + if (write_offset_ == read_offset_) { + return size_; + } + if (write_offset_ < read_offset_) { + return read_offset_ - write_offset_; + } + return (size_ - write_offset_) + read_offset_; + } + private: - uint8_t *raw_buffer_; + uint8_t* raw_buffer_; size_t size_; + size_t read_offset_; size_t write_offset_; };