From 2923fe8ad1ebfae017ee315bf9c9d2488b650ea0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Sat, 18 Feb 2017 13:31:49 -0800 Subject: [PATCH] Cleanup. --- include/bx/inline/ringbuffer.inl | 275 ++++++++++++++++++++++++++++ include/bx/ringbuffer.h | 299 ++++++++----------------------- 2 files changed, 345 insertions(+), 229 deletions(-) create mode 100644 include/bx/inline/ringbuffer.inl diff --git a/include/bx/inline/ringbuffer.inl b/include/bx/inline/ringbuffer.inl new file mode 100644 index 0000000..844d5b7 --- /dev/null +++ b/include/bx/inline/ringbuffer.inl @@ -0,0 +1,275 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#ifndef BX_RINGBUFFER_H_HEADER_GUARD +# error "Must be included from bx/ringbuffer.h!" +#endif // BX_RINGBUFFER_H_HEADER_GUARD + +namespace bx +{ + inline RingBufferControl::RingBufferControl(uint32_t _size) + : m_size(_size) + , m_current(0) + , m_write(0) + , m_read(0) + { + } + + inline RingBufferControl::~RingBufferControl() + { + } + + inline uint32_t RingBufferControl::available() const + { + return distance(m_read, m_current); + } + + inline uint32_t RingBufferControl::consume(uint32_t _size) + { + const uint32_t maxSize = distance(m_read, m_current); + const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff); + const uint32_t test = uint32_sub(sizeNoSign, maxSize); + const uint32_t size = uint32_sels(test, _size, maxSize); + const uint32_t advance = uint32_add(m_read, size); + const uint32_t read = uint32_mod(advance, m_size); + m_read = read; + return size; + } + + inline uint32_t RingBufferControl::reserve(uint32_t _size) + { + const uint32_t dist = distance(m_write, m_read)-1; + const uint32_t maxSize = uint32_sels(dist, m_size-1, dist); + const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff); + const uint32_t test = uint32_sub(sizeNoSign, maxSize); + const uint32_t size = uint32_sels(test, _size, maxSize); + const uint32_t advance = uint32_add(m_write, size); + const uint32_t write = uint32_mod(advance, m_size); + m_write = write; + return size; + } + + inline uint32_t RingBufferControl::commit(uint32_t _size) + { + const uint32_t maxSize = distance(m_current, m_write); + const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff); + const uint32_t test = uint32_sub(sizeNoSign, maxSize); + const uint32_t size = uint32_sels(test, _size, maxSize); + const uint32_t advance = uint32_add(m_current, size); + const uint32_t current = uint32_mod(advance, m_size); + m_current = current; + return size; + } + + inline uint32_t RingBufferControl::distance(uint32_t _from, uint32_t _to) const + { + const uint32_t diff = uint32_sub(_to, _from); + const uint32_t le = uint32_add(m_size, diff); + const uint32_t result = uint32_sels(diff, le, diff); + + return result; + } + + inline void RingBufferControl::reset() + { + m_current = 0; + m_write = 0; + m_read = 0; + } + + inline SpScRingBufferControl::SpScRingBufferControl(uint32_t _size) + : m_size(_size) + , m_current(0) + , m_write(0) + , m_read(0) + { + } + + inline SpScRingBufferControl::~SpScRingBufferControl() + { + } + + inline uint32_t SpScRingBufferControl::available() const + { + return distance(m_read, m_current); + } + + inline uint32_t SpScRingBufferControl::consume(uint32_t _size) + { + const uint32_t maxSize = distance(m_read, m_current); + const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff); + const uint32_t test = uint32_sub(sizeNoSign, maxSize); + const uint32_t size = uint32_sels(test, _size, maxSize); + const uint32_t advance = uint32_add(m_read, size); + const uint32_t read = uint32_mod(advance, m_size); + m_read = read; + return size; + } + + inline uint32_t SpScRingBufferControl::reserve(uint32_t _size) + { + const uint32_t dist = distance(m_write, m_read)-1; + const uint32_t maxSize = uint32_sels(dist, m_size-1, dist); + const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff); + const uint32_t test = uint32_sub(sizeNoSign, maxSize); + const uint32_t size = uint32_sels(test, _size, maxSize); + const uint32_t advance = uint32_add(m_write, size); + const uint32_t write = uint32_mod(advance, m_size); + m_write = write; + return size; + } + + inline uint32_t SpScRingBufferControl::commit(uint32_t _size) + { + const uint32_t maxSize = distance(m_current, m_write); + const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff); + const uint32_t test = uint32_sub(sizeNoSign, maxSize); + const uint32_t size = uint32_sels(test, _size, maxSize); + const uint32_t advance = uint32_add(m_current, size); + const uint32_t current = uint32_mod(advance, m_size); + + // must commit all memory writes before moving m_current pointer + // once m_current pointer moves data is used by consumer thread + memoryBarrier(); + m_current = current; + return size; + } + + inline uint32_t SpScRingBufferControl::distance(uint32_t _from, uint32_t _to) const + { + const uint32_t diff = uint32_sub(_to, _from); + const uint32_t le = uint32_add(m_size, diff); + const uint32_t result = uint32_sels(diff, le, diff); + + return result; + } + + inline void SpScRingBufferControl::reset() + { + m_current = 0; + m_write = 0; + m_read = 0; + } + + template + inline ReadRingBufferT::ReadRingBufferT(ControlT& _control, const char* _buffer, uint32_t _size) + : m_control(_control) + , m_read(_control.m_read) + , m_end(m_read+_size) + , m_size(_size) + , m_buffer(_buffer) + { + BX_CHECK(_control.available() >= _size, "%d >= %d", _control.available(), _size); + } + + template + inline ReadRingBufferT::~ReadRingBufferT() + { + } + + template + inline void ReadRingBufferT::end() + { + m_control.consume(m_size); + } + + template + inline void ReadRingBufferT::read(char* _data, uint32_t _len) + { + const uint32_t eof = (m_read + _len) % m_control.m_size; + uint32_t wrap = 0; + const char* from = &m_buffer[m_read]; + + if (eof < m_read) + { + wrap = m_control.m_size - m_read; + memCopy(_data, from, wrap); + _data += wrap; + from = (const char*)&m_buffer[0]; + } + + memCopy(_data, from, _len-wrap); + + m_read = eof; + } + + template + inline void ReadRingBufferT::skip(uint32_t _len) + { + m_read += _len; + m_read %= m_control.m_size; + } + + template + inline WriteRingBufferT::WriteRingBufferT(ControlT& _control, char* _buffer, uint32_t _size) + : m_control(_control) + , m_size(_size) + , m_buffer(_buffer) + { + uint32_t size = m_control.reserve(_size); + BX_UNUSED(size); + BX_CHECK(size == _size, "%d == %d", size, _size); + m_write = m_control.m_current; + m_end = m_write+_size; + } + + template + inline WriteRingBufferT::~WriteRingBufferT() + { + } + + template + inline void WriteRingBufferT::end() + { + m_control.commit(m_size); + } + + template + inline void WriteRingBufferT::write(const char* _data, uint32_t _len) + { + const uint32_t eof = (m_write + _len) % m_control.m_size; + uint32_t wrap = 0; + char* to = &m_buffer[m_write]; + + if (eof < m_write) + { + wrap = m_control.m_size - m_write; + memCopy(to, _data, wrap); + _data += wrap; + to = (char*)&m_buffer[0]; + } + + memCopy(to, _data, _len-wrap); + + m_write = eof; + } + + template + inline void WriteRingBufferT::write(ReadRingBufferT& _read, uint32_t _len) + { + const uint32_t eof = (_read.m_read + _len) % _read.m_control.m_size; + uint32_t wrap = 0; + const char* from = &_read.m_buffer[_read.m_read]; + + if (eof < _read.m_read) + { + wrap = _read.m_control.m_size - _read.m_read; + write(from, wrap); + from = (const char*)&_read.m_buffer[0]; + } + + write(from, _len-wrap); + + _read.m_read = eof; + } + + template + inline void WriteRingBufferT::skip(uint32_t _len) + { + m_write += _len; + m_write %= m_control.m_size; + } + +} // namespace bx diff --git a/include/bx/ringbuffer.h b/include/bx/ringbuffer.h index 69aeb3a..0172629 100644 --- a/include/bx/ringbuffer.h +++ b/include/bx/ringbuffer.h @@ -12,6 +12,7 @@ namespace bx { + /// class RingBufferControl { BX_CLASS(RingBufferControl @@ -20,75 +21,29 @@ namespace bx ); public: - RingBufferControl(uint32_t _size) - : m_size(_size) - , m_current(0) - , m_write(0) - , m_read(0) - { - } + /// + RingBufferControl(uint32_t _size); - ~RingBufferControl() - { - } + /// + ~RingBufferControl(); - uint32_t available() const - { - return distance(m_read, m_current); - } + /// + uint32_t available() const; - uint32_t consume(uint32_t _size) // consumer only - { - const uint32_t maxSize = distance(m_read, m_current); - const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff); - const uint32_t test = uint32_sub(sizeNoSign, maxSize); - const uint32_t size = uint32_sels(test, _size, maxSize); - const uint32_t advance = uint32_add(m_read, size); - const uint32_t read = uint32_mod(advance, m_size); - m_read = read; - return size; - } + /// + uint32_t consume(uint32_t _size); // consumer only - uint32_t reserve(uint32_t _size) // producer only - { - const uint32_t dist = distance(m_write, m_read)-1; - const uint32_t maxSize = uint32_sels(dist, m_size-1, dist); - const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff); - const uint32_t test = uint32_sub(sizeNoSign, maxSize); - const uint32_t size = uint32_sels(test, _size, maxSize); - const uint32_t advance = uint32_add(m_write, size); - const uint32_t write = uint32_mod(advance, m_size); - m_write = write; - return size; - } + /// + uint32_t reserve(uint32_t _size); // producer only - uint32_t commit(uint32_t _size) // producer only - { - const uint32_t maxSize = distance(m_current, m_write); - const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff); - const uint32_t test = uint32_sub(sizeNoSign, maxSize); - const uint32_t size = uint32_sels(test, _size, maxSize); - const uint32_t advance = uint32_add(m_current, size); - const uint32_t current = uint32_mod(advance, m_size); - m_current = current; - return size; - } + /// + uint32_t commit(uint32_t _size); // producer only - uint32_t distance(uint32_t _from, uint32_t _to) const // both - { - const uint32_t diff = uint32_sub(_to, _from); - const uint32_t le = uint32_add(m_size, diff); - const uint32_t result = uint32_sels(diff, le, diff); + /// + uint32_t distance(uint32_t _from, uint32_t _to) const; // both - return result; - } - - void reset() - { - m_current = 0; - m_write = 0; - m_read = 0; - } + /// + void reset(); const uint32_t m_size; uint32_t m_current; @@ -96,6 +51,7 @@ namespace bx uint32_t m_read; }; + /// class SpScRingBufferControl { BX_CLASS(SpScRingBufferControl @@ -104,79 +60,29 @@ namespace bx ); public: - SpScRingBufferControl(uint32_t _size) - : m_size(_size) - , m_current(0) - , m_write(0) - , m_read(0) - { - } + /// + SpScRingBufferControl(uint32_t _size); - ~SpScRingBufferControl() - { - } + /// + ~SpScRingBufferControl(); - uint32_t available() const - { - return distance(m_read, m_current); - } + /// + uint32_t available() const; - uint32_t consume(uint32_t _size) // consumer only - { - const uint32_t maxSize = distance(m_read, m_current); - const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff); - const uint32_t test = uint32_sub(sizeNoSign, maxSize); - const uint32_t size = uint32_sels(test, _size, maxSize); - const uint32_t advance = uint32_add(m_read, size); - const uint32_t read = uint32_mod(advance, m_size); - m_read = read; - return size; - } + /// + uint32_t consume(uint32_t _size); // consumer only - uint32_t reserve(uint32_t _size) // producer only - { - const uint32_t dist = distance(m_write, m_read)-1; - const uint32_t maxSize = uint32_sels(dist, m_size-1, dist); - const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff); - const uint32_t test = uint32_sub(sizeNoSign, maxSize); - const uint32_t size = uint32_sels(test, _size, maxSize); - const uint32_t advance = uint32_add(m_write, size); - const uint32_t write = uint32_mod(advance, m_size); - m_write = write; - return size; - } + /// + uint32_t reserve(uint32_t _size); // producer only - uint32_t commit(uint32_t _size) // producer only - { - const uint32_t maxSize = distance(m_current, m_write); - const uint32_t sizeNoSign = uint32_and(_size, 0x7fffffff); - const uint32_t test = uint32_sub(sizeNoSign, maxSize); - const uint32_t size = uint32_sels(test, _size, maxSize); - const uint32_t advance = uint32_add(m_current, size); - const uint32_t current = uint32_mod(advance, m_size); + /// + uint32_t commit(uint32_t _size); // producer only - // must commit all memory writes before moving m_current pointer - // once m_current pointer moves data is used by consumer thread - memoryBarrier(); - m_current = current; - return size; - } + /// + uint32_t distance(uint32_t _from, uint32_t _to) const; // both - uint32_t distance(uint32_t _from, uint32_t _to) const // both - { - const uint32_t diff = uint32_sub(_to, _from); - const uint32_t le = uint32_add(m_size, diff); - const uint32_t result = uint32_sels(diff, le, diff); - - return result; - } - - void reset() - { - m_current = 0; - m_write = 0; - m_read = 0; - } + /// + void reset(); const uint32_t m_size; uint32_t m_current; @@ -184,7 +90,8 @@ namespace bx uint32_t m_read; }; - template + /// + template class ReadRingBufferT { BX_CLASS(ReadRingBufferT @@ -194,65 +101,40 @@ namespace bx ); public: - ReadRingBufferT(Control& _control, const char* _buffer, uint32_t _size) - : m_control(_control) - , m_read(_control.m_read) - , m_end(m_read+_size) - , m_size(_size) - , m_buffer(_buffer) - { - BX_CHECK(_control.available() >= _size, "%d >= %d", _control.available(), _size); - } + /// + ReadRingBufferT(ControlT& _control, const char* _buffer, uint32_t _size); - ~ReadRingBufferT() - { - } + /// + ~ReadRingBufferT(); - void end() - { - m_control.consume(m_size); - } + /// + void end(); - void read(char* _data, uint32_t _len) - { - const uint32_t eof = (m_read + _len) % m_control.m_size; - uint32_t wrap = 0; - const char* from = &m_buffer[m_read]; + /// + void read(char* _data, uint32_t _len); - if (eof < m_read) - { - wrap = m_control.m_size - m_read; - memCopy(_data, from, wrap); - _data += wrap; - from = (const char*)&m_buffer[0]; - } - - memCopy(_data, from, _len-wrap); - - m_read = eof; - } - - void skip(uint32_t _len) - { - m_read += _len; - m_read %= m_control.m_size; - } + /// + void skip(uint32_t _len); private: template friend class WriteRingBufferT; - Control& m_control; + ControlT& m_control; uint32_t m_read; uint32_t m_end; const uint32_t m_size; const char* m_buffer; }; + /// typedef ReadRingBufferT ReadRingBuffer; + + /// typedef ReadRingBufferT SpScReadRingBuffer; - template + /// + template class WriteRingBufferT { BX_CLASS(WriteRingBufferT @@ -262,81 +144,40 @@ namespace bx ); public: - WriteRingBufferT(Control& _control, char* _buffer, uint32_t _size) - : m_control(_control) - , m_size(_size) - , m_buffer(_buffer) - { - uint32_t size = m_control.reserve(_size); - BX_UNUSED(size); - BX_CHECK(size == _size, "%d == %d", size, _size); - m_write = m_control.m_current; - m_end = m_write+_size; - } + /// + WriteRingBufferT(ControlT& _control, char* _buffer, uint32_t _size); - ~WriteRingBufferT() - { - } + /// + ~WriteRingBufferT(); - void end() - { - m_control.commit(m_size); - } + /// + void end(); - void write(const char* _data, uint32_t _len) - { - const uint32_t eof = (m_write + _len) % m_control.m_size; - uint32_t wrap = 0; - char* to = &m_buffer[m_write]; + /// + void write(const char* _data, uint32_t _len); - if (eof < m_write) - { - wrap = m_control.m_size - m_write; - memCopy(to, _data, wrap); - _data += wrap; - to = (char*)&m_buffer[0]; - } + /// + void write(ReadRingBufferT& _read, uint32_t _len); - memCopy(to, _data, _len-wrap); - - m_write = eof; - } - - void write(ReadRingBufferT& _read, uint32_t _len) - { - const uint32_t eof = (_read.m_read + _len) % _read.m_control.m_size; - uint32_t wrap = 0; - const char* from = &_read.m_buffer[_read.m_read]; - - if (eof < _read.m_read) - { - wrap = _read.m_control.m_size - _read.m_read; - write(from, wrap); - from = (const char*)&_read.m_buffer[0]; - } - - write(from, _len-wrap); - - _read.m_read = eof; - } - - void skip(uint32_t _len) - { - m_write += _len; - m_write %= m_control.m_size; - } + /// + void skip(uint32_t _len); private: - Control& m_control; + ControlT& m_control; uint32_t m_write; uint32_t m_end; const uint32_t m_size; char* m_buffer; }; + /// typedef WriteRingBufferT WriteRingBuffer; + + /// typedef WriteRingBufferT SpScWriteRingBuffer; } // namespace bx +#include "inline/ringbuffer.inl" + #endif // BX_RINGBUFFER_H_HEADER_GUARD