9#include "arg_wrappers.hpp"
14#include "introspect.hpp"
15#include "processor.hpp"
31template <
typename DataEvent,
typename T,
typename Downstream>
32 requires std::is_constructible_v<std::span<T const>, DataEvent
const &> &&
33 processor<Downstream, bucket<T>>
34class copy_to_buckets {
35 std::shared_ptr<bucket_source<T>> bsource;
37 Downstream downstream;
40 explicit copy_to_buckets(std::shared_ptr<bucket_source<T>> buffer_provider,
41 Downstream downstream)
42 : bsource(std::move(buffer_provider)),
43 downstream(std::move(downstream)) {
45 throw std::invalid_argument(
46 "copy_to_buckets buffer_provider must not be null");
49 [[nodiscard]]
auto introspect_node() const -> processor_info {
50 return processor_info(
this,
"copy_to_buckets");
53 [[nodiscard]]
auto introspect_graph() const -> processor_graph {
54 return downstream.introspect_graph().push_entry_point(
this);
57 template <
typename Event>
58 requires std::same_as<std::remove_cvref_t<Event>, DataEvent>
59 void handle(Event &&event) {
60 auto const event_span = std::span<T const>(event);
61 auto b = bsource->bucket_of_size(event_span.size());
62 std::copy(event_span.begin(), event_span.end(), b.begin());
63 downstream.handle(std::move(b));
66 template <
typename Event>
67 requires(not std::same_as<std::remove_cvref_t<Event>, DataEvent> and
68 handler_for<Downstream, std::remove_cvref_t<Event>>)
69 void handle(Event &&event) {
70 downstream.handle(std::forward<Event>(event));
73 void flush() { downstream.flush(); }
76template <
typename DataEvent,
typename T,
typename LiveDownstream,
77 typename BatchDownstream>
78 requires std::is_constructible_v<std::span<T const>, DataEvent
const &> &&
79 processor<LiveDownstream, bucket<T const>> &&
80 processor<BatchDownstream, bucket<T>>
81class copy_to_full_buckets {
82 std::shared_ptr<bucket_source<T>> bsource;
86 std::size_t filled = 0;
88 LiveDownstream live_downstream;
89 BatchDownstream batch_downstream;
92 void emit_live(bucket<T> &b, std::size_t start, std::size_t
count) {
95 auto v = bsource->shared_view_of(b);
96 v.shrink(start,
count);
97 live_downstream.handle(std::move(v));
98 }
catch (end_of_processing
const &) {
99 b.shrink(0, start +
count);
100 batch_downstream.handle(std::move(b));
101 batch_downstream.flush();
107 void emit_batch(bucket<T> &&b) {
109 batch_downstream.handle(std::move(b));
110 }
catch (end_of_processing
const &) {
111 live_downstream.flush();
117 if (not bkt.empty() && filled > 0) {
118 bkt.shrink(0, filled);
119 batch_downstream.handle(std::move(bkt));
121 batch_downstream.flush();
125 explicit copy_to_full_buckets(
126 std::shared_ptr<bucket_source<T>> buffer_provider,
127 arg::batch_size<std::size_t> batch_size,
128 LiveDownstream live_downstream, BatchDownstream batch_downstream)
129 : bsource(std::move(buffer_provider)), bsize(batch_size.value),
130 live_downstream(std::move(live_downstream)),
131 batch_downstream(std::move(batch_downstream)) {
133 throw std::invalid_argument(
134 "copy_to_full_buckets buffer_provider must not be null");
135 if constexpr (not std::is_same_v<LiveDownstream, internal::sink_all>) {
136 if (not bsource->supports_shared_views())
137 throw std::invalid_argument(
138 "copy_to_full_buckets buffer_provider must support shared views");
141 throw std::invalid_argument(
142 "copy_to_full_buckets batch size must be positive");
145 [[nodiscard]]
auto introspect_node() const -> processor_info {
146 return processor_info(
this,
"copy_to_full_buckets");
149 [[nodiscard]]
auto introspect_graph() const -> processor_graph {
151 live_downstream.introspect_graph().push_entry_point(
this),
152 batch_downstream.introspect_graph().push_entry_point(
this));
155 template <
typename Event>
156 requires std::same_as<std::remove_cvref_t<Event>, DataEvent>
157 void handle(Event &&event) {
158 auto src = std::span<T const>(event);
159 while (not src.empty()) {
160 if (filled == 0 && bkt.empty())
161 bkt = bsource->bucket_of_size(bsize);
162 auto const dest = std::span(bkt).subspan(filled);
163 auto const copy_size = std::min(src.size(), dest.size());
164 std::copy_n(src.begin(), copy_size, dest.begin());
165 if constexpr (not std::is_same_v<LiveDownstream,
167 emit_live(bkt, filled, copy_size);
169 if (filled == bsize) {
170 emit_batch(std::move(bkt));
174 src = src.subspan(copy_size);
178 template <
typename Event>
179 requires(not std::same_as<std::remove_cvref_t<Event>, DataEvent> and
180 handler_for<LiveDownstream, std::remove_cvref_t<Event>>)
181 void handle(Event &&event) {
183 live_downstream.handle(std::forward<Event>(event));
184 }
catch (end_of_processing
const &) {
191 std::exception_ptr end;
193 live_downstream.flush();
194 }
catch (end_of_processing
const &) {
195 end = std::current_exception();
199 std::rethrow_exception(end);
239template <
typename DataEvent,
typename T,
typename Downstream>
241 Downstream downstream) {
242 return internal::copy_to_buckets<DataEvent, T, Downstream>(
243 std::move(buffer_provider), std::move(downstream));
307template <
typename DataEvent,
typename T,
typename LiveDownstream,
308 typename BatchDownstream>
311 LiveDownstream live_downstream,
312 BatchDownstream batch_downstream) {
313 return internal::copy_to_full_buckets<DataEvent, T, LiveDownstream,
315 std::move(buffer_provider), batch_size, std::move(live_downstream),
316 std::move(batch_downstream));
auto merge_processor_graphs(processor_graph const &a, processor_graph const &b) -> processor_graph
Create a new processor graph by merging two existing ones.
Definition introspect.hpp:380
auto copy_to_buckets(std::shared_ptr< bucket_source< T > > buffer_provider, Downstream downstream)
Create a processor that copies batches of data into buckets.
Definition copy_to_buckets.hpp:240
auto copy_to_full_buckets(std::shared_ptr< bucket_source< T > > buffer_provider, arg::batch_size< std::size_t > batch_size, LiveDownstream live_downstream, BatchDownstream batch_downstream)
Create a processor that copies data into buckets, ensuring that each bucket is filled to a fixed size...
Definition copy_to_buckets.hpp:309
auto count(access_tracker< count_accessor > &&tracker, Downstream downstream)
Create a processor that counts events of a given type.
Definition count.hpp:312
libtcspc namespace.
Definition acquire.hpp:30
Function argument wrapper for batch size parameter.
Definition arg_wrappers.hpp:47
Abstract base class for polymorphic bucket sources.
Definition bucket.hpp:504