7#include <condition_variable>
34 std::condition_variable condition_variable_;
37 std::list<T> message_queue_;
40 std::atomic<size_t> num_senders_ = 0;
43 std::atomic<size_t> num_receivers_ = 0;
55 std::shared_ptr<detail::SpscImplementation<T>> impl_;
61 impl_{std::move(impl)}
63 ++impl_->num_senders_;
74 --impl_->num_senders_;
75 impl_->condition_variable_.notify_all();
82 std::lock_guard l{impl_->mutex_};
83 impl_->message_queue_.push_front(std::move(v));
85 impl_->condition_variable_.notify_one();
90 return impl_->num_receivers_ == 0;
97 std::shared_ptr<detail::SpscImplementation<T>> impl_;
103 impl_{std::move(impl)}
105 ++impl_->num_receivers_;
115 --impl_->num_receivers_;
122 std::lock_guard l{impl_->mutex_};
124 if (impl_->message_queue_.empty()) {
128 std::optional<T> rv{std::move(impl_->message_queue_.back())};
129 impl_->message_queue_.pop_back();
136 std::unique_lock l{impl_->mutex_};
139 if (not impl_->message_queue_.empty())
141 std::optional<T> rv{std::move(impl_->message_queue_.back())};
142 impl_->message_queue_.pop_back();
148 impl_->condition_variable_.wait(l, [&]()
150 return not impl_->message_queue_.empty() or impl_->num_senders_ == 0;
158 if (not impl_->message_queue_.empty()) {
159 std::optional<T> rv{std::move(impl_->message_queue_.back())};
160 impl_->message_queue_.pop_back();
170 return impl_->num_senders_ == 0;
178 auto impl = std::make_shared<detail::SpscImplementation<T>>();
186 template<
typename Input,
typename Output,
typename Func>
203 Func message_processor)
208 std::optional<Input> message = receiver.
receive();
214 sender.
send(message_processor(*message));
225 worker_thread_{std::move(worker)},
226 sender_{std::move(sender)},
227 receiver_{std::move(receiver)}
235 auto [request_sender, request_receiver] = make_spsc_channel<Input>();
236 auto [response_sender, response_receiver] = make_spsc_channel<Output>();
237 cpp20::jthread worker{SpscWorker::main, std::move(request_receiver), std::move(response_sender), std::move(message_processor)};
238 return SpscWorker{std::move(worker), std::move(request_sender), std::move(response_receiver)};
243 sender_.
send(std::move(req));
SpscReceiver(SpscReceiver const &)=delete
SpscReceiver(SpscReceiver &&) noexcept=default
std::optional< T > receive()
Definition spsc.h:134
std::optional< T > try_receive()
Definition spsc.h:120
friend std::pair< SpscSender< U >, SpscReceiver< U > > make_spsc_channel()
Definition spsc.h:176
bool is_sender_hung_up()
Definition spsc.h:168
SpscSender(const SpscSender &)=delete
SpscSender(SpscSender &&) noexcept=default
void send(T v)
Definition spsc.h:80
bool is_receiver_hung_up()
Definition spsc.h:88
friend std::pair< SpscSender< U >, SpscReceiver< U > > make_spsc_channel()
Definition spsc.h:176
static SpscWorker create(Func message_processor)
Definition spsc.h:233
std::optional< Output > poll()
Definition spsc.h:246
void send(Input req)
Definition spsc.h:241
Definition stop_token.h:19
friend std::pair< SpscSender< U >, SpscReceiver< U > > make_spsc_channel()
Definition spsc.h:176
Definition custom_decoration_generator.h:5
std::pair< SpscSender< T >, SpscReceiver< T > > make_spsc_channel()
Definition spsc.h:176