Add the spsc ring buffer
This commit is contained in:
parent
25ca3eeb0b
commit
23a3508d81
5 changed files with 262 additions and 0 deletions
|
|
@ -60,6 +60,10 @@ set_target_properties(${VSTPLUGIN_PRJ_NAME} PROPERTIES
|
|||
plugin_add_vst3sdk(${VSTPLUGIN_PRJ_NAME})
|
||||
plugin_add_vstgui(${VSTPLUGIN_PRJ_NAME})
|
||||
|
||||
# Add the ring buffer
|
||||
target_include_directories(${VSTPLUGIN_PRJ_NAME} PRIVATE "external/ring_buffer")
|
||||
target_sources(${VSTPLUGIN_PRJ_NAME} PRIVATE "external/ring_buffer/ring_buffer/ring_buffer.cpp")
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
target_link_libraries(${VSTPLUGIN_PRJ_NAME} PRIVATE
|
||||
"-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/vst3.version")
|
||||
|
|
|
|||
23
vst/external/ring_buffer/LICENSE
vendored
Normal file
23
vst/external/ring_buffer/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
105
vst/external/ring_buffer/ring_buffer/ring_buffer.cpp
vendored
Normal file
105
vst/external/ring_buffer/ring_buffer/ring_buffer.cpp
vendored
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
// 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 <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#if defined(__cpp_if_constexpr)
|
||||
# define if_constexpr if constexpr
|
||||
#else
|
||||
# define if_constexpr if
|
||||
#endif
|
||||
|
||||
template <bool Atomic>
|
||||
Ring_Buffer_Ex<Atomic>::Ring_Buffer_Ex(size_t capacity)
|
||||
: cap_(capacity + 1),
|
||||
rbdata_(new uint8_t[capacity + 1])
|
||||
{
|
||||
}
|
||||
|
||||
template <bool Atomic>
|
||||
Ring_Buffer_Ex<Atomic>::~Ring_Buffer_Ex()
|
||||
{
|
||||
}
|
||||
|
||||
template <bool Atomic>
|
||||
size_t Ring_Buffer_Ex<Atomic>::size_used() const
|
||||
{
|
||||
const size_t rp = rp_, wp = wp_, cap = cap_;
|
||||
return wp + ((wp < rp) ? cap : 0) - rp;
|
||||
}
|
||||
|
||||
template <bool Atomic>
|
||||
bool Ring_Buffer_Ex<Atomic>::discard(size_t len)
|
||||
{
|
||||
return getbytes_ex_(nullptr, len, true);
|
||||
}
|
||||
|
||||
template <bool Atomic>
|
||||
size_t Ring_Buffer_Ex<Atomic>::size_free() const
|
||||
{
|
||||
const size_t rp = rp_, wp = wp_, cap = cap_;
|
||||
return rp + ((rp <= wp) ? cap : 0) - wp - 1;
|
||||
}
|
||||
|
||||
template <bool Atomic>
|
||||
bool Ring_Buffer_Ex<Atomic>::getbytes_(void *data, size_t len)
|
||||
{
|
||||
return getbytes_ex_(data, len, true);
|
||||
}
|
||||
|
||||
template <bool Atomic>
|
||||
bool Ring_Buffer_Ex<Atomic>::peekbytes_(void *data, size_t len) const
|
||||
{
|
||||
auto *ncthis = const_cast<Ring_Buffer_Ex<Atomic> *>(this);
|
||||
return ncthis->getbytes_ex_(data, len, false);
|
||||
}
|
||||
|
||||
template <bool Atomic>
|
||||
bool Ring_Buffer_Ex<Atomic>::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 Atomic>
|
||||
bool Ring_Buffer_Ex<Atomic>::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<true>;
|
||||
template class Ring_Buffer_Ex<false>;
|
||||
69
vst/external/ring_buffer/ring_buffer/ring_buffer.h
vendored
Normal file
69
vst/external/ring_buffer/ring_buffer/ring_buffer.h
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
// 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)
|
||||
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
#include <type_traits>
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
#if defined(__cpp_lib_atomic_is_always_lock_free)
|
||||
static_assert(
|
||||
std::atomic<size_t>::is_always_lock_free, "atomic<size_t> must be lock free");
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template <bool> class Ring_Buffer_Ex;
|
||||
typedef Ring_Buffer_Ex<true> Ring_Buffer;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template <class RB>
|
||||
class Basic_Ring_Buffer {
|
||||
public:
|
||||
// read operations
|
||||
template <class T> bool get(T &x);
|
||||
template <class T> bool get(T *x, size_t n);
|
||||
template <class T> bool peek(T &x);
|
||||
template <class T> bool peek(T *x, size_t n);
|
||||
// write operations
|
||||
template <class T> bool put(const T &x);
|
||||
template <class T> bool put(const T *x, size_t n);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template <bool Atomic>
|
||||
class Ring_Buffer_Ex final :
|
||||
private Basic_Ring_Buffer<Ring_Buffer_Ex<Atomic>> {
|
||||
private:
|
||||
typedef Basic_Ring_Buffer<Ring_Buffer_Ex<Atomic>> Base;
|
||||
public:
|
||||
// initialization and cleanup
|
||||
explicit Ring_Buffer_Ex(size_t capacity);
|
||||
~Ring_Buffer_Ex();
|
||||
// attributes
|
||||
size_t capacity() const;
|
||||
// read operations
|
||||
size_t size_used() const;
|
||||
bool discard(size_t len);
|
||||
using Base::get;
|
||||
using Base::peek;
|
||||
// write operations
|
||||
size_t size_free() const;
|
||||
using Base::put;
|
||||
|
||||
private:
|
||||
size_t cap_{0};
|
||||
typename std::conditional<Atomic, std::atomic<size_t>, size_t>::type rp_{0}, wp_{0};
|
||||
std::unique_ptr<uint8_t[]> rbdata_ {};
|
||||
friend Base;
|
||||
bool getbytes_(void *data, size_t len);
|
||||
bool peekbytes_(void *data, size_t len) const;
|
||||
bool getbytes_ex_(void *data, size_t len, bool advp);
|
||||
bool putbytes_(const void *data, size_t len);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#include "ring_buffer.tcc"
|
||||
61
vst/external/ring_buffer/ring_buffer/ring_buffer.tcc
vendored
Normal file
61
vst/external/ring_buffer/ring_buffer/ring_buffer.tcc
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// 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"
|
||||
|
||||
template <bool Atomic>
|
||||
inline size_t Ring_Buffer_Ex<Atomic>::capacity() const
|
||||
{
|
||||
return cap_ - 1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template <class RB>
|
||||
template <class T>
|
||||
inline bool Basic_Ring_Buffer<RB>::get(T &x)
|
||||
{
|
||||
return get(&x, 1);
|
||||
}
|
||||
|
||||
template <class RB>
|
||||
template <class T>
|
||||
inline bool Basic_Ring_Buffer<RB>::get(T *x, size_t n)
|
||||
{
|
||||
// static_assert(std::is_trivially_copyable<T>::value, "ring_buffer: T must be trivially copyable");
|
||||
RB *self = static_cast<RB *>(this);
|
||||
return self->getbytes_(x, n * sizeof(T));
|
||||
}
|
||||
|
||||
template <class RB>
|
||||
template <class T>
|
||||
inline bool Basic_Ring_Buffer<RB>::peek(T &x)
|
||||
{
|
||||
return peek(&x, 1);
|
||||
}
|
||||
|
||||
template <class RB>
|
||||
template <class T>
|
||||
inline bool Basic_Ring_Buffer<RB>::peek(T *x, size_t n)
|
||||
{
|
||||
// static_assert(std::is_trivially_copyable<T>::value, "ring_buffer: T must be trivially copyable");
|
||||
RB *self = static_cast<RB *>(this);
|
||||
return self->peekbytes_(x, n * sizeof(T));
|
||||
}
|
||||
|
||||
template <class RB>
|
||||
template <class T>
|
||||
inline bool Basic_Ring_Buffer<RB>::put(const T &x)
|
||||
{
|
||||
return put(&x, 1);
|
||||
}
|
||||
|
||||
template <class RB>
|
||||
template <class T>
|
||||
inline bool Basic_Ring_Buffer<RB>::put(const T *x, size_t n)
|
||||
{
|
||||
// static_assert(std::is_trivially_copyable<T>::value, "ring_buffer: T must be trivially copyable");
|
||||
RB *self = static_cast<RB *>(this);
|
||||
return self->putbytes_(x, n * sizeof(T));
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue