9#include "arg_wrappers.hpp"
13#include "data_types.hpp"
15#include "histogram_events.hpp"
16#include "histogram_impl.hpp"
17#include "histogram_policy.hpp"
18#include "introspect.hpp"
19#include "processor.hpp"
38 static constexpr bool emit_concluding =
42 static_assert(processor<Downstream, histogram_event<DataTypes>>);
43 static_assert(std::is_same_v<ResetEvent, never_event> ||
44 handler_for<Downstream, ResetEvent>);
46 handler_for<Downstream, warning_event>);
50 handler_for<Downstream, concluding_histogram_event<DataTypes>>);
52 using internal_overflow_policy = std::conditional_t<
54 saturate_on_internal_overflow, stop_on_internal_overflow>;
56 using bin_index_type =
typename DataTypes::bin_index_type;
57 using bin_type =
typename DataTypes::bin_type;
59 std::shared_ptr<bucket_source<bin_type>> bsource;
60 bucket<bin_type> hist_bucket;
61 single_histogram<bin_index_type, bin_type, internal_overflow_policy> shist;
62 bool saturate_warning_issued =
false;
64 Downstream downstream;
66 LIBTCSPC_NOINLINE
void start_new_round() {
67 hist_bucket = bsource->bucket_of_size(shist.num_bins());
68 shist =
decltype(shist){hist_bucket, shist};
73 if (hist_bucket.empty())
75 if constexpr (emit_concluding) {
77 concluding_histogram_event<DataTypes>{std::move(hist_bucket)});
80 if constexpr (overflow_policy ==
82 saturate_warning_issued =
false;
85 [[noreturn]] LIBTCSPC_NOINLINE
void overflow_error() {
86 throw histogram_overflow_error(
"histogram bin overflowed");
89 [[noreturn]] LIBTCSPC_NOINLINE
void overflow_stop() {
92 throw end_of_processing(
"histogram bin overflowed");
95 LIBTCSPC_NOINLINE
void saturated_warning() {
96 downstream.handle(warning_event{
"histogram bin saturated"});
97 saturate_warning_issued =
true;
100 template <
typename DT>
101 LIBTCSPC_NOINLINE
void
102 overflow_reset(bin_increment_event<DT>
const &event) {
103 if (shist.max_per_bin() == 0)
108 return handle(event);
113 arg::num_bins<std::size_t> num_bins,
114 arg::max_per_bin<bin_type> max_per_bin,
115 std::shared_ptr<bucket_source<bin_type>> buffer_provider,
116 Downstream downstream)
117 : bsource(std::move(buffer_provider)),
118 shist(hist_bucket, max_per_bin, num_bins),
119 downstream(std::move(downstream)) {
120 if (num_bins.value == 0)
121 throw std::invalid_argument(
"histogram must have at least 1 bin");
122 if (max_per_bin.value < 0)
123 throw std::invalid_argument(
124 "histogram max_per_bin must not be negative");
127 [[nodiscard]]
auto introspect_node() const -> processor_info {
128 return processor_info(
this,
"histogram");
131 [[nodiscard]]
auto introspect_graph() const -> processor_graph {
132 return downstream.introspect_graph().push_entry_point(
this);
135 template <
typename DT>
void handle(bin_increment_event<DT>
const &event) {
136 static_assert(std::is_same_v<
typename DT::bin_index_type,
137 typename DataTypes::bin_index_type>);
138 if (hist_bucket.empty())
140 if (not shist.apply_increments({&event.bin_index, 1})) {
141 if constexpr (overflow_policy ==
144 }
else if constexpr (overflow_policy ==
147 }
else if constexpr (overflow_policy ==
149 if (not saturate_warning_issued)
151 }
else if constexpr (overflow_policy ==
153 return overflow_reset(event);
157 auto const hist_event =
158 histogram_event<DataTypes>{
ad_hoc_bucket(std::span(hist_bucket))};
159 downstream.handle(hist_event);
163 template <
typename DT>
void handle(bin_increment_event<DT> &&event) {
164 handle(
static_cast<bin_increment_event<DT>
const &
>(event));
167 template <
typename E>
168 requires handler_for<Downstream, std::remove_cvref_t<E>>
169 void handle(E &&event) {
170 if constexpr (std::is_convertible_v<std::remove_cvref_t<E>,
173 downstream.handle(std::forward<E>(event));
176 void flush() { downstream.flush(); }
267 Downstream downstream) {
268 return internal::histogram<Policy, ResetEvent, DataTypes, Downstream>(
269 num_bins, max_per_bin, std::move(buffer_provider),
270 std::move(downstream));
auto ad_hoc_bucket(std::span< T > s) -> bucket< T >
Create a tcspc::bucket referencing a span.
Definition bucket.hpp:489
histogram_policy
Histogramming policy specifying behavior.
Definition histogram_policy.hpp:29
@ stop_on_overflow
Treat a histogram bin overflow as end of processing.
Definition histogram_policy.hpp:53
@ saturate_on_overflow
Ignore increments that would cause a bin overflow.
Definition histogram_policy.hpp:61
@ reset_on_overflow
Perform a reset when a histogram bin is about to overflow.
Definition histogram_policy.hpp:79
@ overflow_mask
Bitmask for overflow behavior.
Definition histogram_policy.hpp:88
@ emit_concluding_events
Enable generation of tcspc::concluding_histogram_array_event.
Definition histogram_policy.hpp:108
@ default_policy
Default policy with no bit set: equal to error_on_overflow.
Definition histogram_policy.hpp:33
@ error_on_overflow
Treat a histogram bin overflow as an error.
Definition histogram_policy.hpp:43
auto histogram(arg::num_bins< std::size_t > num_bins, arg::max_per_bin< typename DataTypes::bin_type > max_per_bin, std::shared_ptr< bucket_source< typename DataTypes::bin_type > > buffer_provider, Downstream downstream)
Create a processor that collects a histogram.
Definition histogram.hpp:263
libtcspc namespace.
Definition acquire.hpp:29
Function argument wrapper for maximum bin value.
Definition arg_wrappers.hpp:287
Function argument wrapper for number of bins parameter.
Definition arg_wrappers.hpp:327
Abstract base class for polymorphic bucket sources.
Definition bucket.hpp:505
The default data type set.
Definition data_types.hpp:24
An event type whose instances never occur.
Definition core.hpp:54