1313
1414#include < stdexcept>
1515#include < typeinfo>
16+ #include < unordered_map>
17+
18+ namespace Acts {
19+ class Logger ;
20+ }
1621
1722namespace ActsExamples {
1823
24+ // / Base class for all data handles.
25+ // /
26+ // / Provides common functionality for tracking the parent sequence element
27+ // / and key name. The key is optional until explicitly initialized.
1928class DataHandleBase {
20- protected:
21- virtual ~DataHandleBase () = default ;
29+ private:
30+ struct StringHash {
31+ using is_transparent = void ; // Enables heterogeneous operations.
2232
33+ std::size_t operator ()(std::string_view sv) const {
34+ std::hash<std::string_view> hasher;
35+ return hasher (sv);
36+ }
37+ };
38+
39+ protected:
2340 DataHandleBase (SequenceElement* parent, const std::string& name)
2441 : m_parent(parent), m_name(name) {}
2542
@@ -28,6 +45,8 @@ class DataHandleBase {
2845 DataHandleBase (DataHandleBase&&) = default ;
2946
3047 public:
48+ virtual ~DataHandleBase () = default ;
49+
3150 const std::string& key () const { return m_key.value (); }
3251
3352 virtual const std::type_info& typeInfo () const = 0;
@@ -36,50 +55,115 @@ class DataHandleBase {
3655
3756 const std::string& name () const { return m_name; }
3857
39- void maybeInitialize (const std::string& key) {
40- if (!key.empty ()) {
41- m_key = key;
42- }
43- }
58+ void maybeInitialize (std::string_view key);
4459
4560 virtual bool isCompatible (const DataHandleBase& other) const = 0;
4661
62+ using StateMapType = std::unordered_map<std::string, const DataHandleBase*,
63+ StringHash, std::equal_to<>>;
64+
65+ virtual void emulate (StateMapType& state, WhiteBoard::AliasMapType& aliases,
66+ const Acts::Logger& logger) const = 0;
67+
4768 std::string fullName () const { return m_parent->name () + " ." + name (); }
4869
4970 protected:
71+ void registerAsWriteHandle ();
72+ void registerAsReadHandle ();
73+
74+ // Trampoline functions to avoid having the WhiteBoard as a friend
75+ template <typename T>
76+ void add (WhiteBoard& wb, T&& object) const {
77+ wb.add (m_key.value (), std::forward<T>(object));
78+ }
79+
80+ template <typename T>
81+ const T& get (const WhiteBoard& wb) const {
82+ return wb.get <T>(m_key.value ());
83+ }
84+
85+ template <typename T>
86+ T pop (WhiteBoard& wb) const {
87+ return wb.pop <T>(m_key.value ());
88+ }
89+
5090 SequenceElement* m_parent{nullptr };
5191 std::string m_name;
5292 std::optional<std::string> m_key{};
5393};
5494
95+ // / Base class for write data handles.
96+ // /
97+ // / Write handles are used to store data in the WhiteBoard. They ensure that:
98+ // / - Each key can only be written once
99+ // / - The key must be non-empty
100+ // / - The data type is consistent for each key
55101class WriteDataHandleBase : public DataHandleBase {
56102 protected:
57103 WriteDataHandleBase (SequenceElement* parent, const std::string& name)
58104 : DataHandleBase{parent, name} {}
59105
60106 public:
61- void initialize (const std::string& key);
107+ void initialize (std::string_view key);
62108
63109 bool isCompatible (const DataHandleBase& other) const final ;
110+
111+ void emulate (StateMapType& state, WhiteBoard::AliasMapType& aliases,
112+ const Acts::Logger& logger) const final ;
64113};
65114
115+ // / Base class for read data handles.
116+ // /
117+ // / Read handles are used to access data from the WhiteBoard. They ensure that:
118+ // / - The data exists before reading
119+ // / - The data type matches the expected type
120+ // / - The data can be read multiple times
66121class ReadDataHandleBase : public DataHandleBase {
67122 protected:
68- ReadDataHandleBase (SequenceElement* parent, const std::string& name)
69- : DataHandleBase{parent, name} {}
123+ using DataHandleBase::DataHandleBase;
70124
71125 public:
72- void initialize (const std::string& key);
126+ void initialize (std::string_view key);
73127
74128 bool isCompatible (const DataHandleBase& other) const final ;
129+
130+ void emulate (StateMapType& state, WhiteBoard::AliasMapType& aliases,
131+ const Acts::Logger& logger) const override ;
132+ };
133+
134+ // / Base class for consume data handles.
135+ // /
136+ // / Consume handles are used to take ownership of data from the WhiteBoard.
137+ // / They ensure that:
138+ // / - The data exists before consuming
139+ // / - The data type matches the expected type
140+ // / - The data can only be consumed once
141+ // / - The data is removed from the WhiteBoard after consumption
142+ class ConsumeDataHandleBase : public ReadDataHandleBase {
143+ protected:
144+ using ReadDataHandleBase::ReadDataHandleBase;
145+
146+ public:
147+ void emulate (StateMapType& state, WhiteBoard::AliasMapType& aliases,
148+ const Acts::Logger& logger) const override ;
75149};
76150
151+ // / A write handle for storing data in the WhiteBoard.
152+ // /
153+ // / @tparam T The type of data to store
154+ // /
155+ // / Example usage:
156+ // / @code
157+ // / WriteDataHandle<int> handle(parent, "my_data");
158+ // / handle.initialize("my_key");
159+ // / handle(wb, 42); // Store value
160+ // / @endcode
77161template <typename T>
78162class WriteDataHandle final : public WriteDataHandleBase {
79163 public:
80164 WriteDataHandle (SequenceElement* parent, const std::string& name)
81165 : WriteDataHandleBase{parent, name} {
82- m_parent-> registerWriteHandle (* this );
166+ registerAsWriteHandle ( );
83167 }
84168
85169 void operator ()(const AlgorithmContext& ctx, T&& value) const {
@@ -91,18 +175,28 @@ class WriteDataHandle final : public WriteDataHandleBase {
91175 throw std::runtime_error{" WriteDataHandle '" + fullName () +
92176 " ' not initialized" };
93177 }
94- wb. add (m_key. value () , std::move (value));
178+ add (wb , std::move (value));
95179 }
96180
97181 const std::type_info& typeInfo () const override { return typeid (T); };
98182};
99183
184+ // / A read handle for accessing data from the WhiteBoard.
185+ // /
186+ // / @tparam T The type of data to read
187+ // /
188+ // / Example usage:
189+ // / @code
190+ // / ReadDataHandle<int> handle(parent, "my_data");
191+ // / handle.initialize("my_key");
192+ // / const auto& value = handle(wb); // Access value
193+ // / @endcode
100194template <typename T>
101195class ReadDataHandle final : public ReadDataHandleBase {
102196 public:
103197 ReadDataHandle (SequenceElement* parent, const std::string& name)
104198 : ReadDataHandleBase{parent, name} {
105- m_parent-> registerReadHandle (* this );
199+ registerAsReadHandle ( );
106200 }
107201
108202 const T& operator ()(const AlgorithmContext& ctx) const {
@@ -114,7 +208,41 @@ class ReadDataHandle final : public ReadDataHandleBase {
114208 throw std::runtime_error{" ReadDataHandle '" + fullName () +
115209 " ' not initialized" };
116210 }
117- return wb.get <T>(m_key.value ());
211+ return get<T>(wb);
212+ }
213+
214+ const std::type_info& typeInfo () const override { return typeid (T); };
215+ };
216+
217+ // / A consume handle for taking ownership of data from the WhiteBoard.
218+ // /
219+ // / @tparam T The type of data to consume
220+ // /
221+ // / Example usage:
222+ // / @code
223+ // / ConsumeDataHandle<int> handle(parent, "my_data");
224+ // / handle.initialize("my_key");
225+ // / auto value = handle(wb); // Take ownership of value
226+ // / // value is no longer in WhiteBoard
227+ // / @endcode
228+ template <typename T>
229+ class ConsumeDataHandle final : public ConsumeDataHandleBase {
230+ public:
231+ ConsumeDataHandle (SequenceElement* parent, const std::string& name)
232+ : ConsumeDataHandleBase{parent, name} {
233+ registerAsReadHandle ();
234+ }
235+
236+ T operator ()(const AlgorithmContext& ctx) const {
237+ return (*this )(ctx.eventStore );
238+ }
239+
240+ T operator ()(WhiteBoard& wb) const {
241+ if (!isInitialized ()) {
242+ throw std::runtime_error{" ConsumeDataHandle '" + fullName () +
243+ " ' not initialized" };
244+ }
245+ return pop<T>(wb);
118246 }
119247
120248 const std::type_info& typeInfo () const override { return typeid (T); };
0 commit comments