Skip to content

Ring buffer #236

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ if (NOT BOOST_COBALT_IS_ROOT)
src/detail/exception.cpp
src/detail/util.cpp
src/channel.cpp
src/ring_buffer.cpp
src/error.cpp
src/main.cpp
src/this_thread.cpp
Expand Down Expand Up @@ -186,6 +187,7 @@ else()
src/detail/util.cpp
src/error.cpp
src/channel.cpp
src/ring_buffer.cpp
src/main.cpp
src/this_thread.cpp
src/thread.cpp)
Expand Down
1 change: 1 addition & 0 deletions build/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ alias cobalt_sources
channel.cpp
error.cpp
main.cpp
ring_buffer.cpp
this_thread.cpp
thread.cpp
;
Expand Down
1 change: 1 addition & 0 deletions doc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ include::reference/concepts.adoc[]
include::reference/this_coro.adoc[]
include::reference/this_thread.adoc[]
include::reference/channel.adoc[]
include::reference/ring_buffer.adoc[]
include::reference/with.adoc[]
include::reference/race.adoc[]
include::reference/gather.adoc[]
Expand Down
2 changes: 1 addition & 1 deletion doc/reference/channel.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ generator<variant2::variant<int, double>> merge(
channel<double> & c2)
{
while (c1 && c2)
co_yield co_await race(c1, c2);
co_yield co_await race(c1.read(), c2.read());
}
----

Expand Down
53 changes: 53 additions & 0 deletions doc/reference/ring_buffer.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
[#ring_buffer]
== cobalt/ring_buffer.hpp

Channels can be used to exchange data between different coroutines
on a single thread.

=== Outline

.ring_buffer outline
[example]
[source,cpp,subs=+quotes]
----
include::../../include/boost/cobalt/ring_buffer.hpp[tag=outline]
----

=== Description

Ring Buffers are a tool for two coroutines to communicate and synchronize,
which does not block the writing coroutine, but overwrites the values in tbue ffer.

[source,cpp]
----
const std::size_t buffer_size = 2;
ring_buffer<int> ch{exec, buffer_size};

// in coroutine <1>
co_await ch.write(42);

// in coroutine <2>
auto val = co_await ch.read();
----
<1> Send a value to the ring_buffer - will not block, but may prioritize coroutine
<2> Read a value from the ring_buffer - will block until a value is awaitable.

The read operation will block if no value is available.
The write operation might suspend and resume itself later if a read is waiting.

NOTE: A ring_buffer type can be `void`, in which case `write` takes no parameter.

The ring_buffer read operation can be cancelled without losing data.
This makes it usable with <<race, race>>.

[source,cpp]
----
generator<variant2::variant<int, double>> merge(
ring_buffer<int> & c1,
ring_buffer<double> & c2)
{
while (c1 && c2)
co_yield co_await race(c1.read(), c2.read());
}
----

12 changes: 7 additions & 5 deletions include/boost/cobalt/channel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ struct channel
{
// end::outline[]
#if defined(BOOST_COBALT_NO_PMR)
explicit
channel(std::size_t limit = 0u,
executor executor = this_thread::get_executor());
#else
Expand Down Expand Up @@ -96,7 +97,7 @@ struct channel
}

struct cancel_impl;
bool await_ready() { return !chn->buffer_.empty() || chn->is_closed_; }
bool await_ready() const noexcept{ return !chn->buffer_.empty() || chn->is_closed_; }
template<typename Promise>
BOOST_COBALT_MSVC_NOINLINE
std::coroutine_handle<void> await_suspend(std::coroutine_handle<Promise> h);
Expand Down Expand Up @@ -140,7 +141,7 @@ struct channel

struct cancel_impl;

bool await_ready() { return !chn->buffer_.full() || chn->is_closed_; }
bool await_ready() const noexcept { return !chn->buffer_.full() || chn->is_closed_; }
template<typename Promise>
BOOST_COBALT_MSVC_NOINLINE
std::coroutine_handle<void> await_suspend(std::coroutine_handle<Promise> h);
Expand All @@ -153,6 +154,7 @@ struct channel
boost::intrusive::list<read_op, intrusive::constant_time_size<false> > read_queue_;
boost::intrusive::list<write_op, intrusive::constant_time_size<false> > write_queue_;
public:
BOOST_COBALT_MSVC_NOINLINE
read_op read(const boost::source_location & loc = BOOST_CURRENT_LOCATION) {return read_op{{}, this, loc}; }

BOOST_COBALT_MSVC_NOINLINE
Expand All @@ -179,7 +181,7 @@ struct channel
BOOST_COBALT_MSVC_NOINLINE
write_op write( T & value, const boost::source_location & loc = BOOST_CURRENT_LOCATION)
{
return write_op{{}, this, &value, loc};
return write_op{{}, this, &static_cast<const T&>(value), loc};
}
/*
// tag::outline[]
Expand Down Expand Up @@ -257,7 +259,7 @@ struct channel<void>
}

struct cancel_impl;
bool await_ready()
bool await_ready() const noexcept
{
return (chn->n_ > 0) || chn->is_closed_;
}
Expand Down Expand Up @@ -298,7 +300,7 @@ struct channel<void>
}

struct cancel_impl;
bool await_ready()
bool await_ready() const noexcept
{
return chn->n_ < chn->limit_ || chn->is_closed_;
}
Expand Down
2 changes: 1 addition & 1 deletion include/boost/cobalt/detail/fork.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ struct fork
struct final_awaitable
{
promise_type * self;
bool await_ready() noexcept
bool await_ready() const noexcept
{
return self->state->use_count != 1u;
}
Expand Down
2 changes: 1 addition & 1 deletion include/boost/cobalt/detail/with.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ struct [[nodiscard]] with_impl
{
struct promise_type;

bool await_ready() { return false;}
bool await_ready() const { return false;}

template<typename Promise>
BOOST_COBALT_MSVC_NOINLINE
Expand Down
Loading
Loading