Ice 3.9
C++ API Reference
Loading...
Searching...
No Matches
DataStorm.h
1// Copyright (c) ZeroC, Inc.
2
3#ifndef DATASTORM_DATASTORM_H
4#define DATASTORM_DATASTORM_H
5
6#include "Config.h"
7#include "DataStorm/SampleEvent.h"
8#include "InternalI.h"
9#include "InternalT.h"
10#include "Node.h"
11#include "Types.h"
12
13#include <cassert>
14#include <regex>
15
16#if defined(__clang__)
17# pragma clang diagnostic push
18# pragma clang diagnostic ignored "-Wshadow-field-in-constructor"
19#elif defined(__GNUC__)
20# pragma GCC diagnostic push
21# pragma GCC diagnostic ignored "-Wshadow"
22#endif
23
24namespace DataStorm
25{
26 /// A sample provides information about a data element update.
27 /// The Sample template provides access to the key, value as well as additional information such as the event,
28 /// timestamp, update tag. Samples are generated and published by writers and received by readers.
29 /// @headerfile DataStorm/DataStorm.h
30 template<typename Key, typename Value, typename UpdateTag = std::string> class Sample
31 {
32 public:
33 /// The type of the sample key.
34 using KeyType = Key;
35
36 /// The type of the sample value.
37 using ValueType = Value;
38
39 /// The type of the update tag. The update tag type defaults to string if it's not explicitly specified
40 /// with the Sample template parameters.
41 using UpdateTagType = UpdateTag;
42
43 /// Gets the event associated with the sample.
44 /// @return The sample event.
45 [[nodiscard]] SampleEvent getEvent() const noexcept;
46
47 /// Gets the key of the sample.
48 /// @return The sample key.
49 [[nodiscard]] const Key& getKey() const noexcept;
50
51 /// Gets the value of the sample.
52 /// Depending on the sample event, the sample value might not always be available. It's the case if the
53 /// sample event is Remove where this method will return a default value.
54 /// @return The sample value.
55 [[nodiscard]] const Value& getValue() const noexcept;
56
57 /// Gets the update tag for the partial update.
58 /// This method should only be called if the sample event is PartialUpdate.
59 /// @return The update tag.
60 [[nodiscard]] UpdateTag getUpdateTag() const;
61
62 /// Gets the timestamp of the sample.
63 /// The timestamp is generated by the writer and corresponds to the time of sending.
64 /// @return The timestamp.
65 [[nodiscard]] std::chrono::time_point<std::chrono::system_clock> getTimeStamp() const noexcept;
66
67 /// Gets the origin of the sample.
68 /// The origin of the sample identifies uniquely on the node the writer that created the sample. It's the
69 /// name of the writer if a name was explicitly provided on creation of the writer. Otherwise, if no name
70 /// was provided, an unique identifier is generated by DataStorm.
71 /// @return The origin of the sample.
72 [[nodiscard]] const std::string& getOrigin() const noexcept;
73
74 /// @private
75 /// Gets the session identifier of the session that received this sample.
76 /// This session identifier can be used to retrieve the Ice connection with the node.
77 /// @return The session identifier.
78 [[nodiscard]] const std::string& getSession() const noexcept;
79
80 /// @private
81 Sample(const std::shared_ptr<DataStormI::Sample>&) noexcept;
82
83 private:
84 std::shared_ptr<DataStormI::SampleT<Key, Value, UpdateTag>> _impl;
85 };
86
87 /// Converts the given sample type vector to a string and add it to the stream.
88 /// @param os The output stream
89 /// @param types The sample type vector to add to the stream
90 /// @return The output stream
91 inline std::ostream& operator<<(std::ostream& os, const SampleEventSeq& types)
92 {
93 Ice::print(os, types);
94 return os;
95 }
96
97 /// Converts the given sample to a string and add it to the stream. The implementation outputs the sample value.
98 /// @param os The output stream
99 /// @param sample The sample to add to the stream
100 /// @return The output stream
101 template<typename K, typename V, typename U>
102 std::ostream& operator<<(std::ostream& os, const Sample<K, V, U>& sample)
103 {
104 os << sample.getValue();
105 return os;
106 }
107
108 /// The Reader class is used to retrieve samples for a data element.
109 /// @headerfile DataStorm/DataStorm.h
110 template<typename Key, typename Value, typename UpdateTag> class Reader
111 {
112 public:
113 /// The key type.
114 using KeyType = Key;
115
116 /// The value type.
117 using ValueType = Value;
118
119 /// Move constructor.
120 /// @param reader The reader to move from.
121 Reader(Reader&& reader) noexcept;
122
123 /// Destructor.
124 /// The destruction of the reader disconnects the reader from the writers.
125 ~Reader();
126
127 /// Move assignment operator.
128 /// @param reader The reader to remove from.
129 /// @return A reference to this reader.
130 Reader& operator=(Reader&& reader) noexcept;
131
132 /// Indicates whether or not writers are online.
133 /// @return `true` if writers are connected, `false` otherwise.
134 [[nodiscard]] bool hasWriters() const noexcept;
135
136 /// Waits for the given number of writers to be online.
137 /// @param count The number of writers to wait for.
138 /// @throws NodeShutdownException Thrown when the node is shut down while waiting.
139 void waitForWriters(unsigned int count = 1) const;
140
141 /// Waits for writers to be offline.
142 /// @throws NodeShutdownException Thrown when the node is shut down while waiting.
143 void waitForNoWriters() const;
144
145 /// Gets the connected writers.
146 /// @return The names of the connected writers.
147 [[nodiscard]] std::vector<std::string> getConnectedWriters() const;
148
149 /// Gets the keys for which writers are connected to this reader.
150 /// @return The keys for which we have writers connected.
151 [[nodiscard]] std::vector<Key> getConnectedKeys() const;
152
153 /// Returns all the unread samples.
154 /// @return The unread samples.
155 [[nodiscard]] std::vector<Sample<Key, Value, UpdateTag>> getAllUnread();
156
157 /// Waits for the given number of unread samples to be available.
158 /// @throws NodeShutdownException Thrown when the node is shut down while waiting.
159 void waitForUnread(unsigned int count = 1) const;
160
161 /// Returns whether or not unread samples are available.
162 /// @return `true` if there unread samples are queued, `false` otherwise.
163 [[nodiscard]] bool hasUnread() const noexcept;
164
165 /// Returns the next unread sample.
166 /// @return The unread sample.
167 /// @throws NodeShutdownException Thrown when the node is shut down while waiting.
168 [[nodiscard]] Sample<Key, Value, UpdateTag> getNextUnread();
169
170 /// Calls the given functions to provide the initial set of connected keys and when a key is added or
171 /// removed from the set of connected keys. If callback functions are already set, they will be replaced.
172 /// The connected keys represent the set of keys for which writers are connected to this reader.
173 /// The @p init callback is always called after this method returns to provide the initial set of connected
174 /// keys. The @p update callback is called when new keys are added or removed from the set of connected keys.
175 /// @param init The function to call with the initial set of connected keys.
176 /// @param update The function to call when a key is added or removed from the set.
177 void onConnectedKeys(
178 std::function<void(std::vector<Key>)> init,
179 std::function<void(CallbackReason, Key)> update) noexcept;
180
181 /// Calls the given functions to provide the initial set of connected writers and when a new writer
182 /// connects or disconnects. If callback functions are already set, they will be replaced.
183 /// The @p init callback is always called after this method returns to provide the initial set of connected
184 /// writers. The @p update callback is called when new writers connect or disconnect.
185 /// @param init The function to call with the initial set of connected writers.
186 /// @param update The function to call when a new writer connects or disconnects.
188 std::function<void(std::vector<std::string>)> init,
189 std::function<void(CallbackReason, std::string)> update) noexcept;
190
191 /// Calls the given function to provide the initial set of unread samples and when new samples are queued.
192 /// If a function is already set, it will be replaced.
193 /// The @p init callback is called after this method returns to provide the initial set of unread samples;
194 /// it is only called when the reader has unread samples. The @p queue callback is called when a new sample
195 /// is received.
196 /// @param init The function to call with the initial set of unread samples.
197 /// @param queue The function to call when a new sample is received.
198 void onSamples(
199 std::function<void(std::vector<Sample<Key, Value, UpdateTag>>)> init,
200 std::function<void(Sample<Key, Value, UpdateTag>)> queue) noexcept;
201
202 protected:
203 /// @private
204 Reader(const std::shared_ptr<DataStormI::DataReader>& impl) noexcept : _impl(impl) {}
205
206 /// @private
207 std::shared_ptr<DataStormI::DataReader> _impl;
208 };
209
210 /// The Writer class is used to write samples for a data element.
211 /// @headerfile DataStorm/DataStorm.h
212 template<typename Key, typename Value, typename UpdateTag> class Writer
213 {
214 public:
215 /// The key type.
216 using KeyType = Key;
217
218 /// The value type.
219 using ValueType = Value;
220
221 /// Move constructor.
222 /// @param writer The writer to move from.
223 Writer(Writer&& writer) noexcept;
224
225 /// Move assignment operator.
226 /// @param writer The writer to move from.
227 /// @return A reference to this writer.
228 Writer& operator=(Writer&& writer) noexcept;
229
230 /// Destructor.
231 /// The destruction of the writer disconnects the writer from the readers.
232 ~Writer();
233
234 /// Indicates whether or not readers are online.
235 /// @return `true` if readers are connected, `false` otherwise.
236 [[nodiscard]] bool hasReaders() const noexcept;
237
238 /// Waits for the given number of readers to be online.
239 /// @param count The number of readers to wait for.
240 /// @throws NodeShutdownException Thrown when the node is shut down while waiting.
241 void waitForReaders(unsigned int count = 1) const;
242
243 /// Waits for readers to be offline.
244 /// @throws NodeShutdownException Thrown when the node is shut down while waiting.
245 void waitForNoReaders() const;
246
247 /// Gets the connected readers.
248 /// @return The names of the connected readers.
249 [[nodiscard]] std::vector<std::string> getConnectedReaders() const;
250
251 /// Gets the keys for which readers are connected to this writer.
252 /// @return The keys for which we have writers connected.
253 [[nodiscard]] std::vector<Key> getConnectedKeys() const;
254
255 /// Gets the last written sample.
256 /// @return The last written sample.
257 /// @throws std::logic_error If there's no sample.
258 [[nodiscard]] Sample<Key, Value, UpdateTag> getLast();
259
260 /// Gets all the written sample kept in the writer history.
261 /// @return The sample history.
262 [[nodiscard]] std::vector<Sample<Key, Value, UpdateTag>> getAll();
263
264 /// Calls the given functions to provide the initial set of connected keys and when a key is added or
265 /// removed from the set of connected keys. If callback functions are already set, they will be replaced.
266 /// The connected keys represent the set of keys for which writers are connected to this reader.
267 /// The @p init callback is always called after this method returns to provide the initial set of connected
268 /// keys. The @p update callback is called when new keys are added or removed from the set of connected keys.
269 /// @param init The function to call with the initial set of connected keys.
270 /// @param update The function to call when a key is added or removed from the set.
271 void onConnectedKeys(
272 std::function<void(std::vector<Key>)> init,
273 std::function<void(CallbackReason, Key)> update) noexcept;
274
275 /// Calls the given functions to provide the initial set of connected readers and when a new reader
276 /// connects or disconnects. If callback functions are already set, they will be replaced.
277 /// The @p init callback is always called after this method returns to provide the initial set of connected
278 /// readers. The @p update callback is called when new readers connect or disconnect.
279 /// @param init The function to call with the initial set of connected readers.
280 /// @param update The function to call when a new reader connects or disconnects.
282 std::function<void(std::vector<std::string>)> init,
283 std::function<void(CallbackReason, std::string)> update) noexcept;
284
285 protected:
286 /// @private
287 Writer(const std::shared_ptr<DataStormI::DataWriter>& impl) noexcept : _impl(impl) {}
288
289 /// @private
290 std::shared_ptr<DataStormI::DataWriter> _impl;
291 };
292
293 /// The Topic class.
294 /// This class allows constructing reader and writer objects. It's also used to setup filter and updater
295 /// functions.
296 /// @headerfile DataStorm/DataStorm.h
297 template<typename Key, typename Value, typename UpdateTag = std::string> class Topic
298 {
299 public:
300 /// The topic's key type.
301 using KeyType = Key;
302
303 /// The topic's value type.
304 using ValueType = Value;
305
306 /// The topic's update tag type (defaults to std::string if not specified).
307 using UpdateTagType = UpdateTag;
308
309 /// The topic's writer type.
311
312 /// The topic's reader type.
314
315 /// The topic's sample type.
317
318 /// Constructs a new Topic for the topic with the given name.
319 /// @param node The node.
320 /// @param name The name of the topic.
321 Topic(const Node& node, std::string name) noexcept;
322
323 /// Move constructor.
324 /// @param topic The topic to move from.
325 Topic(Topic&& topic) noexcept
326 : _name(std::move(topic._name)),
327 _topicFactory(std::move(topic._topicFactory)),
328 _keyFactory(std::move(topic._keyFactory)),
329 _tagFactory(std::move(topic._tagFactory)),
330 _keyFilterFactories(std::move(topic._keyFilterFactories)),
331 _sampleFilterFactories(std::move(topic._sampleFilterFactories)),
332 _reader(std::move(topic._reader)),
333 _writer(std::move(topic._writer)),
334 _updaters(std::move(topic._updaters))
335 {
336 }
337
338 /// Destructor.
339 /// The destructor disconnects the topic from peers.
340 ~Topic();
341
342 /// Move assignment operator.
343 /// @param topic The topic to move from.
344 /// @return A reference to this topic.
345 Topic& operator=(Topic&& topic) noexcept;
346
347 /// Indicates whether or not data writers are online.
348 /// @return `true` if data writers are connected, `false` otherwise.
349 [[nodiscard]] bool hasWriters() const noexcept;
350
351 /// Waits for the given number of data writers to be online.
352 /// @param count The number of data writers to wait for.
353 /// @throws NodeShutdownException Thrown when the node is shut down while waiting.
354 void waitForWriters(unsigned int count = 1) const;
355
356 /// Waits for data writers to be offline.
357 /// @throws NodeShutdownException Thrown when the node is shut down while waiting.
358 void waitForNoWriters() const;
359
360 /// Sets the default configuration used to construct writers.
361 /// @param config The default writer configuration.
362 void setWriterDefaultConfig(const WriterConfig& config) noexcept;
363
364 /// Indicates whether or not data readers are online.
365 /// @return `true` if data readers are connected, `false` otherwise.
366 [[nodiscard]] bool hasReaders() const noexcept;
367
368 /// Waits for the given number of data readers to be online.
369 /// @param count The number of data readers to wait for.
370 /// @throws NodeShutdownException Thrown when the node is shut down while waiting.
371 void waitForReaders(unsigned int count = 1) const;
372
373 /// Waits for data readers to be offline.
374 /// @throws NodeShutdownException Thrown when the node is shut down while waiting.
375 void waitForNoReaders() const;
376
377 /// Sets the default configuration used to construct readers.
378 /// @param config The default reader configuration.
379 void setReaderDefaultConfig(const ReaderConfig& config) noexcept;
380
381 /// Sets an updater function for the given update tag. The function is called when a partial update is
382 /// received or sent to compute the new value. The function is provided a copy of the latest value and the
383 /// partial update, and it updates this value in place.
384 /// @param tag The update tag.
385 /// @param updater The updater function.
386 template<typename UpdateValue>
387 void setUpdater(const UpdateTag& tag, std::function<void(Value&, UpdateValue)> updater) noexcept;
388
389 /// Sets a key filter factory. The given factory function must return a filter function that returns `true` if
390 /// the key matches the filter criteria, `false` otherwise.
391 /// Register all key filter factories before creating any reader or writer for this topic: the set of
392 /// factories is not synchronized, so modifying it once the topic is in use races with the Ice threads that
393 /// use the topic.
394 /// @param name The name of the key filter.
395 /// @param factory The filter factory function.
396 template<typename Criteria>
397 void setKeyFilter(
398 std::string name,
399 std::function<std::function<bool(const Key&)>(const Criteria&)> factory) noexcept;
400
401 /// Sets a sample filter factory. The given factory function must return a filter function that returns `true`
402 /// if the sample matches the filter criteria, `false` otherwise.
403 /// Register all sample filter factories before creating any reader or writer for this topic: the set of
404 /// factories is not synchronized, so modifying it once the topic is in use races with the Ice threads that
405 /// use the topic.
406 /// A sample filter interacts with partial updates: a writer sends only the samples a reader's filter matches,
407 /// so the reader can receive a partial update for a key whose full value it never received. The reader has
408 /// nothing to resolve such updates against and discards them until it receives a full value for the key. And
409 /// when the filter rejects some samples for a key but a later partial update matches, the reader applies that
410 /// update to the last value it received for the key — not to the value the writer computed the update
411 /// against — so the reader's value can silently diverge from the writer's.
412 /// @param name The name of the sample filter.
413 /// @param factory The filter factory function.
414 template<typename Criteria>
415 void setSampleFilter(
416 std::string name,
417 std::function<std::function<bool(const SampleType&)>(const Criteria&)> factory) noexcept;
418
419 private:
420 [[nodiscard]] std::shared_ptr<DataStormI::TopicReader> getReader() const;
421 [[nodiscard]] std::shared_ptr<DataStormI::TopicWriter> getWriter() const;
422 [[nodiscard]] Ice::CommunicatorPtr getCommunicator() const noexcept;
423
424 template<typename, typename, typename> friend class SingleKeyWriter;
425 template<typename, typename, typename> friend class MultiKeyWriter;
426 template<typename, typename, typename> friend class SingleKeyReader;
427 template<typename, typename, typename> friend class MultiKeyReader;
428 template<typename, typename, typename> friend class FilteredKeyReader;
429
430 // These fields are non-const because we move them in the move-assignment operator.
431 std::string _name;
432 std::shared_ptr<DataStormI::TopicFactory> _topicFactory;
433 std::shared_ptr<DataStormI::KeyFactoryT<Key>> _keyFactory;
434 std::shared_ptr<DataStormI::TagFactoryT<UpdateTag>> _tagFactory;
435 std::shared_ptr<DataStormI::FilterManagerT<DataStormI::KeyT<Key>>> _keyFilterFactories;
436 std::shared_ptr<DataStormI::FilterManagerT<DataStormI::SampleT<Key, Value, UpdateTag>>> _sampleFilterFactories;
437
438 mutable std::mutex _mutex;
439 mutable std::shared_ptr<DataStormI::TopicReader> _reader;
440 mutable std::shared_ptr<DataStormI::TopicWriter> _writer;
441 mutable std::map<std::shared_ptr<DataStormI::Tag>, DataStormI::Topic::Updater> _updaters;
442 };
443
444 /// Filter structure to specify the filter name and criteria value.
445 /// @headerfile DataStorm/DataStorm.h
446 template<typename T> struct Filter
447 {
448 /// Constructs a filter structure with the given name and criteria.
449 /// @param name The filter name
450 /// @param criteria The criteria
451 template<typename TT>
452 Filter(std::string name, TT&& criteria) noexcept : name(std::move(name)),
453 criteria(std::forward<TT>(criteria))
454 {
455 }
456
457 /// The filter name.
458 std::string name;
459
460 /// The filter criteria value.
462 };
463
464 /// The key reader to read the data element associated with a given key.
465 /// @headerfile DataStorm/DataStorm.h
466 template<typename Key, typename Value, typename UpdateTag = std::string>
467 class SingleKeyReader : public Reader<Key, Value, UpdateTag>
468 {
469 public:
470 /// Constructs a new reader for the given key. The construction of the reader connects the reader to writers
471 /// with a matching key.
472 /// @param topic The topic.
473 /// @param key The key of the data element to read.
474 /// @param name The optional reader name.
475 /// @param config The reader configuration.
477 const Topic<Key, Value, UpdateTag>& topic,
478 const Key& key,
479 std::string name = std::string(),
480 const ReaderConfig& config = ReaderConfig());
481
482 /// Constructs a new reader for the given key and sample filter criteria. The construction of the reader
483 /// connects the reader to writers with a matching key. The writer will only send samples matching the
484 /// given sample filter criteria to the reader.
485 /// @param topic The topic.
486 /// @param key The key of the data element to read.
487 /// @param sampleFilter The sample filter.
488 /// @param name The optional reader name.
489 /// @param config The reader configuration.
490 template<typename SampleFilterCriteria>
492 const Topic<Key, Value, UpdateTag>& topic,
493 const Key& key,
494 const Filter<SampleFilterCriteria>& sampleFilter,
495 std::string name = std::string(),
496 const ReaderConfig& config = ReaderConfig());
497
498 /// Move constructor.
499 /// @param reader The reader to move from.
500 SingleKeyReader(SingleKeyReader&& reader) noexcept;
501
502 /// Move assignment operator.
503 /// @param reader The reader to move from.
504 /// @return A reference to this reader.
505 SingleKeyReader& operator=(SingleKeyReader&& reader) noexcept;
506 };
507
508 /// The key reader to read the data element associated with a given set of keys.
509 ///
510 /// A multi-key reader retains the current value of every key it has received and not since seen removed, so that
511 /// it can resolve later partial updates against it. This per-key state is independent of the reader's
512 /// `sampleCount` and `sampleLifetime` history settings, and is released when the reader receives the key's remove
513 /// sample. A reader connected to writers over an unbounded set of keys therefore accumulates one current value per
514 /// key.
515 /// @headerfile DataStorm/DataStorm.h
516 template<typename Key, typename Value, typename UpdateTag = std::string>
517 class MultiKeyReader : public Reader<Key, Value, UpdateTag>
518 {
519 public:
520 /// Constructs a new reader for the given keys. The construction of the reader connects the reader to
521 /// writers with matching keys. If an empty vector of keys is provided, the reader will connect to all the
522 /// available writers.
523 /// @param topic The topic.
524 /// @param keys The keys of the data elements to read.
525 /// @param name The optional reader name.
526 /// @param config The reader configuration.
528 const Topic<Key, Value, UpdateTag>& topic,
529 const std::vector<Key>& keys,
530 std::string name = std::string(),
531 const ReaderConfig& config = ReaderConfig());
532
533 /// Constructs a new reader for the given keys and sample filter criteria. The construction of the reader
534 /// connects the reader to writers with matching keys. If an empty vector of keys is provided, the reader
535 /// will connect to all the available writers. The writer will only send samples matching the given sample
536 /// filter criteria to the reader.
537 /// @param topic The topic.
538 /// @param keys The keys of the data elements to read.
539 /// @param sampleFilter The sample filter.
540 /// @param name The optional reader name.
541 /// @param config The reader configuration.
542 template<typename SampleFilterCriteria>
544 const Topic<Key, Value, UpdateTag>& topic,
545 const std::vector<Key>& keys,
546 const Filter<SampleFilterCriteria>& sampleFilter,
547 std::string name = std::string(),
548 const ReaderConfig& config = ReaderConfig());
549
550 /// Move constructor.
551 /// @param reader The reader to move from.
552 MultiKeyReader(MultiKeyReader&& reader) noexcept;
553
554 /// Move assignment operator.
555 /// @param reader The reader to move from.
556 /// @return A reference to this reader.
557 MultiKeyReader& operator=(MultiKeyReader&& reader) noexcept;
558 };
559
560 /// Creates a key reader for the given topic and key. This helper method deduces the topic Key, Value and
561 /// UpdateTag types from the topic argument.
562 /// @param topic The topic.
563 /// @param key The key.
564 /// @param name The optional reader name.
565 /// @param config The optional reader configuration.
566 template<typename K, typename V, typename UT>
568 const Topic<K, V, UT>& topic,
569 const typename Topic<K, V, UT>::KeyType& key,
570 std::string name = std::string(),
571 const ReaderConfig& config = ReaderConfig())
572 {
573 return SingleKeyReader<K, V, UT>(topic, key, std::move(name), config);
574 }
575
576 /// Creates a key reader for the given topic, key and sample filter. This helper method deduces the topic Key
577 /// and Value types from the topic argument.
578 /// @param topic The topic.
579 /// @param key The key.
580 /// @param sampleFilter The sample filter.
581 /// @param name The optional reader name.
582 /// @param config The optional reader configuration.
583 template<typename SFC, typename K, typename V, typename UT>
585 const Topic<K, V, UT>& topic,
586 const typename Topic<K, V, UT>::KeyType& key,
587 const Filter<SFC>& sampleFilter,
588 std::string name = std::string(),
589 const ReaderConfig& config = ReaderConfig())
590 {
591 return SingleKeyReader<K, V, UT>(topic, key, sampleFilter, std::move(name), config);
592 }
593
594 /// Creates a multi-key reader for the given topic. This helper method deduces the topic Key, Value and
595 /// UpdateTag types from the topic argument.
596 /// The reader will only receive samples for the given set of keys.
597 /// @param topic The topic.
598 /// @param keys The keys.
599 /// @param name The optional reader name.
600 /// @param config The optional reader configuration.
601 template<typename K, typename V, typename UT>
603 const Topic<K, V, UT>& topic,
604 const std::vector<typename Topic<K, V, UT>::KeyType>& keys,
605 std::string name = std::string(),
606 const ReaderConfig& config = ReaderConfig())
607 {
608 return MultiKeyReader<K, V, UT>(topic, keys, std::move(name), config);
609 }
610
611 /// Creates a multi-key reader for the given topic, keys and sample filter. This helper method deduces the
612 /// topic Key and Value types from the topic argument.
613 /// The reader will only receive samples for the given set of keys.
614 /// @param topic The topic.
615 /// @param keys The keys.
616 /// @param sampleFilter The sample filter.
617 /// @param name The optional reader name.
618 /// @param config The optional reader configuration.
619 template<typename SFC, typename K, typename V, typename UT>
621 const Topic<K, V, UT>& topic,
622 const std::vector<typename Topic<K, V, UT>::KeyType>& keys,
623 const Filter<SFC>& sampleFilter,
624 std::string name = std::string(),
625 const ReaderConfig& config = ReaderConfig())
626 {
627 return MultiKeyReader<K, V, UT>(topic, keys, sampleFilter, std::move(name), config);
628 }
629
630 /// Creates an any-key reader for the given topic. This helper method deduces the topic Key, Value and
631 /// UpdateTag types from the topic argument.
632 /// The reader will receive samples for any keys from the topic.
633 /// @param topic The topic.
634 /// @param name The optional reader name.
635 /// @param config The optional reader configuration.
636 template<typename K, typename V, typename UT>
638 const Topic<K, V, UT>& topic,
639 std::string name = std::string(),
640 const ReaderConfig& config = ReaderConfig())
641 {
642 return MultiKeyReader<K, V, UT>(topic, {}, std::move(name), config);
643 }
644
645 /// Creates an any-key reader for the given topic and sample filter. This helper method deduces the topic Key
646 /// and Value types from the topic argument.
647 /// The reader will receive samples for the keys from the topic.
648 /// @param topic The topic.
649 /// @param sampleFilter The sample filter.
650 /// @param name The optional reader name.
651 /// @param config The optional reader configuration.
652 template<typename SFC, typename K, typename V, typename UT>
654 const Topic<K, V, UT>& topic,
655 const Filter<SFC>& sampleFilter,
656 std::string name = std::string(),
657 const ReaderConfig& config = ReaderConfig())
658 {
659 return MultiKeyReader<K, V, UT>(topic, {}, sampleFilter, std::move(name), config);
660 }
661
662 /// The filtered reader to read data elements whose key match a given filter.
663 ///
664 /// A filtered reader retains the current value of every key it has received and not since seen removed, so that it
665 /// can resolve later partial updates against it. This per-key state is independent of the reader's `sampleCount`
666 /// and `sampleLifetime` history settings, and is released when the reader receives the key's remove sample. A
667 /// reader matching an unbounded set of keys therefore accumulates one current value per key.
668 /// @headerfile DataStorm/DataStorm.h
669 template<typename Key, typename Value, typename UpdateTag = std::string>
670 class FilteredKeyReader : public Reader<Key, Value, UpdateTag>
671 {
672 public:
673 /// Constructs a new reader for the given key filter. The construction of the reader connects the reader to
674 /// writers whose key matches the key filter criteria.
675 /// @param topic The topic.
676 /// @param keyFilter The key filter.
677 /// @param name The optional reader name.
678 /// @param config The reader configuration.
679 /// @throws std::invalid_argument Thrown when the key filter is not registered with the topic or the filter is
680 /// invalid.
681 template<typename KeyFilterCriteria>
683 const Topic<Key, Value, UpdateTag>& topic,
684 const Filter<KeyFilterCriteria>& keyFilter,
685 std::string name = std::string(),
686 const ReaderConfig& config = ReaderConfig());
687
688 /// Constructs a new reader for the given key filter and sample filter criteria. The construction of the
689 /// reader connects the reader to writers whose key matches the key filter criteria.
690 /// @param topic The topic.
691 /// @param keyFilter The key filter.
692 /// @param sampleFilter The sample filter.
693 /// @param name The optional reader name.
694 /// @param config The reader configuration.
695 /// @throws std::invalid_argument Thrown when the key filter is not registered with the topic or the filter is
696 /// invalid.
697 template<typename KeyFilterCriteria, typename SampleFilterCriteria>
699 const Topic<Key, Value, UpdateTag>& topic,
700 const Filter<KeyFilterCriteria>& keyFilter,
701 const Filter<SampleFilterCriteria>& sampleFilter,
702 std::string name = std::string(),
703 const ReaderConfig& config = ReaderConfig());
704
705 /// Move constructor
706 /// @param reader The reader to move from.
707 FilteredKeyReader(FilteredKeyReader&& reader) noexcept;
708
709 /// Move assignment operator.
710 /// @param reader The reader to move from.
711 /// @return A reference to this reader.
713 };
714
715 /// Creates a new filtered reader for the given topic and key filter. This helper method deduces the topic Key,
716 /// Value and UpdateTag types from the topic argument.
717 /// @param topic The topic.
718 /// @param filter The key filter.
719 /// @param name The optional reader name.
720 /// @param config The optional reader configuration.
721 template<typename KFC, typename K, typename V, typename UT>
723 const Topic<K, V, UT>& topic,
724 const Filter<KFC>& filter,
725 std::string name = std::string(),
726 const ReaderConfig& config = ReaderConfig())
727 {
728 return FilteredKeyReader<K, V, UT>(topic, filter, std::move(name), config);
729 }
730
731 /// Creates a new filter reader for the given topic, key filter and sample filter. This helper method deduces
732 /// the topic Key, Value and UpdateTag types from the topic argument.
733 /// @param topic The topic.
734 /// @param keyFilter The key filter.
735 /// @param sampleFilter The sample filter.
736 /// @param name The optional reader name.
737 /// @param config The optional reader configuration.
738 template<typename KFC, typename SFC, typename K, typename V, typename UT>
740 const Topic<K, V, UT>& topic,
741 const Filter<KFC>& keyFilter,
742 const Filter<SFC>& sampleFilter,
743 std::string name = std::string(),
744 const ReaderConfig& config = ReaderConfig())
745 {
746 return FilteredKeyReader<K, V, UT>(topic, keyFilter, sampleFilter, std::move(name), config);
747 }
748
749 /// The key writer to write the data element associated with a given key.
750 /// @headerfile DataStorm/DataStorm.h
751 template<typename Key, typename Value, typename UpdateTag = std::string>
752 class SingleKeyWriter : public Writer<Key, Value, UpdateTag>
753 {
754 public:
755 /// Constructs a new writer for the given key. The construction of the writer connects the writer to readers
756 /// with a matching key.
757 /// @param topic The topic.
758 /// @param key The key of the data element to write.
759 /// @param name The optional writer name.
760 /// @param config The writer configuration.
762 const Topic<Key, Value, UpdateTag>& topic,
763 const Key& key,
764 std::string name = std::string(),
765 const WriterConfig& config = WriterConfig());
766
767 /// Move constructor.
768 /// @param writer The writer to move from.
769 SingleKeyWriter(SingleKeyWriter&& writer) noexcept;
770
771 /// Move assignment operator.
772 /// @param writer The writer to move from.
773 /// @return A reference to this writer.
774 SingleKeyWriter& operator=(SingleKeyWriter&& writer) noexcept;
775
776 /// Adds the data element. This generates a SampleEvent::Add sample with the given value.
777 /// @param value The data element value.
778 void add(const Value& value);
779
780 /// Updates the data element. This generates a SampleEvent::Update sample with the given value.
781 /// @param value The data element value.
782 void update(const Value& value);
783
784 /// Gets a partial update generator function for the given partial update tag. When called, the returned
785 /// function generates a SampleEvent::PartialUpdate sample with the given partial update value.
786 /// The UpdateValue template parameter must match the UpdateValue type used to register the updater with
787 /// the Topic::setUpdater method.
788 /// A partial update resolves against the key's current value, so the key must have a current value when the
789 /// returned function is called: a full value was written for the key and the key was not since removed.
790 /// Calling the returned function for a key with no current value is an application error that throws
791 /// std::logic_error and publishes nothing.
792 /// A reader that uses a sample filter receives only the samples its filter matches: such a reader can lack
793 /// a current value for the key even though the writer has one, and it discards partial updates until it
794 /// receives a full value for the key. See Topic::setSampleFilter.
795 /// @param tag The partial update tag.
796 template<typename UpdateValue>
797 [[nodiscard]] std::function<void(const UpdateValue&)> partialUpdate(const UpdateTag& tag);
798
799 /// Removes the data element. This generates a SampleEvent::Remove sample and releases the key's current value
800 /// on the writer and on the readers that receive the sample, so a later partial update has no value to resolve
801 /// against and is rejected until a new full value is written.
802 void remove() noexcept;
803
804 private:
805 const std::shared_ptr<DataStormI::TagFactoryT<UpdateTag>> _tagFactory;
806 };
807
808 /// The key writer to write data elements associated with a given set of keys.
809 ///
810 /// A multi-key writer retains the current value of every key it has written and not since removed, so that later
811 /// partial updates and late-joining readers can resolve against it. This per-key state is the writer's current data
812 /// set, not retained history: it is independent of the `sampleCount` and `sampleLifetime` history settings, which
813 /// bound the retained samples but never the current value of a live key. An any-key writer (one constructed with
814 /// an empty key vector) that writes to an unbounded set of keys therefore accumulates one current value per key;
815 /// call remove(const Key&) to retire a key and release its state once the key is no longer in use.
816 /// @headerfile DataStorm/DataStorm.h
817 template<typename Key, typename Value, typename UpdateTag = std::string>
818 class MultiKeyWriter : public Writer<Key, Value, UpdateTag>
819 {
820 public:
821 /// Constructs a new writer for the given keys. The construction of the writer connects the writer to
822 /// readers with matching keys. If an empty vector of keys is provided, the writer will connect to all the
823 /// available readers.
824 /// @param topic The topic.
825 /// @param keys The keys.
826 /// @param name The optional writer name.
827 /// @param config The writer configuration.
829 const Topic<Key, Value, UpdateTag>& topic,
830 const std::vector<Key>& keys,
831 std::string name = std::string(),
832 const WriterConfig& config = WriterConfig());
833
834 /// Move constructor
835 /// @param writer The writer to move from.
836 MultiKeyWriter(MultiKeyWriter&& writer) noexcept;
837
838 /// Move assignment operator.
839 /// @param writer The writer to move from.
840 /// @return A reference to this writer.
841 MultiKeyWriter& operator=(MultiKeyWriter&& writer) noexcept;
842
843 /// Adds the data element. This generates a SampleEvent::Add sample with the given value.
844 /// @param key The key
845 /// @param value The data element value.
846 void add(const Key& key, const Value& value);
847
848 /// Updates the data element. This generates a SampleEvent::Update sample with the given value.
849 /// @param key The key
850 /// @param value The data element value.
851 void update(const Key& key, const Value& value);
852
853 /// Gets a partial update generator function for the given partial update tag. When called, the returned
854 /// function generates a SampleEvent::PartialUpdate sample with the given partial update value.
855 /// The UpdateValue template parameter must match the UpdateValue type used to register the updater with
856 /// the Topic::setUpdater method.
857 /// A partial update resolves against the key's current value, so the key must have a current value when the
858 /// returned function is called: a full value was written for the key and the key was not since removed.
859 /// Calling the returned function for a key with no current value is an application error that throws
860 /// std::logic_error and publishes nothing.
861 /// A reader that uses a sample filter receives only the samples its filter matches: such a reader can lack
862 /// a current value for the key even though the writer has one, and it discards partial updates until it
863 /// receives a full value for the key. See Topic::setSampleFilter.
864 /// @param tag The partial update tag.
865 template<typename UpdateValue>
866 [[nodiscard]] std::function<void(const Key&, const UpdateValue&)> partialUpdate(const UpdateTag& tag);
867
868 /// Removes the data element. This generates a SampleEvent::Remove sample and retires the key: its current value
869 /// is released on the writer and on the readers that receive the sample, so a later partial update for the key
870 /// has no value to resolve against and is rejected until a new full value is written.
871 /// @param key The key
872 void remove(const Key& key) noexcept;
873
874 private:
875 const std::shared_ptr<DataStormI::KeyFactoryT<Key>> _keyFactory;
876 const std::shared_ptr<DataStormI::TagFactoryT<UpdateTag>> _tagFactory;
877 };
878
879 /// Creates a key writer for the given topic and key. This helper method deduces the topic Key, Value and
880 /// UpdateTag types from the topic argument.
881 /// @param topic The topic.
882 /// @param key The key.
883 /// @param name The optional writer name.
884 /// @param config The optional writer configuration.
885 template<typename K, typename V, typename UT>
887 const Topic<K, V, UT>& topic,
888 const typename Topic<K, V, UT>::KeyType& key,
889 std::string name = std::string(),
890 const WriterConfig& config = WriterConfig())
891 {
892 return SingleKeyWriter<K, V, UT>(topic, key, std::move(name), config);
893 }
894
895 /// Creates a multi-key writer for the given topic and keys. This helper method deduces the topic Key, Value
896 /// and UpdateTag types from the topic argument.
897 /// @param topic The topic.
898 /// @param keys The keys.
899 /// @param name The optional writer name.
900 /// @param config The optional writer configuration.
901 template<typename K, typename V, typename UT>
903 const Topic<K, V, UT>& topic,
904 const std::vector<typename Topic<K, V, UT>::KeyType>& keys,
905 std::string name = std::string(),
906 const WriterConfig& config = WriterConfig())
907 {
908 return MultiKeyWriter<K, V, UT>(topic, keys, std::move(name), config);
909 }
910
911 /// Creates an any-key writer for the given topic. This helper method deduces the topic Key, Value and
912 /// UpdateTag types from the topic argument.
913 /// @param topic The topic.
914 /// @param name The optional writer name.
915 /// @param config The optional writer configuration.
916 template<typename K, typename V, typename UT>
918 const Topic<K, V, UT>& topic,
919 std::string name = std::string(),
920 const WriterConfig& config = WriterConfig())
921 {
922 return MultiKeyWriter<K, V, UT>(topic, {}, std::move(name), config);
923 }
924
925 //
926 // Public template based API implementation
927 //
928
929 //
930 // Sample template implementation
931 //
932 template<typename Key, typename Value, typename UpdateTag>
934 {
935 return _impl->event;
936 }
937
938 template<typename Key, typename Value, typename UpdateTag>
939 const Key& Sample<Key, Value, UpdateTag>::getKey() const noexcept
940 {
941 return _impl->getKey();
942 }
943
944 template<typename Key, typename Value, typename UpdateTag>
945 const Value& Sample<Key, Value, UpdateTag>::getValue() const noexcept
946 {
947 return _impl->getValue();
948 }
949
950 template<typename Key, typename Value, typename UpdateTag>
952 {
953 return _impl->getTag();
954 }
955
956 template<typename Key, typename Value, typename UpdateTag>
957 std::chrono::time_point<std::chrono::system_clock> Sample<Key, Value, UpdateTag>::getTimeStamp() const noexcept
958 {
959 return _impl->timestamp;
960 }
961
962 template<typename Key, typename Value, typename UpdateTag>
963 const std::string& Sample<Key, Value, UpdateTag>::getOrigin() const noexcept
964 {
965 return _impl->origin;
966 }
967
968 template<typename Key, typename Value, typename UpdateTag>
969 const std::string& Sample<Key, Value, UpdateTag>::getSession() const noexcept
970 {
971 return _impl->session;
972 }
973
974 template<typename Key, typename Value, typename UpdateTag>
975 Sample<Key, Value, UpdateTag>::Sample(const std::shared_ptr<DataStormI::Sample>& impl) noexcept
976 : _impl(std::static_pointer_cast<DataStormI::SampleT<Key, Value, UpdateTag>>(impl))
977 {
978 }
979
980 //
981 // Reader template implementation
982 //
983 template<typename Key, typename Value, typename UpdateTag>
985 : _impl(std::move(reader._impl))
986 {
987 }
988
989 template<typename Key, typename Value, typename UpdateTag> Reader<Key, Value, UpdateTag>::~Reader()
990 {
991 if (_impl)
992 {
993 _impl->destroy();
994 }
995 }
996
997 template<typename Key, typename Value, typename UpdateTag>
999 {
1000 if (_impl)
1001 {
1002 _impl->destroy();
1003 }
1004 _impl = std::move(reader._impl);
1005 return *this;
1006 }
1007
1008 template<typename Key, typename Value, typename UpdateTag>
1010 {
1011 return _impl->hasWriters();
1012 }
1013
1014 template<typename Key, typename Value, typename UpdateTag>
1016 {
1017 _impl->waitForWriters(static_cast<int>(count));
1018 }
1019
1020 template<typename Key, typename Value, typename UpdateTag>
1022 {
1023 _impl->waitForWriters(-1);
1024 }
1025
1026 template<typename Key, typename Value, typename UpdateTag>
1028 {
1029 return _impl->getConnectedElements();
1030 }
1031
1032 template<typename Key, typename Value, typename UpdateTag>
1034 {
1035 std::vector<Key> keys;
1036 auto connectedKeys = _impl->getConnectedKeys();
1037 keys.reserve(connectedKeys.size());
1038 for (const auto& k : connectedKeys)
1039 {
1040 keys.push_back(std::static_pointer_cast<DataStormI::KeyT<Key>>(k)->get());
1041 }
1042 return keys;
1043 }
1044
1045 template<typename Key, typename Value, typename UpdateTag>
1046 std::vector<Sample<Key, Value, UpdateTag>> Reader<Key, Value, UpdateTag>::getAllUnread()
1047 {
1048 auto unread = _impl->getAllUnread();
1049 std::vector<Sample<Key, Value, UpdateTag>> samples;
1050 samples.reserve(unread.size());
1051 for (const auto& sample : unread)
1052 {
1053 samples.push_back(sample);
1054 }
1055 return samples;
1056 }
1057
1058 template<typename Key, typename Value, typename UpdateTag>
1060 {
1061 _impl->waitForUnread(count);
1062 }
1063
1064 template<typename Key, typename Value, typename UpdateTag>
1066 {
1067 return _impl->hasUnread();
1068 }
1069
1070 template<typename Key, typename Value, typename UpdateTag>
1075
1076 template<typename Key, typename Value, typename UpdateTag>
1078 std::function<void(std::vector<Key>)> init,
1079 std::function<void(CallbackReason, Key)> update) noexcept
1080 {
1081 _impl->onConnectedKeys(
1082 init ?
1083 [init = std::move(init)](const std::vector<std::shared_ptr<DataStormI::Key>>& connectedKeys)
1084 {
1085 std::vector<Key> keys;
1086 keys.reserve(connectedKeys.size());
1087 for(const auto& k : connectedKeys)
1088 {
1089 keys.push_back(std::static_pointer_cast<DataStormI::KeyT<Key>>(k)->get());
1090 }
1091 init(std::move(keys));
1092 } : std::function<void(std::vector<std::shared_ptr<DataStormI::Key>>)>{},
1093 update ?
1094 [update = std::move(update)](CallbackReason action, const std::shared_ptr<DataStormI::Key>& key)
1095 {
1096 update(action, std::static_pointer_cast<DataStormI::KeyT<Key>>(key)->get());
1097 } : std::function<void(CallbackReason, std::shared_ptr<DataStormI::Key>)>{});
1098 }
1099
1100 template<typename Key, typename Value, typename UpdateTag>
1102 std::function<void(std::vector<std::string>)> init,
1103 std::function<void(CallbackReason, std::string)> update) noexcept
1104 {
1105 _impl->onConnectedElements(std::move(init), std::move(update));
1106 }
1107
1108 template<typename Key, typename Value, typename UpdateTag>
1110 std::function<void(std::vector<Sample<Key, Value, UpdateTag>>)> init,
1111 std::function<void(Sample<Key, Value, UpdateTag>)> update) noexcept
1112 {
1113 auto communicator = _impl->getCommunicator();
1114 _impl->onSamples(
1115 init ?
1116 [communicator, init = std::move(init)](const std::vector<std::shared_ptr<DataStormI::Sample>>& samplesI)
1117 {
1118 std::vector<Sample<Key, Value, UpdateTag>> samples;
1119 samples.reserve(samplesI.size());
1120 for(const auto& s : samplesI)
1121 {
1122 samples.emplace_back(s);
1123 }
1124 init(std::move(samples));
1125 } : std::function<void(const std::vector<std::shared_ptr<DataStormI::Sample>>&)>(),
1126 update ?
1127 [communicator, update = std::move(update)](const std::shared_ptr<DataStormI::Sample>& sampleI)
1128 {
1129 update(sampleI);
1130 } : std::function<void(const std::shared_ptr<DataStormI::Sample>&)>{});
1131 }
1132
1133 template<typename Key, typename Value, typename UpdateTag>
1135 const Topic<Key, Value, UpdateTag>& topic,
1136 const Key& key,
1137 std::string name,
1138 const ReaderConfig& config)
1139 : Reader<Key, Value, UpdateTag>(
1140 topic.getReader()->create({topic._keyFactory->create(key)}, std::move(name), config))
1141 {
1142 }
1143
1144 template<typename Key, typename Value, typename UpdateTag>
1145 template<typename SampleFilterCriteria>
1147 const Topic<Key, Value, UpdateTag>& topic,
1148 const Key& key,
1149 const Filter<SampleFilterCriteria>& sampleFilter,
1150 std::string name,
1151 const ReaderConfig& config)
1152 : Reader<Key, Value, UpdateTag>(topic.getReader()->create(
1153 {topic._keyFactory->create(key)},
1154 std::move(name),
1155 config,
1156 sampleFilter.name,
1157 DataStormI::EncoderT<SampleFilterCriteria>::encode(topic.getCommunicator(), sampleFilter.criteria)))
1158 {
1159 }
1160
1161 template<typename Key, typename Value, typename UpdateTag>
1166
1167 template<typename Key, typename Value, typename UpdateTag>
1170 {
1172 return *this;
1173 }
1174
1175 template<typename Key, typename Value, typename UpdateTag>
1177 const Topic<Key, Value, UpdateTag>& topic,
1178 const std::vector<Key>& keys,
1179 std::string name,
1180 const ReaderConfig& config)
1181 : Reader<Key, Value, UpdateTag>(
1182 topic.getReader()->create(topic._keyFactory->create(keys), std::move(name), config))
1183 {
1184 }
1185
1186 template<typename Key, typename Value, typename UpdateTag>
1187 template<typename SampleFilterCriteria>
1189 const Topic<Key, Value, UpdateTag>& topic,
1190 const std::vector<Key>& keys,
1191 const Filter<SampleFilterCriteria>& sampleFilter,
1192 std::string name,
1193 const ReaderConfig& config)
1194 : Reader<Key, Value, UpdateTag>(topic.getReader()->create(
1195 topic._keyFactory->create(keys),
1196 std::move(name),
1197 config,
1198 sampleFilter.name,
1199 DataStormI::EncoderT<SampleFilterCriteria>::encode(topic.getCommunicator(), sampleFilter.criteria)))
1200 {
1201 }
1202
1203 template<typename Key, typename Value, typename UpdateTag>
1208
1209 template<typename Key, typename Value, typename UpdateTag>
1212 {
1214 return *this;
1215 }
1216
1217 template<typename Key, typename Value, typename UpdateTag>
1218 template<typename KeyFilterCriteria>
1220 const Topic<Key, Value, UpdateTag>& topic,
1221 const Filter<KeyFilterCriteria>& filter,
1222 std::string name,
1223 const ReaderConfig& config)
1224 : Reader<Key, Value, UpdateTag>(topic.getReader()->createFiltered(
1225 topic._keyFilterFactories->create(filter.name, filter.criteria),
1226 std::move(name),
1227 config))
1228 {
1229 }
1230
1231 template<typename Key, typename Value, typename UpdateTag>
1232 template<typename KeyFilterCriteria, typename SampleFilterCriteria>
1234 const Topic<Key, Value, UpdateTag>& topic,
1235 const Filter<KeyFilterCriteria>& keyFilter,
1236 const Filter<SampleFilterCriteria>& sampleFilter,
1237 std::string name,
1238 const ReaderConfig& config)
1239 : Reader<Key, Value, UpdateTag>(topic.getReader()->createFiltered(
1240 topic._keyFilterFactories->create(keyFilter.name, keyFilter.criteria),
1241 std::move(name),
1242 config,
1243 sampleFilter.name,
1244 DataStormI::EncoderT<SampleFilterCriteria>::encode(topic.getCommunicator(), sampleFilter.criteria)))
1245 {
1246 }
1247
1248 template<typename Key, typename Value, typename UpdateTag>
1254
1255 template<typename Key, typename Value, typename UpdateTag>
1258 {
1260 return *this;
1261 }
1262
1263 //
1264 // Writer template implementation
1265 //
1266 template<typename Key, typename Value, typename UpdateTag>
1267 Writer<Key, Value, UpdateTag>::Writer(Writer&& writer) noexcept : _impl(std::move(writer._impl))
1268 {
1269 }
1270
1271 template<typename Key, typename Value, typename UpdateTag> Writer<Key, Value, UpdateTag>::~Writer()
1272 {
1273 if (_impl)
1274 {
1275 _impl->destroy();
1276 }
1277 }
1278
1279 template<typename Key, typename Value, typename UpdateTag>
1281 {
1282 if (_impl)
1283 {
1284 _impl->destroy();
1285 }
1286 _impl = std::move(writer._impl);
1287 return *this;
1288 }
1289
1290 template<typename Key, typename Value, typename UpdateTag>
1292 {
1293 return _impl->hasReaders();
1294 }
1295
1296 template<typename Key, typename Value, typename UpdateTag>
1298 {
1299 return _impl->waitForReaders(static_cast<int>(count));
1300 }
1301
1302 template<typename Key, typename Value, typename UpdateTag>
1304 {
1305 return _impl->waitForReaders(-1);
1306 }
1307
1308 template<typename Key, typename Value, typename UpdateTag>
1310 {
1311 return _impl->getConnectedElements();
1312 }
1313
1314 template<typename Key, typename Value, typename UpdateTag>
1316 {
1317 std::vector<Key> keys;
1318 auto connectedKeys = _impl->getConnectedKeys();
1319 keys.reserve(connectedKeys.size());
1320 for (const auto& k : connectedKeys)
1321 {
1322 keys.push_back(std::static_pointer_cast<DataStormI::KeyT<Key>>(k)->get());
1323 }
1324 return keys;
1325 }
1326
1327 template<typename Key, typename Value, typename UpdateTag>
1329 {
1330 auto sample = _impl->getLast();
1331 if (!sample)
1332 {
1333 throw std::logic_error("no sample");
1334 }
1335 return Sample<Key, Value, UpdateTag>(sample);
1336 }
1337
1338 template<typename Key, typename Value, typename UpdateTag>
1339 std::vector<Sample<Key, Value, UpdateTag>> Writer<Key, Value, UpdateTag>::getAll()
1340 {
1341 auto all = _impl->getAll();
1342 std::vector<Sample<Key, Value, UpdateTag>> samples;
1343 samples.reserve(all.size());
1344 for (const auto& sample : all)
1345 {
1346 samples.push_back(sample);
1347 }
1348 return samples;
1349 }
1350
1351 template<typename Key, typename Value, typename UpdateTag>
1353 std::function<void(std::vector<Key>)> init,
1354 std::function<void(CallbackReason, Key)> update) noexcept
1355 {
1356 _impl->onConnectedKeys(
1357 init ?
1358 [init = std::move(init)](const std::vector<std::shared_ptr<DataStormI::Key>>& connectedKeys)
1359 {
1360 std::vector<Key> keys;
1361 keys.reserve(connectedKeys.size());
1362 for(const auto& k : connectedKeys)
1363 {
1364 keys.push_back(std::static_pointer_cast<DataStormI::KeyT<Key>>(k)->get());
1365 }
1366 init(std::move(keys));
1367 } : std::function<void(std::vector<std::shared_ptr<DataStormI::Key>>)>{},
1368 update ?
1369 [update = std::move(update)](CallbackReason action, const std::shared_ptr<DataStormI::Key>& key)
1370 {
1371 update(action, std::static_pointer_cast<DataStormI::KeyT<Key>>(key)->get());
1372 } : std::function<void(CallbackReason, std::shared_ptr<DataStormI::Key>)>{});
1373 }
1374
1375 template<typename Key, typename Value, typename UpdateTag>
1377 std::function<void(std::vector<std::string>)> init,
1378 std::function<void(CallbackReason, std::string)> update) noexcept
1379 {
1380 _impl->onConnectedElements(std::move(init), std::move(update));
1381 }
1382
1383 template<typename Key, typename Value, typename UpdateTag>
1385 const Topic<Key, Value, UpdateTag>& topic,
1386 const Key& key,
1387 std::string name,
1388 const WriterConfig& config)
1389 : Writer<Key, Value, UpdateTag>(
1390 topic.getWriter()->create({topic._keyFactory->create(key)}, std::move(name), config)),
1391 _tagFactory(topic._tagFactory)
1392 {
1393 }
1394
1395 template<typename Key, typename Value, typename UpdateTag>
1397 : Writer<Key, Value, UpdateTag>(std::move(writer)),
1398 _tagFactory(std::move(writer._tagFactory))
1399 {
1400 }
1401
1402 template<typename Key, typename Value, typename UpdateTag>
1405 {
1407 return *this;
1408 }
1409
1410 template<typename Key, typename Value, typename UpdateTag>
1412 {
1413 Writer<Key, Value, UpdateTag>::_impl->publish(
1414 nullptr,
1415 std::make_shared<DataStormI::SampleT<Key, Value, UpdateTag>>(SampleEvent::Add, value));
1416 }
1417
1418 template<typename Key, typename Value, typename UpdateTag>
1420 {
1421 Writer<Key, Value, UpdateTag>::_impl->publish(
1422 nullptr,
1423 std::make_shared<DataStormI::SampleT<Key, Value, UpdateTag>>(SampleEvent::Update, value));
1424 }
1425
1426 template<typename Key, typename Value, typename UpdateTag>
1427 template<typename UpdateValue>
1428 std::function<void(const UpdateValue&)> SingleKeyWriter<Key, Value, UpdateTag>::partialUpdate(const UpdateTag& tag)
1429 {
1430 auto impl = Writer<Key, Value, UpdateTag>::_impl;
1431 auto updateTag = _tagFactory->create(tag);
1432 return [impl, updateTag](const UpdateValue& value)
1433 {
1434 auto encoded = DataStormI::EncoderT<UpdateValue>::encode(impl->getCommunicator(), value);
1435 impl->publish(nullptr, std::make_shared<DataStormI::SampleT<Key, Value, UpdateTag>>(encoded, updateTag));
1436 };
1437 }
1438
1439 template<typename Key, typename Value, typename UpdateTag>
1441 {
1442 Writer<Key, Value, UpdateTag>::_impl->publish(
1443 nullptr,
1444 std::make_shared<DataStormI::SampleT<Key, Value, UpdateTag>>(SampleEvent::Remove));
1445 }
1446
1447 template<typename Key, typename Value, typename UpdateTag>
1449 const Topic<Key, Value, UpdateTag>& topic,
1450 const std::vector<Key>& keys,
1451 std::string name,
1452 const WriterConfig& config)
1453 : Writer<Key, Value, UpdateTag>(
1454 topic.getWriter()->create(topic._keyFactory->create(keys), std::move(name), config)),
1455 _keyFactory(topic._keyFactory),
1456 _tagFactory(topic._tagFactory)
1457 {
1458 }
1459
1460 template<typename Key, typename Value, typename UpdateTag>
1462 : Writer<Key, Value, UpdateTag>(std::move(writer)),
1463 _keyFactory(std::move(writer._keyFactory)),
1464 _tagFactory(std::move(writer._tagFactory))
1465 {
1466 }
1467
1468 template<typename Key, typename Value, typename UpdateTag>
1471 {
1473 return *this;
1474 }
1475
1476 template<typename Key, typename Value, typename UpdateTag>
1477 void MultiKeyWriter<Key, Value, UpdateTag>::add(const Key& key, const Value& value)
1478 {
1479 Writer<Key, Value, UpdateTag>::_impl->publish(
1480 _keyFactory->create(key),
1481 std::make_shared<DataStormI::SampleT<Key, Value, UpdateTag>>(SampleEvent::Add, value));
1482 }
1483
1484 template<typename Key, typename Value, typename UpdateTag>
1485 void MultiKeyWriter<Key, Value, UpdateTag>::update(const Key& key, const Value& value)
1486 {
1487 Writer<Key, Value, UpdateTag>::_impl->publish(
1488 _keyFactory->create(key),
1489 std::make_shared<DataStormI::SampleT<Key, Value, UpdateTag>>(SampleEvent::Update, value));
1490 }
1491
1492 template<typename Key, typename Value, typename UpdateTag>
1493 template<typename UpdateValue>
1494 std::function<void(const Key&, const UpdateValue&)>
1496 {
1497 auto impl = Writer<Key, Value, UpdateTag>::_impl;
1498 auto updateTag = _tagFactory->create(tag);
1499 auto keyFactory = _keyFactory;
1500 return [impl, updateTag, keyFactory](const Key& key, const UpdateValue& value)
1501 {
1502 auto encoded = DataStormI::EncoderT<UpdateValue>::encode(impl->getCommunicator(), value);
1503 impl->publish(
1504 keyFactory->create(key),
1505 std::make_shared<DataStormI::SampleT<Key, Value, UpdateTag>>(encoded, updateTag));
1506 };
1507 }
1508
1509 template<typename Key, typename Value, typename UpdateTag>
1511 {
1512 Writer<Key, Value, UpdateTag>::_impl->publish(
1513 _keyFactory->create(key),
1514 std::make_shared<DataStormI::SampleT<Key, Value, UpdateTag>>(SampleEvent::Remove));
1515 }
1516
1517 /// @private
1518 template<typename Value> std::function<std::function<bool(const Value&)>(const std::string&)> makeRegexFilter()
1519 {
1520 // std::regex's constructor accepts a const string&; it does not accept a string_view.
1521 return [](const std::string& criteria)
1522 {
1523 std::regex expr(criteria);
1524 return [expr = std::move(expr)](const Value& value)
1525 {
1526 std::ostringstream os;
1527 os << value;
1528 return std::regex_match(os.str(), expr);
1529 };
1530 };
1531 }
1532
1533 /// @private
1534 template<typename Key, typename Value, typename UpdateTag>
1535 std::function<std::function<bool(const Sample<Key, Value, UpdateTag>&)>(const SampleEventSeq&)>
1536 makeSampleEventFilter(const Topic<Key, Value, UpdateTag>&)
1537 {
1538 return [](const SampleEventSeq& criteria)
1539 {
1540 return [criteria](const Sample<Key, Value, UpdateTag>& sample)
1541 { return std::find(criteria.begin(), criteria.end(), sample.getEvent()) != criteria.end(); };
1542 };
1543 }
1544
1545 /// @private
1546 template<typename T, typename V, typename Enabler = void> struct RegexFilter
1547 {
1548 template<typename F> static void add(const F&) {}
1549 };
1550
1551 /// @private
1552 template<typename T, typename V> struct RegexFilter<T, V, std::enable_if_t<DataStormI::is_streamable<V>::value>>
1553 {
1554 template<typename F> static void add(const F& factory)
1555 {
1556 factory->set("_regex", makeRegexFilter<T>()); // Only set the _regex filter if the value is streamable
1557 }
1558 };
1559
1560 //
1561 // Topic template implementation
1562 //
1563 template<typename Key, typename Value, typename UpdateTag>
1564 Topic<Key, Value, UpdateTag>::Topic(const Node& node, std::string name) noexcept
1565 : _name(std::move(name)),
1566 _topicFactory(node._factory),
1567 _keyFactory(DataStormI::KeyFactoryT<Key>::createFactory()),
1568 _tagFactory(DataStormI::TagFactoryT<UpdateTag>::createFactory()),
1569 _keyFilterFactories(std::make_shared<DataStormI::FilterManagerT<DataStormI::KeyT<Key>>>()),
1570 _sampleFilterFactories(
1571 std::make_shared<DataStormI::FilterManagerT<DataStormI::SampleT<Key, Value, UpdateTag>>>())
1572 {
1573 RegexFilter<Key, Key>::add(_keyFilterFactories);
1574 RegexFilter<Sample<Key, Value, UpdateTag>, Value>::add(_sampleFilterFactories);
1575 _sampleFilterFactories->set("_event", makeSampleEventFilter(*this));
1576 }
1577
1578 template<typename Key, typename Value, typename UpdateTag> Topic<Key, Value, UpdateTag>::~Topic()
1579 {
1580 std::lock_guard<std::mutex> lock(_mutex);
1581 if (_reader)
1582 {
1583 _reader->destroy();
1584 }
1585 if (_writer)
1586 {
1587 _writer->destroy();
1588 }
1589 }
1590
1591 template<typename Key, typename Value, typename UpdateTag>
1593 {
1594 std::lock_guard<std::mutex> lock(_mutex);
1595 if (_reader)
1596 {
1597 _reader->destroy();
1598 }
1599 if (_writer)
1600 {
1601 _writer->destroy();
1602 }
1603 _name = std::move(topic._name);
1604 _topicFactory = std::move(topic._topicFactory);
1605 _keyFactory = std::move(topic._keyFactory);
1606 _tagFactory = std::move(topic._tagFactory);
1607 _keyFilterFactories = std::move(topic._keyFilterFactories);
1608 _sampleFilterFactories = std::move(topic._sampleFilterFactories);
1609 _reader = std::move(topic._reader);
1610 _writer = std::move(topic._writer);
1611 _updaters = std::move(topic._updaters);
1612 return *this;
1613 }
1614
1615 template<typename Key, typename Value, typename UpdateTag>
1617 {
1618 return getReader()->hasWriters();
1619 }
1620
1621 template<typename Key, typename Value, typename UpdateTag>
1623 {
1624 getReader()->waitForWriters(static_cast<int>(count));
1625 }
1626
1627 template<typename Key, typename Value, typename UpdateTag>
1629 {
1630 getReader()->waitForWriters(-1);
1631 }
1632
1633 template<typename Key, typename Value, typename UpdateTag>
1635 {
1636 getReader()->setDefaultConfig(config);
1637 }
1638
1639 template<typename Key, typename Value, typename UpdateTag>
1641 {
1642 return getWriter()->hasReaders();
1643 }
1644
1645 template<typename Key, typename Value, typename UpdateTag>
1647 {
1648 getWriter()->waitForReaders(static_cast<int>(count));
1649 }
1650
1651 template<typename Key, typename Value, typename UpdateTag>
1653 {
1654 getWriter()->waitForReaders(-1);
1655 }
1656
1657 template<typename Key, typename Value, typename UpdateTag>
1659 {
1660 getWriter()->setDefaultConfig(config);
1661 }
1662
1663 template<typename Key, typename Value, typename UpdateTag>
1664 template<typename UpdateValue>
1666 const UpdateTag& tag,
1667 std::function<void(Value&, UpdateValue)> updater) noexcept
1668 {
1669 std::lock_guard<std::mutex> lock(_mutex);
1670 auto tagI = _tagFactory->create(std::move(tag));
1671 auto updaterImpl =
1672 updater ?
1673 [updater = std::move(updater)](const std::shared_ptr<DataStormI::Sample>& previous,
1674 const std::shared_ptr<DataStormI::Sample>& next,
1675 const Ice::CommunicatorPtr& communicator)
1676 {
1677 // Every updater call site ensures the previous sample exists and has a value before invoking the
1678 // updater (the writer throws otherwise, the reader drops the sample), so this assert holds and the
1679 // clone below always runs. The guarded branch is not a safe release-build fallback for a broken
1680 // invariant: a default-constructed base is null for class-typed values, which the user's updater
1681 // would dereference just as if the guard were absent.
1682 assert(previous && previous->hasValue());
1683 Value value{};
1684 if (previous && previous->hasValue())
1685 {
1686 value = Cloner<Value>::clone(
1687 std::static_pointer_cast<DataStormI::SampleT<Key, Value, UpdateTag>>(previous)->getValue());
1688 }
1689 updater(value, DataStormI::DecoderT<UpdateValue>::decode(communicator, next->getEncodedValue()));
1690 std::static_pointer_cast<DataStormI::SampleT<Key, Value, UpdateTag>>(next)->setValue(std::move(value));
1691 } : std::function<void(const std::shared_ptr<DataStormI::Sample>&,
1692 const std::shared_ptr<DataStormI::Sample>&,
1693 const Ice::CommunicatorPtr&)>{};
1694
1695 if (_reader && !_writer)
1696 {
1697 _reader->setUpdater(tagI, updaterImpl);
1698 }
1699 else if (_writer && !_reader)
1700 {
1701 _writer->setUpdater(tagI, updaterImpl);
1702 }
1703 else if (_reader && _writer)
1704 {
1705 _reader->setUpdater(tagI, updaterImpl);
1706 _writer->setUpdater(tagI, updaterImpl);
1707 }
1708 else
1709 {
1710 _updaters[tagI] = updaterImpl;
1711 }
1712 }
1713
1714 template<typename Key, typename Value, typename UpdateTag>
1715 template<typename Criteria>
1717 std::string name,
1718 std::function<std::function<bool(const Key&)>(const Criteria&)> factory) noexcept
1719 {
1720 std::lock_guard<std::mutex> lock(_mutex);
1721 _keyFilterFactories->set(std::move(name), std::move(factory));
1722 }
1723
1724 template<typename Key, typename Value, typename UpdateTag>
1725 template<typename Criteria>
1727 std::string name,
1728 std::function<std::function<bool(const SampleType&)>(const Criteria&)> factory) noexcept
1729 {
1730 std::lock_guard<std::mutex> lock(_mutex);
1731 _sampleFilterFactories->set(std::move(name), std::move(factory));
1732 }
1733
1734 template<typename Key, typename Value, typename UpdateTag>
1735 std::shared_ptr<DataStormI::TopicReader> Topic<Key, Value, UpdateTag>::getReader() const
1736 {
1737 std::lock_guard<std::mutex> lock(_mutex);
1738 if (!_reader)
1739 {
1740 auto sampleFactory = std::make_shared<DataStormI::SampleFactoryT<Key, Value, UpdateTag>>();
1741 _reader = _topicFactory->createTopicReader(
1742 _name,
1743 _keyFactory,
1744 _tagFactory,
1745 std::move(sampleFactory),
1746 _keyFilterFactories,
1747 _sampleFilterFactories);
1748 _reader->setUpdaters(_writer ? _writer->getUpdaters() : _updaters);
1749 _updaters.clear();
1750 }
1751 return _reader;
1752 }
1753
1754 template<typename Key, typename Value, typename UpdateTag>
1755 std::shared_ptr<DataStormI::TopicWriter> Topic<Key, Value, UpdateTag>::getWriter() const
1756 {
1757 std::lock_guard<std::mutex> lock(_mutex);
1758 if (!_writer)
1759 {
1760 _writer = _topicFactory->createTopicWriter(
1761 _name,
1762 _keyFactory,
1763 _tagFactory,
1764 nullptr,
1765 _keyFilterFactories,
1766 _sampleFilterFactories);
1767 _writer->setUpdaters(_reader ? _reader->getUpdaters() : _updaters);
1768 _updaters.clear();
1769 }
1770 return _writer;
1771 }
1772
1773 template<typename Key, typename Value, typename UpdateTag>
1774 Ice::CommunicatorPtr Topic<Key, Value, UpdateTag>::getCommunicator() const noexcept
1775 {
1776 return _topicFactory->getCommunicator();
1777 }
1778}
1779
1780#if defined(__clang__)
1781# pragma clang diagnostic pop
1782#elif defined(__GNUC__)
1783# pragma GCC diagnostic pop
1784#endif
1785
1786#endif
FilteredKeyReader & operator=(FilteredKeyReader &&reader) noexcept
Move assignment operator.
Definition DataStorm.h:1257
FilteredKeyReader(const Topic< Key, Value, UpdateTag > &topic, const Filter< KeyFilterCriteria > &keyFilter, std::string name=std::string(), const ReaderConfig &config=ReaderConfig())
Constructs a new reader for the given key filter.
Definition DataStorm.h:1219
The filtered reader to read data elements whose key match a given filter.
Definition DataStorm.h:671
MultiKeyReader(const Topic< Key, Value, UpdateTag > &topic, const std::vector< Key > &keys, std::string name=std::string(), const ReaderConfig &config=ReaderConfig())
Constructs a new reader for the given keys.
Definition DataStorm.h:1176
MultiKeyReader & operator=(MultiKeyReader &&reader) noexcept
Move assignment operator.
Definition DataStorm.h:1211
The key reader to read the data element associated with a given set of keys.
Definition DataStorm.h:518
std::function< void(const Key &, const UpdateValue &)> partialUpdate(const UpdateTag &tag)
Gets a partial update generator function for the given partial update tag.
Definition DataStorm.h:1495
void add(const Key &key, const Value &value)
Adds the data element.
Definition DataStorm.h:1477
MultiKeyWriter(const Topic< Key, Value, UpdateTag > &topic, const std::vector< Key > &keys, std::string name=std::string(), const WriterConfig &config=WriterConfig())
Constructs a new writer for the given keys.
Definition DataStorm.h:1448
void remove(const Key &key) noexcept
Removes the data element.
Definition DataStorm.h:1510
void update(const Key &key, const Value &value)
Updates the data element.
Definition DataStorm.h:1485
MultiKeyWriter & operator=(MultiKeyWriter &&writer) noexcept
Move assignment operator.
Definition DataStorm.h:1470
The key writer to write data elements associated with a given set of keys.
Definition DataStorm.h:819
The Node class allows creating topic readers and writers.
Definition Node.h:56
The ReaderConfig class specifies configuration options specific to readers.
Definition Types.h:111
std::vector< Key > getConnectedKeys() const
Gets the keys for which writers are connected to this reader.
Definition DataStorm.h:1033
void onConnectedWriters(std::function< void(std::vector< std::string >)> init, std::function< void(CallbackReason, std::string)> update) noexcept
Calls the given functions to provide the initial set of connected writers and when a new writer conne...
Definition DataStorm.h:1101
std::vector< std::string > getConnectedWriters() const
Gets the connected writers.
Definition DataStorm.h:1027
Reader & operator=(Reader &&reader) noexcept
Move assignment operator.
Definition DataStorm.h:998
void waitForNoWriters() const
Waits for writers to be offline.
Definition DataStorm.h:1021
Value ValueType
The value type.
Definition DataStorm.h:117
Reader(Reader &&reader) noexcept
Move constructor.
Definition DataStorm.h:984
void waitForWriters(unsigned int count=1) const
Waits for the given number of writers to be online.
Definition DataStorm.h:1015
bool hasUnread() const noexcept
Returns whether or not unread samples are available.
Definition DataStorm.h:1065
void onConnectedKeys(std::function< void(std::vector< Key >)> init, std::function< void(CallbackReason, Key)> update) noexcept
Calls the given functions to provide the initial set of connected keys and when a key is added or rem...
Definition DataStorm.h:1077
std::vector< Sample< Key, Value, UpdateTag > > getAllUnread()
Returns all the unread samples.
Definition DataStorm.h:1046
Sample< Key, Value, UpdateTag > getNextUnread()
Returns the next unread sample.
Definition DataStorm.h:1071
Key KeyType
The key type.
Definition DataStorm.h:114
bool hasWriters() const noexcept
Indicates whether or not writers are online.
Definition DataStorm.h:1009
void waitForUnread(unsigned int count=1) const
Waits for the given number of unread samples to be available.
Definition DataStorm.h:1059
void onSamples(std::function< void(std::vector< Sample< Key, Value, UpdateTag > >)> init, std::function< void(Sample< Key, Value, UpdateTag >)> queue) noexcept
Calls the given function to provide the initial set of unread samples and when new samples are queued...
Definition DataStorm.h:1109
~Reader()
Destructor.
Definition DataStorm.h:989
The Reader class is used to retrieve samples for a data element.
Definition DataStorm.h:111
const Value & getValue() const noexcept
Value ValueType
The type of the sample value.
Definition DataStorm.h:37
const std::string & getOrigin() const noexcept
UpdateTag UpdateTagType
The type of the update tag.
Definition DataStorm.h:41
Key KeyType
The type of the sample key.
Definition DataStorm.h:34
SampleEvent getEvent() const noexcept
Gets the event associated with the sample.
Definition DataStorm.h:933
std::chrono::time_point< std::chrono::system_clock > getTimeStamp() const noexcept
const Key & getKey() const noexcept
A sample provides information about a data element update.
Definition DataStorm.h:31
SingleKeyReader & operator=(SingleKeyReader &&reader) noexcept
Move assignment operator.
Definition DataStorm.h:1169
SingleKeyReader(const Topic< Key, Value, UpdateTag > &topic, const Key &key, std::string name=std::string(), const ReaderConfig &config=ReaderConfig())
Constructs a new reader for the given key.
Definition DataStorm.h:1134
The key reader to read the data element associated with a given key.
Definition DataStorm.h:468
std::function< void(const UpdateValue &)> partialUpdate(const UpdateTag &tag)
Gets a partial update generator function for the given partial update tag.
Definition DataStorm.h:1428
void add(const Value &value)
Adds the data element.
Definition DataStorm.h:1411
void update(const Value &value)
Updates the data element.
Definition DataStorm.h:1419
void remove() noexcept
Removes the data element.
Definition DataStorm.h:1440
SingleKeyWriter & operator=(SingleKeyWriter &&writer) noexcept
Move assignment operator.
Definition DataStorm.h:1404
SingleKeyWriter(const Topic< Key, Value, UpdateTag > &topic, const Key &key, std::string name=std::string(), const WriterConfig &config=WriterConfig())
Constructs a new writer for the given key.
Definition DataStorm.h:1384
The key writer to write the data element associated with a given key.
Definition DataStorm.h:753
void setUpdater(const UpdateTag &tag, std::function< void(Value &, UpdateValue)> updater) noexcept
Sets an updater function for the given update tag.
Definition DataStorm.h:1665
Topic(const Node &node, std::string name) noexcept
Constructs a new Topic for the topic with the given name.
Definition DataStorm.h:1564
void setKeyFilter(std::string name, std::function< std::function< bool(const Key &)>(const Criteria &)> factory) noexcept
Sets a key filter factory.
Definition DataStorm.h:1716
UpdateTag UpdateTagType
The topic's update tag type (defaults to std::string if not specified).
Definition DataStorm.h:307
Key KeyType
The topic's key type.
Definition DataStorm.h:301
void waitForReaders(unsigned int count=1) const
Waits for the given number of data readers to be online.
Definition DataStorm.h:1646
void waitForNoWriters() const
Waits for data writers to be offline.
Definition DataStorm.h:1628
Value ValueType
The topic's value type.
Definition DataStorm.h:304
bool hasReaders() const noexcept
Indicates whether or not data readers are online.
Definition DataStorm.h:1640
Sample< Key, Value, UpdateTag > SampleType
The topic's sample type.
Definition DataStorm.h:316
void setSampleFilter(std::string name, std::function< std::function< bool(const SampleType &)>(const Criteria &)> factory) noexcept
Sets a sample filter factory.
Definition DataStorm.h:1726
Reader< Key, Value, UpdateTag > ReaderType
The topic's reader type.
Definition DataStorm.h:313
bool hasWriters() const noexcept
Indicates whether or not data writers are online.
Definition DataStorm.h:1616
void setWriterDefaultConfig(const WriterConfig &config) noexcept
Sets the default configuration used to construct writers.
Definition DataStorm.h:1658
Topic & operator=(Topic &&topic) noexcept
Move assignment operator.
Definition DataStorm.h:1592
Writer< Key, Value, UpdateTag > WriterType
The topic's writer type.
Definition DataStorm.h:310
void setReaderDefaultConfig(const ReaderConfig &config) noexcept
Sets the default configuration used to construct readers.
Definition DataStorm.h:1634
Topic(Topic &&topic) noexcept
Move constructor.
Definition DataStorm.h:325
void waitForWriters(unsigned int count=1) const
Waits for the given number of data writers to be online.
Definition DataStorm.h:1622
void waitForNoReaders() const
Waits for data readers to be offline.
Definition DataStorm.h:1652
~Topic()
Destructor.
Definition DataStorm.h:1578
The Topic class.
Definition DataStorm.h:298
The WriterConfig class specifies configuration options specific to writers.
Definition Types.h:139
Sample< Key, Value, UpdateTag > getLast()
Gets the last written sample.
Definition DataStorm.h:1328
Writer & operator=(Writer &&writer) noexcept
Move assignment operator.
Definition DataStorm.h:1280
std::vector< Sample< Key, Value, UpdateTag > > getAll()
Gets all the written sample kept in the writer history.
Definition DataStorm.h:1339
std::vector< std::string > getConnectedReaders() const
Gets the connected readers.
Definition DataStorm.h:1309
void onConnectedReaders(std::function< void(std::vector< std::string >)> init, std::function< void(CallbackReason, std::string)> update) noexcept
Calls the given functions to provide the initial set of connected readers and when a new reader conne...
Definition DataStorm.h:1376
void waitForReaders(unsigned int count=1) const
Waits for the given number of readers to be online.
Definition DataStorm.h:1297
~Writer()
Destructor.
Definition DataStorm.h:1271
void onConnectedKeys(std::function< void(std::vector< Key >)> init, std::function< void(CallbackReason, Key)> update) noexcept
Calls the given functions to provide the initial set of connected keys and when a key is added or rem...
Definition DataStorm.h:1352
bool hasReaders() const noexcept
Indicates whether or not readers are online.
Definition DataStorm.h:1291
std::vector< Key > getConnectedKeys() const
Gets the keys for which readers are connected to this writer.
Definition DataStorm.h:1315
Key KeyType
The key type.
Definition DataStorm.h:216
Value ValueType
The value type.
Definition DataStorm.h:219
Writer(Writer &&writer) noexcept
Move constructor.
Definition DataStorm.h:1267
void waitForNoReaders() const
Waits for readers to be offline.
Definition DataStorm.h:1303
The Writer class is used to write samples for a data element.
Definition DataStorm.h:213
SampleEvent
Describes the operation used by a data writer to update a data element.
Definition SampleEvent.h:35
@ Update
The data writer updated the element.
Definition SampleEvent.h:40
@ Remove
The data writer removed the element.
Definition SampleEvent.h:46
@ Add
The data writer added the element.
Definition SampleEvent.h:37
SingleKeyReader< K, V, UT > makeSingleKeyReader(const Topic< K, V, UT > &topic, const typename Topic< K, V, UT >::KeyType &key, std::string name=std::string(), const ReaderConfig &config=ReaderConfig())
Creates a key reader for the given topic and key.
Definition DataStorm.h:567
FilteredKeyReader< K, V, UT > makeFilteredKeyReader(const Topic< K, V, UT > &topic, const Filter< KFC > &filter, std::string name=std::string(), const ReaderConfig &config=ReaderConfig())
Creates a new filtered reader for the given topic and key filter.
Definition DataStorm.h:722
MultiKeyReader< K, V, UT > makeAnyKeyReader(const Topic< K, V, UT > &topic, std::string name=std::string(), const ReaderConfig &config=ReaderConfig())
Creates an any-key reader for the given topic.
Definition DataStorm.h:637
std::vector< SampleEvent > SampleEventSeq
A sequence of sample events.
Definition SampleEvent.h:56
MultiKeyWriter< K, V, UT > makeMultiKeyWriter(const Topic< K, V, UT > &topic, const std::vector< typename Topic< K, V, UT >::KeyType > &keys, std::string name=std::string(), const WriterConfig &config=WriterConfig())
Creates a multi-key writer for the given topic and keys.
Definition DataStorm.h:902
SingleKeyWriter< K, V, UT > makeSingleKeyWriter(const Topic< K, V, UT > &topic, const typename Topic< K, V, UT >::KeyType &key, std::string name=std::string(), const WriterConfig &config=WriterConfig())
Creates a key writer for the given topic and key.
Definition DataStorm.h:886
MultiKeyReader< K, V, UT > makeMultiKeyReader(const Topic< K, V, UT > &topic, const std::vector< typename Topic< K, V, UT >::KeyType > &keys, std::string name=std::string(), const ReaderConfig &config=ReaderConfig())
Creates a multi-key reader for the given topic.
Definition DataStorm.h:602
std::ostream & operator<<(std::ostream &os, const SampleEventSeq &types)
Converts the given sample type vector to a string and add it to the stream.
Definition DataStorm.h:91
MultiKeyWriter< K, V, UT > makeAnyKeyWriter(const Topic< K, V, UT > &topic, std::string name=std::string(), const WriterConfig &config=WriterConfig())
Creates an any-key writer for the given topic.
Definition DataStorm.h:917
CallbackReason
The callback action enumerator specifies the reason why a callback is called.
Definition Types.h:164
Data-centric, broker-less publish/subscribe framework. C++ only.
Definition DataStorm.h:25
std::shared_ptr< Communicator > CommunicatorPtr
A shared pointer to a Communicator.
void print(std::ostream &stream, T v)
Prints a value to a stream.
The Ice RPC framework.
Definition SampleEvent.h:60
static T clone(const T &value) noexcept
Clones the given value.
Definition Types.h:209
Filter(std::string name, TT &&criteria) noexcept
Constructs a filter structure with the given name and criteria.
Definition DataStorm.h:452
std::string name
The filter name.
Definition DataStorm.h:458
T criteria
The filter criteria value.
Definition DataStorm.h:461
Filter structure to specify the filter name and criteria value.
Definition DataStorm.h:447