util/CircularBuffer: use std::span

This commit is contained in:
Max Kellermann 2022-05-20 10:59:53 +02:00
parent b37c031fd1
commit b50173ae8b
6 changed files with 51 additions and 55 deletions

View File

@ -117,9 +117,9 @@ AsyncInputStream::Seek(std::unique_lock<Mutex> &lock,
break; break;
const size_t nbytes = const size_t nbytes =
new_offset - offset < (offset_type)r.size new_offset - offset < (offset_type)r.size()
? new_offset - offset ? new_offset - offset
: r.size; : r.size();
buffer.Consume(nbytes); buffer.Consume(nbytes);
offset += nbytes; offset += nbytes;
@ -193,8 +193,8 @@ AsyncInputStream::Read(std::unique_lock<Mutex> &lock,
cond_handler.cond.wait(lock); cond_handler.cond.wait(lock);
} }
const size_t nbytes = std::min(read_size, r.size); const size_t nbytes = std::min(read_size, r.size());
memcpy(ptr, r.data, nbytes); memcpy(ptr, r.data(), nbytes);
buffer.Consume(nbytes); buffer.Consume(nbytes);
offset += (offset_type)nbytes; offset += (offset_type)nbytes;
@ -222,17 +222,17 @@ AsyncInputStream::AppendToBuffer(const void *data, size_t append_size) noexcept
auto w = buffer.Write(); auto w = buffer.Write();
assert(!w.empty()); assert(!w.empty());
size_t nbytes = std::min(w.size, append_size); size_t nbytes = std::min(w.size(), append_size);
memcpy(w.data, data, nbytes); memcpy(w.data(), data, nbytes);
buffer.Append(nbytes); buffer.Append(nbytes);
const size_t remaining = append_size - nbytes; const size_t remaining = append_size - nbytes;
if (remaining > 0) { if (remaining > 0) {
w = buffer.Write(); w = buffer.Write();
assert(!w.empty()); assert(!w.empty());
assert(w.size >= remaining); assert(w.size() >= remaining);
memcpy(w.data, (const uint8_t *)data + nbytes, remaining); memcpy(w.data(), (const uint8_t *)data + nbytes, remaining);
buffer.Append(remaining); buffer.Append(remaining);
} }

View File

