libtcspc C++ API
Streaming TCSPC and time tag data processing
Loading...
Searching...
No Matches
type_erased_processor.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 "introspect.hpp"
12#include "processor.hpp"
13#include "type_list.hpp"
14
15#include <concepts>
16#include <memory>
17#include <type_traits>
18#include <utility>
19
20namespace tcspc {
21
22namespace internal {
23
24template <typename EventList> class abstract_processor;
25
26template <> class abstract_processor<type_list<>> {
27 public:
28 abstract_processor() = default;
29 abstract_processor(abstract_processor const &) = delete;
30 auto operator=(abstract_processor const &) = delete;
31 abstract_processor(abstract_processor &&) = delete;
32 auto operator=(abstract_processor &&) = delete;
33 virtual ~abstract_processor() = default;
34 [[nodiscard]] virtual auto introspect_node() const -> processor_info = 0;
35 [[nodiscard]] virtual auto introspect_graph() const -> processor_graph = 0;
36 virtual void flush() = 0;
37};
38
39template <typename Event0>
40class abstract_processor<type_list<Event0>>
41 : public abstract_processor<type_list<>> {
42 public:
43 virtual void handle(Event0 const &) = 0;
44 virtual void handle(Event0 &&) = 0;
45};
46
47template <typename Event0, typename... Events>
48class abstract_processor<type_list<Event0, Events...>>
49 : public abstract_processor<type_list<Events...>> {
50 using base_type = abstract_processor<type_list<Events...>>;
51
52 public:
53 using base_type::handle; // Import overload set
54 virtual void handle(Event0 const &) = 0;
55 virtual void handle(Event0 &&) = 0;
56};
57
58template <typename Interface, typename Proc, typename EventList>
59class virtual_processor_impl;
60
61template <typename Interface, typename Proc>
62class virtual_processor_impl<Interface, Proc, type_list<>> : public Interface {
63 protected:
64 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes,misc-non-private-member-variables-in-classes)
65 Proc proc;
66
67 public:
68 explicit virtual_processor_impl(Proc proc) : proc(std::move(proc)) {}
69
70 template <typename... Args>
71 explicit virtual_processor_impl(Args &&...args)
72 : proc(std::forward<Args>(args)...) {}
73
74 [[nodiscard]] auto introspect_node() const -> processor_info final {
75 return processor_info(this, "virtual_processor_impl");
76 }
77
78 [[nodiscard]] auto introspect_graph() const -> processor_graph final {
79 if constexpr (introspectable<Proc>)
80 return proc.introspect_graph().push_entry_point(this);
81 else
82 return processor_graph().push_entry_point(this);
83 }
84
85 void flush() final { proc.flush(); }
86};
87
88template <typename Interface, typename Proc, typename Event0,
89 typename... Events>
90class virtual_processor_impl<Interface, Proc, type_list<Event0, Events...>>
91 : public virtual_processor_impl<Interface, Proc, type_list<Events...>> {
92 using base_type =
93 virtual_processor_impl<Interface, Proc, type_list<Events...>>;
94
95 protected:
96 using base_type::proc;
97
98 public:
99 using base_type::base_type;
100
101 using base_type::handle; // Import overload set
102 void handle(Event0 const &event) final { proc.handle(event); }
103 void handle(Event0 &&event) final { proc.handle(std::move(event)); }
104};
105
106template <typename Proc, typename EventList>
107using virtual_processor =
108 virtual_processor_impl<abstract_processor<EventList>, Proc, EventList>;
109
110} // namespace internal
111
126template <typename EventList> class type_erased_processor {
127 using event_list = unique_type_list_t<EventList>;
128 using abstract_processor = internal::abstract_processor<event_list>;
129
130 template <typename Proc>
131 using virtual_processor = internal::virtual_processor<Proc, event_list>;
132
133 std::unique_ptr<abstract_processor> proc;
134
135 public:
142 : proc(std::make_unique<virtual_processor<internal::sink_all>>()) {}
143
151 template <typename Downstream>
152 requires(not std::same_as<std::remove_cvref_t<Downstream>,
155 event_list>)
156 explicit type_erased_processor(Downstream downstream)
157 : proc(std::make_unique<virtual_processor<Downstream>>(
158 std::move(downstream))) {}
159
161 [[nodiscard]] auto introspect_node() const -> processor_info {
162 return processor_info(this, "type_erased_processor");
163 }
164
166 [[nodiscard]] auto introspect_graph() const -> processor_graph {
167 return proc->introspect_graph().push_entry_point(this);
168 }
169
171 template <typename Event>
173 event_list>
174 void handle(Event &&event) {
175 proc->handle(std::forward<Event>(event));
176 }
177
179 void flush() { proc->flush(); }
180};
181
182} // namespace tcspc
Value type representing a directed acyclic graph of processors.
Definition introspect.hpp:220
auto push_entry_point(Processor const *processor) -> processor_graph &
Add a processor node to this graph, upstream of the current entry point (if any), making it the new e...
Definition introspect.hpp:252
Value type representing metadata of a processor.
Definition introspect.hpp:59
Processor that type-erases the downstream processor.
Definition type_erased_processor.hpp:126
auto introspect_graph() const -> processor_graph
Implements processor requirement.
Definition type_erased_processor.hpp:166
void handle(Event &&event)
Implements processor requirement.
Definition type_erased_processor.hpp:174
auto introspect_node() const -> processor_info
Implements processor requirement.
Definition type_erased_processor.hpp:161
void flush()
Implements processor requirement.
Definition type_erased_processor.hpp:179
type_erased_processor(Downstream downstream)
Construct with the given downstream processor.
Definition type_erased_processor.hpp:156
type_erased_processor()
Construct with a stub downstream processor.
Definition type_erased_processor.hpp:141
Concept that is satisfied when a type is convertible to at least one of the members of a type list.
Definition type_list.hpp:222
constexpr bool is_processor_of_list_v
Trait variable to check whether a processor handles a list of event types and flush.
Definition processor.hpp:223
auto sink_all()
Create a processor that sinks any event and the end-of-stream and does nothing.
Definition core.hpp:115
unique_type_list< TypeList >::type unique_type_list_t
Helper type for tcspc::unique_type_list.
Definition type_list.hpp:335
libtcspc namespace.
Definition acquire.hpp:30