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 "event.hpp"
12#include "introspect.hpp"
13#include "numeric_traits.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 NumericTraits, bool RequireStrictlyIncreasing,
27 typename Downstream>
28 requires processor<Downstream, warning_event>
29class check_monotonic {
30 NumericTraits::abstime_type last_seen =
31 std::numeric_limits<typename NumericTraits::abstime_type>::min();
32
33 Downstream downstream;
34
35 LIBTCSPC_NOINLINE void issue_warning(NumericTraits::abstime_type abstime) {
36 std::ostringstream stream;
37 stream << "non-monotonic abstime: " << last_seen << " followed by "
38 << abstime;
39 downstream.handle(warning_event{stream.str()});
40 }
41
42 public:
43 explicit check_monotonic(Downstream downstream)
44 : downstream(std::move(downstream)) {}
45
46 [[nodiscard]] auto introspect_node() const -> processor_info {
47 return processor_info(this, "check_monotonic");
48 }
49
50 [[nodiscard]] auto introspect_graph() const -> processor_graph {
51 return downstream.introspect_graph().push_entry_point(this);
52 }
53
54 template <typename Event>
55 requires handler_for<Downstream, std::remove_cvref_t<Event>>
56 void handle(Event &&event) {
57 if constexpr (abstime_stamped<std::remove_cvref_t<Event>>) {
58 static_assert(
59 std::is_same_v<decltype(event.abstime),
60 typename NumericTraits::abstime_type>);
61 bool const monotonic = RequireStrictlyIncreasing
62 ? event.abstime > last_seen
63 : event.abstime >= last_seen;
64 if (not monotonic)
65 issue_warning(event.abstime);
66 last_seen = event.abstime;
67 }
68 downstream.handle(std::forward<Event>(event));
69 }
70
71 void flush() { downstream.flush(); }
72};
73
74} // namespace internal
75
109template <typename NumericTraits = default_numeric_traits,
110 bool RequireStrictlyIncreasing = false, typename Downstream>
111auto check_monotonic(Downstream downstream) {
112 return internal::check_monotonic<NumericTraits, RequireStrictlyIncreasing,
113 Downstream>(std::move(downstream));
114}
115
116namespace internal {
117
118template <typename Event0, typename Event1, typename Downstream>
119 requires processor<Downstream, Event0, Event1, warning_event>
120class check_alternating {
121 bool last_saw_0 = false;
122 Downstream downstream;
123
124 LIBTCSPC_NOINLINE void issue_warning() {
125 downstream.handle(warning_event{"non-alternating events"});
126 }
127
128 public:
129 explicit check_alternating(Downstream downstream)
130 : downstream(std::move(downstream)) {}
131
132 [[nodiscard]] auto introspect_node() const -> processor_info {
133 return processor_info(this, "check_alternating");
134 }
135
136 [[nodiscard]] auto introspect_graph() const -> processor_graph {
137 return downstream.introspect_graph().push_entry_point(this);
138 }
139
140 template <typename E>
141 requires handler_for<Downstream, std::remove_cvref_t<E>>
142 void handle(E &&event) {
143 if constexpr (std::is_convertible_v<std::remove_cvref_t<E>, Event0>) {
144 if (last_saw_0)
145 issue_warning();
146 last_saw_0 = true;
147 } else if constexpr (std::is_convertible_v<std::remove_cvref_t<E>,
148 Event1>) {
149 if (not last_saw_0)
150 issue_warning();
151 last_saw_0 = false;
152 }
153 downstream.handle(std::forward<E>(event));
154 }
155
156 void flush() { downstream.flush(); }
157};
158
159} // namespace internal
160
188template <typename Event0, typename Event1, typename Downstream>
189auto check_alternating(Downstream downstream) {
190 return internal::check_alternating<Event0, Event1, Downstream>(
191 std::move(downstream));
192}
193
194} // namespace tcspc
auto check_alternating(Downstream downstream)
Create a processor that checks that events of two types appear in alternation.
Definition check.hpp:189
auto check_monotonic(Downstream downstream)
Create a processor that checks that abstime is monotonically increasing or nondecreasing.
Definition check.hpp:111
libtcspc namespace.
Definition acquire.hpp:30
The default numeric traits.
Definition numeric_traits.hpp:27