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