libtcspc C++ API
Streaming TCSPC and time tag data processing
Loading...
Searching...
No Matches
check.hpp
1/*
2 * This file is part of libtcspc
3 * Copyright 2019-2026 Board of Regents of the University of Wisconsin System
4 * SPDX-License-Identifier: MIT
5 */
6
7#pragma once
8
9#include "common.hpp"
10#include "core.hpp"
11#include "data_types.hpp"
12#include "event.hpp"
13#include "introspect.hpp"
14#include "processor.hpp"
15
16#include <limits>
17#include <ostream>
18#include <sstream>
19#include <type_traits>
20#include <utility>
21
22namespace tcspc {
23
24namespace internal {
25
26template <typename DataTypes, bool RequireStrictlyIncreasing,
27 typename Downstream>
28class check_monotonic {
29 static_assert(processor<Downstream, warning_event>);
30
31 typename DataTypes::abstime_type last_seen =
32 std::numeric_limits<typename DataTypes::abstime_type>::min();
33
34 Downstream downstream;
35
36 LIBTCSPC_NOINLINE void
37 issue_warning(typename DataTypes::abstime_type abstime) {
38 std::ostringstream stream;
39 stream << "non-monotonic abstime: " << last_seen << " followed by "
40 << abstime;
41 downstream.handle(warning_event{stream.str()});
42 }
43
44 public:
45 explicit check_monotonic(Downstream downstream)
46 : downstream(std::move(downstream)) {}
47
48 [[nodiscard]] auto introspect_node() const -> processor_info {
49 return processor_info(this, "check_monotonic");
50 }
51
52 [[nodiscard]] auto introspect_graph() const -> processor_graph {
53 return downstream.introspect_graph().push_entry_point(this);
54 }
55
56 template <typename Event>
57 requires handler_for<Downstream, std::remove_cvref_t<Event>>
58 void handle(Event &&event) {
59 if constexpr (abstime_stamped<std::remove_cvref_t<Event>>) {
60 static_assert(std::is_same_v<decltype(event.abstime),
61 typename DataTypes::abstime_type>);
62 bool const monotonic = RequireStrictlyIncreasing
63 ? event.abstime > last_seen
64 : event.abstime >= last_seen;
65 if (not monotonic)
66 issue_warning(event.abstime);
67 last_seen = event.abstime;
68 }
69 downstream.handle(std::forward<Event>(event));
70 }
71
72 void flush() { downstream.flush(); }
73};
74
75} // namespace internal
76
110template <typename DataTypes = default_data_types,
111 bool RequireStrictlyIncreasing = false, typename Downstream>
112auto check_monotonic(Downstream downstream) {
113 return internal::check_monotonic<DataTypes, RequireStrictlyIncreasing,
114 Downstream>(std::move(downstream));
115}
116
117namespace internal {
118
119template <typename Event0, typename Event1, typename Downstream>
120class check_alternating {
121 static_assert(processor<Downstream, Event0, Event1, warning_event>);
122
123 bool last_saw_0 = false;
124 Downstream downstream;
125
126 LIBTCSPC_NOINLINE void issue_warning() {
127 downstream.handle(warning_event{"non-alternating events"});
128 }
129
130 public:
131 explicit check_alternating(Downstream downstream)
132 : downstream(std::move(downstream)) {}
133
134 [[nodiscard]] auto introspect_node() const -> processor_info {
135 return processor_info(this, "check_alternating");
136 }
137
138 [[nodiscard]] auto introspect_graph() const -> processor_graph {
139 return downstream.introspect_graph().push_entry_point(this);
140 }
141
142 template <typename E>
143 requires handler_for<Downstream, std::remove_cvref_t<E>>
144 void handle(E &&event) {
145 if constexpr (std::is_convertible_v<std::remove_cvref_t<E>, Event0>) {
146 if (last_saw_0)
147 issue_warning();
148 last_saw_0 = true;
149 } else if constexpr (std::is_convertible_v<std::remove_cvref_t<E>,
150 Event1>) {
151 if (not last_saw_0)
152 issue_warning();
153 last_saw_0 = false;
154 }
155 downstream.handle(std::forward<E>(event));
156 }
157
158 void flush() { downstream.flush(); }
159};
160
161} // namespace internal
162
190template <typename Event0, typename Event1, typename Downstream>
191auto check_alternating(Downstream downstream) {
192 return internal::check_alternating<Event0, Event1, Downstream>(
193 std::move(downstream));
194}
195
196} // namespace tcspc
auto check_alternating(Downstream downstream)
Create a processor that checks that events of two types appear in alternation.
Definition check.hpp:191
auto check_monotonic(Downstream downstream)
Create a processor that checks that abstime is monotonically increasing or nondecreasing.
Definition check.hpp:112
libtcspc namespace.
Definition acquire.hpp:29
The default data type set.
Definition data_types.hpp:24