@ -93,7 +93,7 @@ ThreadInputStream::ThreadFunc() noexcept
try { try {
const ScopeUnlock unlock(mutex); const ScopeUnlock unlock(mutex);
nbytes = ThreadRead(w.data, w.size); nbytes = ThreadRead(w.data(), w.size());
} catch (...) { } catch (...) {
postponed_exception = std::current_exception(); postponed_exception = std::current_exception();
InvokeOnAvailable(); InvokeOnAvailable();
@ -145,8 +145,8 @@ ThreadInputStream::Read(std::unique_lock<Mutex> &lock,
auto r = buffer.Read(); auto r = buffer.Read();
if (!r.empty()) { if (!r.empty()) {
size_t nbytes = std::min(read_size, r.size); size_t nbytes = std::min(read_size, r.size());
memcpy(ptr, r.data, nbytes); memcpy(ptr, r.data(), nbytes);
buffer.Consume(nbytes); buffer.Consume(nbytes);
wake_cond.notify_all(); wake_cond.notify_all();
offset += nbytes; offset += nbytes;

View File

@ -240,7 +240,7 @@ AlsaInputStream::DispatchSockets() noexcept
const std::scoped_lock<Mutex> protect(mutex); const std::scoped_lock<Mutex> protect(mutex);
auto w = PrepareWriteBuffer(); auto w = PrepareWriteBuffer();
const snd_pcm_uframes_t w_frames = w.size / frame_size; const snd_pcm_uframes_t w_frames = w.size() / frame_size;
if (w_frames == 0) { if (w_frames == 0) {
/* buffer is full */ /* buffer is full */
Pause(); Pause();
@ -249,7 +249,7 @@ AlsaInputStream::DispatchSockets() noexcept
snd_pcm_sframes_t n_frames; snd_pcm_sframes_t n_frames;
while ((n_frames = snd_pcm_readi(capture_handle, while ((n_frames = snd_pcm_readi(capture_handle,
w.data, w_frames)) < 0) { w.data(), w_frames)) < 0) {
if (n_frames == -EAGAIN) if (n_frames == -EAGAIN)
return; return;

View File

@ -123,7 +123,7 @@ UringInputStream::SubmitRead() noexcept
read_operation = std::make_unique<Uring::ReadOperation>(); read_operation = std::make_unique<Uring::ReadOperation>();
read_operation->Start(uring, fd, next_offset, read_operation->Start(uring, fd, next_offset,
std::min(w.size, URING_MAX_READ), std::min(w.size(), URING_MAX_READ),
*this); *this);
} }
@ -158,8 +158,8 @@ UringInputStream::OnRead(std::unique_ptr<std::byte[]> data,
} }
auto w = PrepareWriteBuffer(); auto w = PrepareWriteBuffer();
assert(w.size >= nbytes); assert(w.size() >= nbytes);
memcpy(w.data, data.get(), nbytes); memcpy(w.data(), data.get(), nbytes);
CommitWriteBuffer(nbytes); CommitWriteBuffer(nbytes);
next_offset += nbytes; next_offset += nbytes;
SubmitRead(); SubmitRead();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2014 Max Kellermann <max.kellermann@gmail.com> * Copyright 2014-2022 Max Kellermann <max.kellermann@gmail.com>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -27,13 +27,11 @@
* OF THE POSSIBILITY OF SUCH DAMAGE. * OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef CIRCULAR_BUFFER_HPP #pragma once
#define CIRCULAR_BUFFER_HPP
#include "WritableBuffer.hxx"
#include <cassert> #include <cassert>
#include <cstddef> #include <cstddef>
#include <span>
/** /**
* A circular buffer. * A circular buffer.
@ -50,7 +48,7 @@
template<typename T> template<typename T>
class CircularBuffer { class CircularBuffer {
public: public:
typedef WritableBuffer<T> Range; using Range = std::span<T>;
typedef typename Range::pointer pointer; typedef typename Range::pointer pointer;
typedef typename Range::size_type size_type; typedef typename Range::size_type size_type;
@ -182,5 +180,3 @@ public:
head = 0; head = 0;
} }
}; };
#endif

View File

@ -24,8 +24,8 @@ TEST(CircularBuffer, Basic)
EXPECT_EQ(size_t(7), buffer.GetSpace()); EXPECT_EQ(size_t(7), buffer.GetSpace());
EXPECT_TRUE(buffer.Read().empty()); EXPECT_TRUE(buffer.Read().empty());
EXPECT_FALSE(buffer.Write().empty()); EXPECT_FALSE(buffer.Write().empty());
EXPECT_EQ(&data[0], buffer.Write().data); EXPECT_EQ(&data[0], buffer.Write().data());
EXPECT_EQ(size_t(7), buffer.Write().size); EXPECT_EQ(size_t(7), buffer.Write().size());
/* append one element */ /* append one element */
/* [O......X] */ /* [O......X] */
@ -35,11 +35,11 @@ TEST(CircularBuffer, Basic)
EXPECT_FALSE(buffer.Read().empty()); EXPECT_FALSE(buffer.Read().empty());
EXPECT_EQ(size_t(1), buffer.GetSize()); EXPECT_EQ(size_t(1), buffer.GetSize());
EXPECT_EQ(size_t(6), buffer.GetSpace()); EXPECT_EQ(size_t(6), buffer.GetSpace());
EXPECT_EQ(size_t(1), buffer.Read().size); EXPECT_EQ(size_t(1), buffer.Read().size());
EXPECT_EQ(&data[0], buffer.Read().data); EXPECT_EQ(&data[0], buffer.Read().data());
EXPECT_FALSE(buffer.Write().empty()); EXPECT_FALSE(buffer.Write().empty());
EXPECT_EQ(&data[1], buffer.Write().data); EXPECT_EQ(&data[1], buffer.Write().data());
EXPECT_EQ(size_t(6), buffer.Write().size); EXPECT_EQ(size_t(6), buffer.Write().size());
/* append 6 elements, buffer is now full */ /* append 6 elements, buffer is now full */
/* [OOOOOOOX] */ /* [OOOOOOOX] */
@ -49,8 +49,8 @@ TEST(CircularBuffer, Basic)
EXPECT_FALSE(buffer.Read().empty()); EXPECT_FALSE(buffer.Read().empty());
EXPECT_EQ(size_t(7), buffer.GetSize()); EXPECT_EQ(size_t(7), buffer.GetSize());
EXPECT_EQ(size_t(0), buffer.GetSpace()); EXPECT_EQ(size_t(0), buffer.GetSpace());
EXPECT_EQ(size_t(7), buffer.Read().size); EXPECT_EQ(size_t(7), buffer.Read().size());
EXPECT_EQ(&data[0], buffer.Read().data); EXPECT_EQ(&data[0], buffer.Read().data());
EXPECT_TRUE(buffer.Write().empty()); EXPECT_TRUE(buffer.Write().empty());
/* consume [0]; can append one at [7] */ /* consume [0]; can append one at [7] */
@ -61,11 +61,11 @@ TEST(CircularBuffer, Basic)
EXPECT_FALSE(buffer.Read().empty()); EXPECT_FALSE(buffer.Read().empty());
EXPECT_EQ(size_t(6), buffer.GetSize()); EXPECT_EQ(size_t(6), buffer.GetSize());
EXPECT_EQ(size_t(1), buffer.GetSpace()); EXPECT_EQ(size_t(1), buffer.GetSpace());
EXPECT_EQ(size_t(6), buffer.Read().size); EXPECT_EQ(size_t(6), buffer.Read().size());
EXPECT_EQ(&data[1], buffer.Read().data); EXPECT_EQ(&data[1], buffer.Read().data());
EXPECT_FALSE(buffer.Write().empty()); EXPECT_FALSE(buffer.Write().empty());
EXPECT_EQ(&data[7], buffer.Write().data); EXPECT_EQ(&data[7], buffer.Write().data());
EXPECT_EQ(size_t(1), buffer.Write().size); EXPECT_EQ(size_t(1), buffer.Write().size());
/* append one element; [0] is still empty but cannot /* append one element; [0] is still empty but cannot
be written to because head==1 */ be written to because head==1 */
@ -76,8 +76,8 @@ TEST(CircularBuffer, Basic)
EXPECT_FALSE(buffer.Read().empty()); EXPECT_FALSE(buffer.Read().empty());
EXPECT_EQ(size_t(7), buffer.GetSize()); EXPECT_EQ(size_t(7), buffer.GetSize());
EXPECT_EQ(size_t(0), buffer.GetSpace()); EXPECT_EQ(size_t(0), buffer.GetSpace());
EXPECT_EQ(size_t(7), buffer.Read().size); EXPECT_EQ(size_t(7), buffer.Read().size());
EXPECT_EQ(&data[1], buffer.Read().data); EXPECT_EQ(&data[1], buffer.Read().data());
EXPECT_TRUE(buffer.Write().empty()); EXPECT_TRUE(buffer.Write().empty());
/* consume [1..3]; can append [0..2] */ /* consume [1..3]; can append [0..2] */
@ -88,11 +88,11 @@ TEST(CircularBuffer, Basic)
EXPECT_FALSE(buffer.Read().empty()); EXPECT_FALSE(buffer.Read().empty());
EXPECT_EQ(size_t(4), buffer.GetSize()); EXPECT_EQ(size_t(4), buffer.GetSize());
EXPECT_EQ(size_t(3), buffer.GetSpace()); EXPECT_EQ(size_t(3), buffer.GetSpace());
EXPECT_EQ(size_t(4), buffer.Read().size); EXPECT_EQ(size_t(4), buffer.Read().size());
EXPECT_EQ(&data[4], buffer.Read().data); EXPECT_EQ(&data[4], buffer.Read().data());
EXPECT_FALSE(buffer.Write().empty()); EXPECT_FALSE(buffer.Write().empty());
EXPECT_EQ(&data[0], buffer.Write().data); EXPECT_EQ(&data[0], buffer.Write().data());
EXPECT_EQ(size_t(3), buffer.Write().size); EXPECT_EQ(size_t(3), buffer.Write().size());
/* append [0..1] */ /* append [0..1] */
/* [OO.XOOOO] */ /* [OO.XOOOO] */
@ -102,11 +102,11 @@ TEST(CircularBuffer, Basic)
EXPECT_FALSE(buffer.Read().empty()); EXPECT_FALSE(buffer.Read().empty());
EXPECT_EQ(size_t(6), buffer.GetSize()); EXPECT_EQ(size_t(6), buffer.GetSize());
EXPECT_EQ(size_t(1), buffer.GetSpace()); EXPECT_EQ(size_t(1), buffer.GetSpace());
EXPECT_EQ(size_t(4), buffer.Read().size); EXPECT_EQ(size_t(4), buffer.Read().size());
EXPECT_EQ(&data[4], buffer.Read().data); EXPECT_EQ(&data[4], buffer.Read().data());
EXPECT_FALSE(buffer.Write().empty()); EXPECT_FALSE(buffer.Write().empty());
EXPECT_EQ(&data[2], buffer.Write().data); EXPECT_EQ(&data[2], buffer.Write().data());
EXPECT_EQ(size_t(1), buffer.Write().size); EXPECT_EQ(size_t(1), buffer.Write().size());
/* append [2] */ /* append [2] */
/* [OOOXOOOO] */ /* [OOOXOOOO] */
@ -116,8 +116,8 @@ TEST(CircularBuffer, Basic)
EXPECT_FALSE(buffer.Read().empty()); EXPECT_FALSE(buffer.Read().empty());
EXPECT_EQ(size_t(7), buffer.GetSize()); EXPECT_EQ(size_t(7), buffer.GetSize());
EXPECT_EQ(size_t(0), buffer.GetSpace()); EXPECT_EQ(size_t(0), buffer.GetSpace());
EXPECT_EQ(size_t(4), buffer.Read().size); EXPECT_EQ(size_t(4), buffer.Read().size());
EXPECT_EQ(&data[4], buffer.Read().data); EXPECT_EQ(&data[4], buffer.Read().data());
EXPECT_TRUE(buffer.Write().empty()); EXPECT_TRUE(buffer.Write().empty());
/* consume [4..7] */ /* consume [4..7] */
@ -128,11 +128,11 @@ TEST(CircularBuffer, Basic)
EXPECT_FALSE(buffer.Read().empty()); EXPECT_FALSE(buffer.Read().empty());
EXPECT_EQ(size_t(3), buffer.GetSize()); EXPECT_EQ(size_t(3), buffer.GetSize());
EXPECT_EQ(size_t(4), buffer.GetSpace()); EXPECT_EQ(size_t(4), buffer.GetSpace());
EXPECT_EQ(size_t(3), buffer.Read().size); EXPECT_EQ(size_t(3), buffer.Read().size());
EXPECT_EQ(&data[0], buffer.Read().data); EXPECT_EQ(&data[0], buffer.Read().data());
EXPECT_FALSE(buffer.Write().empty()); EXPECT_FALSE(buffer.Write().empty());
EXPECT_EQ(&data[3], buffer.Write().data); EXPECT_EQ(&data[3], buffer.Write().data());
EXPECT_EQ(size_t(4), buffer.Write().size); EXPECT_EQ(size_t(4), buffer.Write().size());
/* consume [0..2]; after that, we can only write 5, /* consume [0..2]; after that, we can only write 5,
because the CircularBuffer class doesn't have because the CircularBuffer class doesn't have
@ -145,6 +145,6 @@ TEST(CircularBuffer, Basic)
EXPECT_EQ(size_t(7), buffer.GetSpace()); EXPECT_EQ(size_t(7), buffer.GetSpace());
EXPECT_TRUE(buffer.Read().empty()); EXPECT_TRUE(buffer.Read().empty());
EXPECT_FALSE(buffer.Write().empty()); EXPECT_FALSE(buffer.Write().empty());
EXPECT_EQ(&data[3], buffer.Write().data); EXPECT_EQ(&data[3], buffer.Write().data());
EXPECT_EQ(size_t(5), buffer.Write().size); EXPECT_EQ(size_t(5), buffer.Write().size());
} }