Refactor ring buffer (add external buffer version)
This commit is contained in:
parent
a4c1baa410
commit
b2eee97903
3 changed files with 143 additions and 112 deletions
|
@ -5,6 +5,7 @@ add_library(f4ll STATIC
|
||||||
src/fault.cpp
|
src/fault.cpp
|
||||||
src/memcpy_dma.cpp
|
src/memcpy_dma.cpp
|
||||||
src/packet_usart.cpp
|
src/packet_usart.cpp
|
||||||
|
src/ringbuffer.cpp
|
||||||
src/str_util.cpp
|
src/str_util.cpp
|
||||||
src/usart_core.cpp
|
src/usart_core.cpp
|
||||||
)
|
)
|
||||||
|
|
|
@ -72,10 +72,11 @@ public:
|
||||||
virtual size_type unused() const = 0;
|
virtual size_type unused() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <iringbuffer::size_type SZ> class ringbuffer : public iringbuffer
|
//
|
||||||
|
class ringbuffer_ext : public iringbuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ringbuffer() = default;
|
ringbuffer_ext(uint8_t *bptr, size_type bsize);
|
||||||
|
|
||||||
size_type put(uint8_t const *data, size_type len) override;
|
size_type put(uint8_t const *data, size_type len) override;
|
||||||
void commit() override;
|
void commit() override;
|
||||||
|
@ -89,7 +90,8 @@ public:
|
||||||
size_type unused() const override;
|
size_type unused() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t m_buffer[SZ]; //!< Data bufer
|
uint8_t *m_buffer; //!< Data bufer
|
||||||
|
size_type const m_bsize; //!< Data buffer size
|
||||||
size_type m_head = 0; //!< Write position
|
size_type m_head = 0; //!< Write position
|
||||||
size_type m_head_shadow = 0; //!< Shadowed write position for collecting data
|
size_type m_head_shadow = 0; //!< Shadowed write position for collecting data
|
||||||
//!< before committing it
|
//!< before committing it
|
||||||
|
@ -99,120 +101,20 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
template <iringbuffer::size_type SZ> iringbuffer::size_type ringbuffer<SZ>::put(uint8_t const *data, size_type len)
|
template <iringbuffer::size_type SZ> class ringbuffer : public ringbuffer_ext
|
||||||
{
|
{
|
||||||
size_type chunk1 = 0;
|
public:
|
||||||
size_type chunk2 = 0;
|
ringbuffer();
|
||||||
|
|
||||||
if (!data || !len) {
|
private:
|
||||||
return 0;
|
uint8_t m_buffer[SZ];
|
||||||
}
|
|
||||||
|
|
||||||
size_type max_len = unused();
|
|
||||||
len = len < max_len ? len : max_len;
|
|
||||||
|
|
||||||
chunk1 = sizeof(m_buffer) - m_head_shadow;
|
|
||||||
if (chunk1 >= len) {
|
|
||||||
chunk1 = len;
|
|
||||||
} else {
|
|
||||||
chunk2 = len - chunk1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::memcpy(m_buffer + m_head_shadow, data, chunk1);
|
|
||||||
m_head_shadow += chunk1;
|
|
||||||
if (m_head_shadow == sizeof(m_buffer)) {
|
|
||||||
m_head_shadow = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chunk2) {
|
|
||||||
std::memcpy(m_buffer, data + chunk1, chunk2);
|
|
||||||
m_head_shadow += chunk2;
|
|
||||||
if (m_head_shadow == sizeof(m_buffer)) {
|
|
||||||
m_head_shadow = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <iringbuffer::size_type SZ> void ringbuffer<SZ>::commit()
|
|
||||||
{
|
|
||||||
m_head = m_head_shadow;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <iringbuffer::size_type SZ> bool ringbuffer<SZ>::get_chunk(size_type len_requested, uint8_t const *&data, size_type &len) const
|
//
|
||||||
|
template <iringbuffer::size_type SZ>
|
||||||
|
ringbuffer<SZ>::ringbuffer()
|
||||||
|
: ringbuffer_ext(m_buffer, SZ)
|
||||||
{
|
{
|
||||||
if (!len_requested) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_type head = m_head;
|
|
||||||
size_type tail = m_tail;
|
|
||||||
size_type chunk_size = head >= tail ? head - tail : sizeof(m_buffer) - tail;
|
|
||||||
|
|
||||||
if (!chunk_size) {
|
|
||||||
len = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chunk_size > len_requested) {
|
|
||||||
chunk_size = len_requested;
|
|
||||||
}
|
|
||||||
data = m_buffer + tail;
|
|
||||||
len = chunk_size;
|
|
||||||
|
|
||||||
tail += chunk_size;
|
|
||||||
if (tail == sizeof(m_buffer)) {
|
|
||||||
tail = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tail != head;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <iringbuffer::size_type SZ> void ringbuffer<SZ>::consumed(size_type len)
|
|
||||||
{
|
|
||||||
if (!len) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_tail += len;
|
|
||||||
if (m_tail == sizeof(m_buffer)) {
|
|
||||||
m_tail = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <iringbuffer::size_type SZ> iringbuffer::size_type ringbuffer<SZ>::uncommited() const
|
|
||||||
{
|
|
||||||
return marker_diff(m_head_shadow, m_head);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <iringbuffer::size_type SZ> iringbuffer::size_type ringbuffer<SZ>::commited() const
|
|
||||||
{
|
|
||||||
return marker_diff(m_head, m_tail);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <iringbuffer::size_type SZ> void ringbuffer<SZ>::discard()
|
|
||||||
{
|
|
||||||
m_head_shadow = m_head;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <iringbuffer::size_type SZ> iringbuffer::size_type ringbuffer<SZ>::size() const
|
|
||||||
{
|
|
||||||
return SZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <iringbuffer::size_type SZ> iringbuffer::size_type ringbuffer<SZ>::used() const
|
|
||||||
{
|
|
||||||
return marker_diff(m_head_shadow, m_tail);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <iringbuffer::size_type SZ> iringbuffer::size_type ringbuffer<SZ>::unused() const
|
|
||||||
{
|
|
||||||
return SZ - used() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <iringbuffer::size_type SZ> iringbuffer::size_type ringbuffer<SZ>::marker_diff(size_type m1, size_type m2) const
|
|
||||||
{
|
|
||||||
return (m1 >= m2) ? (m1 - m2) : (SZ - m2 + m1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace f1ll
|
} // namespace f1ll
|
128
src/ringbuffer.cpp
Normal file
128
src/ringbuffer.cpp
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
#include <f4ll/ringbuffer.h>
|
||||||
|
|
||||||
|
namespace f4ll {
|
||||||
|
|
||||||
|
ringbuffer_ext::ringbuffer_ext(uint8_t *bptr, size_type bsize)
|
||||||
|
: m_buffer(bptr),
|
||||||
|
m_bsize(bsize)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
iringbuffer::size_type ringbuffer_ext::put(uint8_t const *data, size_type len)
|
||||||
|
{
|
||||||
|
size_type chunk1 = 0;
|
||||||
|
size_type chunk2 = 0;
|
||||||
|
|
||||||
|
if (!data || !len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_type max_len = unused();
|
||||||
|
len = len < max_len ? len : max_len;
|
||||||
|
|
||||||
|
chunk1 = m_bsize - m_head_shadow;
|
||||||
|
if (chunk1 >= len) {
|
||||||
|
chunk1 = len;
|
||||||
|
} else {
|
||||||
|
chunk2 = len - chunk1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::memcpy(m_buffer + m_head_shadow, data, chunk1);
|
||||||
|
m_head_shadow += chunk1;
|
||||||
|
if (m_head_shadow == m_bsize) {
|
||||||
|
m_head_shadow = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chunk2) {
|
||||||
|
std::memcpy(m_buffer, data + chunk1, chunk2);
|
||||||
|
m_head_shadow += chunk2;
|
||||||
|
if (m_head_shadow == m_bsize) {
|
||||||
|
m_head_shadow = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ringbuffer_ext::commit()
|
||||||
|
{
|
||||||
|
m_head = m_head_shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ringbuffer_ext::get_chunk(size_type len_requested, uint8_t const *&data, size_type &len) const
|
||||||
|
{
|
||||||
|
if (!len_requested) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_type head = m_head;
|
||||||
|
size_type tail = m_tail;
|
||||||
|
size_type chunk_size = head >= tail ? head - tail : m_bsize - tail;
|
||||||
|
|
||||||
|
if (!chunk_size) {
|
||||||
|
len = 0;
|
||||||
|
return tail != head;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chunk_size > len_requested) {
|
||||||
|
chunk_size = len_requested;
|
||||||
|
}
|
||||||
|
data = m_buffer + tail;
|
||||||
|
len = chunk_size;
|
||||||
|
|
||||||
|
tail += chunk_size;
|
||||||
|
if (tail == m_bsize) {
|
||||||
|
tail = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tail != head;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ringbuffer_ext::consumed(size_type len)
|
||||||
|
{
|
||||||
|
if (!len) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_tail += len;
|
||||||
|
if (m_tail == m_bsize) {
|
||||||
|
m_tail = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iringbuffer::size_type ringbuffer_ext::uncommited() const
|
||||||
|
{
|
||||||
|
return marker_diff(m_head_shadow, m_head);
|
||||||
|
}
|
||||||
|
|
||||||
|
iringbuffer::size_type ringbuffer_ext::commited() const
|
||||||
|
{
|
||||||
|
return marker_diff(m_head, m_tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ringbuffer_ext::discard()
|
||||||
|
{
|
||||||
|
m_head_shadow = m_head;
|
||||||
|
}
|
||||||
|
|
||||||
|
iringbuffer::size_type ringbuffer_ext::size() const
|
||||||
|
{
|
||||||
|
return m_bsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
iringbuffer::size_type ringbuffer_ext::used() const
|
||||||
|
{
|
||||||
|
return marker_diff(m_head_shadow, m_tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
iringbuffer::size_type ringbuffer_ext::unused() const
|
||||||
|
{
|
||||||
|
return m_bsize - used() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
iringbuffer::size_type ringbuffer_ext::marker_diff(size_type m1, size_type m2) const
|
||||||
|
{
|
||||||
|
return (m1 >= m2) ? (m1 - m2) : (m_bsize - m2 + m1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue