libtcspc C++ API
Streaming TCSPC and time tag data processing
Loading...
Searching...
No Matches
delay.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 "arg_wrappers.hpp"
10#include "common.hpp"
11#include "data_types.hpp"
12#include "int_arith.hpp"
13#include "introspect.hpp"
14#include "processor.hpp"
15
16#include <type_traits>
17#include <utility>
18
19namespace tcspc {
20
21namespace internal {
22
23template <typename DataTypes, typename Downstream> class delay {
24 typename DataTypes::abstime_type delta;
25 Downstream downstream;
26
27 public:
28 explicit delay(arg::delta<typename DataTypes::abstime_type> delta,
29 Downstream downstream)
30 : delta(delta.value), downstream(std::move(downstream)) {}
31
32 [[nodiscard]] auto introspect_node() const -> processor_info {
33 return processor_info(this, "delay");
34 }
35
36 [[nodiscard]] auto introspect_graph() const -> processor_graph {
37 return downstream.introspect_graph().push_entry_point(this);
38 }
39
40 // Note: We could support rvalue events and edit the abstime in place. But
41 // in practice events are expected to be small (so copy overhead is
42 // probably minor) and may originate from a buffer (in which case we do not
43 // want to rely on the compiler to optimize out the write to the event in a
44 // heap buffer). Also only handling lvalues is simpler.
45
46 template <typename TimeTaggedEvent>
47 requires handler_for<Downstream, std::remove_cvref_t<TimeTaggedEvent>>
48 void handle(TimeTaggedEvent const &event) {
49 static_assert(std::is_same_v<decltype(event.abstime),
50 typename DataTypes::abstime_type>);
51 TimeTaggedEvent copy(event);
52 copy.abstime = add_with_wrap(copy.abstime, delta);
53 downstream.handle(std::move(copy));
54 }
55
56 void flush() { downstream.flush(); }
57};
58
59template <typename DataTypes, typename Downstream> class zero_base_abstime {
60 bool initialized = false;
61 typename DataTypes::abstime_type minus_delta{};
62 Downstream downstream;
63
64 public:
65 explicit zero_base_abstime(Downstream downstream)
66 : downstream(std::move(downstream)) {}
67
68 [[nodiscard]] auto introspect_node() const -> processor_info {
69 return processor_info(this, "zero_base_abstime");
70 }
71
72 [[nodiscard]] auto introspect_graph() const -> processor_graph {
73 return downstream.introspect_graph().push_entry_point(this);
74 }
75
76 // Handle only const lvalue (see note on delay::handle()).
77
78 template <typename TimeTaggedEvent>
79 requires handler_for<Downstream, std::remove_cvref_t<TimeTaggedEvent>>
80 void handle(TimeTaggedEvent const &event) {
81 static_assert(std::is_same_v<decltype(event.abstime),
82 typename DataTypes::abstime_type>);
83 if (not initialized) {
84 minus_delta = event.abstime;
85 initialized = true;
86 }
87 TimeTaggedEvent copy(event);
88 copy.abstime = subtract_with_wrap(event.abstime, minus_delta);
89 downstream.handle(std::move(copy));
90 }
91
92 void flush() { downstream.flush(); }
93};
94
95} // namespace internal
96
122template <typename DataTypes = default_data_types, typename Downstream>
124 Downstream downstream) {
125 return internal::delay<DataTypes, Downstream>(delta,
126 std::move(downstream));
127}
128
154template <typename DataTypes = default_data_types, typename Downstream>
155auto zero_base_abstime(Downstream downstream) {
156 return internal::zero_base_abstime<DataTypes, Downstream>(
157 std::move(downstream));
158}
159
160} // namespace tcspc
auto delay(arg::delta< typename DataTypes::abstime_type > delta, Downstream downstream)
Create a processor that applies an abstime offset to all events.
Definition delay.hpp:123
auto zero_base_abstime(Downstream downstream)
Create a processor that offsets abstime so that the first event is at time zero.
Definition delay.hpp:155
libtcspc namespace.
Definition acquire.hpp:29
Function argument wrapper for delta parameter.
Definition arg_wrappers.hpp:127