// Copyright Jean Pierre Cimalando 2018. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE or copy at // http://www.boost.org/LICENSE_1_0.txt) #include "ring_buffer.h" #include #include #if defined(__cpp_if_constexpr) # define if_constexpr if constexpr #else # define if_constexpr if #endif template Ring_Buffer_Ex::Ring_Buffer_Ex(size_t capacity) : cap_(capacity + 1), rbdata_(new uint8_t[capacity + 1]) { } template Ring_Buffer_Ex::~Ring_Buffer_Ex() { } template size_t Ring_Buffer_Ex::size_used() const { const size_t rp = rp_, wp = wp_, cap = cap_; return wp + ((wp < rp) ? cap : 0) - rp; } template bool Ring_Buffer_Ex::discard(size_t len) { return getbytes_ex_(nullptr, len, true); } template size_t Ring_Buffer_Ex::size_free() const { const size_t rp = rp_, wp = wp_, cap = cap_; return rp + ((rp <= wp) ? cap : 0) - wp - 1; } template bool Ring_Buffer_Ex::getbytes_(void *data, size_t len) { return getbytes_ex_(data, len, true); } template bool Ring_Buffer_Ex::peekbytes_(void *data, size_t len) const { auto *ncthis = const_cast *>(this); return ncthis->getbytes_ex_(data, len, false); } template bool Ring_Buffer_Ex::getbytes_ex_(void *data, size_t len, bool advp) { if (size_used() < len) return false; const size_t rp = rp_, cap = cap_; const uint8_t *src = rbdata_.get(); uint8_t *dst = (uint8_t *)data; if (data) { const size_t taillen = std::min(len, cap - rp); if_constexpr (Atomic) std::atomic_thread_fence(std::memory_order_acquire); std::copy_n(&src[rp], taillen, dst); std::copy_n(src, len - taillen, dst + taillen); } if (advp) rp_ = (rp + len < cap) ? (rp + len) : (rp + len - cap); return true; } template bool Ring_Buffer_Ex::putbytes_(const void *data, size_t len) { if (size_free() < len) return false; const size_t wp = wp_, cap = cap_; const uint8_t *src = (const uint8_t *)data; uint8_t *dst = rbdata_.get(); const size_t taillen = std::min(len, cap - wp); std::copy_n(src, taillen, &dst[wp]); std::copy_n(src + taillen, len - taillen, dst); if_constexpr (Atomic) std::atomic_thread_fence(std::memory_order_release); wp_ = (wp + len < cap) ? (wp + len) : (wp + len - cap); return true; } template class Ring_Buffer_Ex; template class Ring_Buffer_Ex;