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 /// 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 filters before creating any reader or writer for this topic: the set of filters is not
393 /// synchronized, so modifying it once the topic is in use races with the Ice threads that 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 filters before creating any reader or writer for this topic: the set of filters is not
404 /// synchronized, so modifying it once the topic is in use races with the Ice threads that use the topic.
405 /// @param name The name of the sample filter.
406 /// @param factory The filter factory function.
407 template<typename Criteria>
408 void setSampleFilter(
409 std::string name,
410 std::function<std::function<bool(const SampleType&)>(const Criteria&)> factory) noexcept;
411
412 private:
413 [[nodiscard]] std::shared_ptr<DataStormI::TopicReader> getReader() const;
414 [[nodiscard]] std::shared_ptr<DataStormI::TopicWriter> getWriter() const;
415 [[nodiscard]] Ice::CommunicatorPtr getCommunicator() const noexcept;
416
417 template<typename, typename, typename> friend class SingleKeyWriter;
418 template<typename, typename, typename> friend class MultiKeyWriter;
419 template<typename, typename, typename> friend class SingleKeyReader;
420 template<typename, typename, typename> friend class MultiKeyReader;
421 template<typename, typename, typename> friend class FilteredKeyReader;
422
423 // These fields are non-const because we move them in the move-assignment operator.
424 std::string _name;
425 std::shared_ptr<DataStormI::TopicFactory> _topicFactory;
426 std::shared_ptr<DataStormI::KeyFactoryT<Key>> _keyFactory;
427 std::shared_ptr<DataStormI::TagFactoryT<UpdateTag>> _tagFactory;
428 std::shared_ptr<DataStormI::FilterManagerT<DataStormI::KeyT<Key>>> _keyFilterFactories;
429 std::shared_ptr<DataStormI::FilterManagerT<DataStormI::SampleT<Key, Value, UpdateTag>>> _sampleFilterFactories;
430
431 mutable std::mutex _mutex;
432 mutable std::shared_ptr<DataStormI::TopicReader> _reader;
433 mutable std::shared_ptr<DataStormI::TopicWriter> _writer;
434 mutable std::map<std::shared_ptr<DataStormI::Tag>, DataStormI::Topic::Updater> _updaters;
435 };
436
437 /// Filter structure to specify the filter name and criteria value.
438 /// @headerfile DataStorm/DataStorm.h
439 template<typename T> struct Filter
440 {
441 /// Constructs a filter structure with the given name and criteria.
442 /// @param name The filter name
443 /// @param criteria The criteria
444 template<typename TT>
445 Filter(std::string name, TT&& criteria) noexcept : name(std::move(name)),
446 criteria(std::forward<TT>(criteria))
447 {
448 }
449
450 /// The filter name.
451 std::string name;
452
453 /// The filter criteria value.
455 };
456
457 /// The key reader to read the data element associated with a given key.
458 /// @headerfile DataStorm/DataStorm.h
459 template<typename Key, typename Value, typename UpdateTag = std::string>
460 class SingleKeyReader : public Reader<Key, Value, UpdateTag>
461 {
462 public:
463 /// Constructs a new reader for the given key. The construction of the reader connects the reader to writers
464 /// with a matching key.
465 /// @param topic The topic.
466 /// @param key The key of the data element to read.
467 /// @param name The optional reader name.
468 /// @param config The reader configuration.
470 const Topic<Key, Value, UpdateTag>& topic,
471 const Key& key,
472 std::string name = std::string(),
473 const ReaderConfig& config = ReaderConfig());
474
475 /// Constructs a new reader for the given key and sample filter criteria. The construction of the reader
476 /// connects the reader to writers with a matching key. The writer will only send samples matching the
477 /// given sample filter criteria to the reader.
478 /// @param topic The topic.
479 /// @param key The key of the data element to read.
480 /// @param sampleFilter The sample filter.
481 /// @param name The optional reader name.
482 /// @param config The reader configuration.
483 template<typename SampleFilterCriteria>
485 const Topic<Key, Value, UpdateTag>& topic,
486 const Key& key,
487 const Filter<SampleFilterCriteria>& sampleFilter,
488 std::string name = std::string(),
489 const ReaderConfig& config = ReaderConfig());
490
491 /// Move constructor.
492 /// @param reader The reader to move from.
493 SingleKeyReader(SingleKeyReader&& reader) noexcept;
494
495 /// Move assignment operator.
496 /// @param reader The reader to move from.
497 /// @return A reference to this reader.
498 SingleKeyReader& operator=(SingleKeyReader&& reader) noexcept;
499 };
500
501 /// The key reader to read the data element associated with a given set of keys.
502 ///
503 /// A multi-key reader retains the current value of every key it has received and not since seen removed, so that
504 /// it can resolve later partial updates against it. This per-key state is independent of the reader's
505 /// `sampleCount` and `sampleLifetime` history settings, and is released when the reader receives the key's remove
506 /// sample. A reader connected to writers over an unbounded set of keys therefore accumulates one current value per
507 /// key.
508 /// @headerfile DataStorm/DataStorm.h
509 template<typename Key, typename Value, typename UpdateTag = std::string>
510 class MultiKeyReader : public Reader<Key, Value, UpdateTag>
511 {
512 public:
513 /// Constructs a new reader for the given keys. The construction of the reader connects the reader to
514 /// writers with matching keys. If an empty vector of keys is provided, the reader will connect to all the
515 /// available writers.
516 /// @param topic The topic.
517 /// @param keys The keys of the data elements to read.
518 /// @param name The optional reader name.
519 /// @param config The reader configuration.
521 const Topic<Key, Value, UpdateTag>& topic,
522 const std::vector<Key>& keys,
523 std::string name = std::string(),
524 const ReaderConfig& config = ReaderConfig());
525
526 /// Constructs a new reader for the given keys and sample filter criteria. The construction of the reader
527 /// connects the reader to writers with matching keys. If an empty vector of keys is provided, the reader
528 /// will connect to all the available writers. The writer will only send samples matching the given sample
529 /// filter criteria to the reader.
530 /// @param topic The topic.
531 /// @param keys The keys of the data elements to read.
532 /// @param sampleFilter The sample filter.
533 /// @param name The optional reader name.
534 /// @param config The reader configuration.
535 template<typename SampleFilterCriteria>
537 const Topic<Key, Value, UpdateTag>& topic,
538 const std::vector<Key>& keys,
539 const Filter<SampleFilterCriteria>& sampleFilter,
540 std::string name = std::string(),
541 const ReaderConfig& config = ReaderConfig());
542
543 /// Move constructor.
544 /// @param reader The reader to move from.
545 MultiKeyReader(MultiKeyReader&& reader) noexcept;
546
547 /// Move assignment operator.
548 /// @param reader The reader to move from.
549 /// @return A reference to this reader.
550 MultiKeyReader& operator=(MultiKeyReader&& reader) noexcept;
551 };
552
553 /// Creates a key reader for the given topic and key. This helper method deduces the topic Key, Value and
554 /// UpdateTag types from the topic argument.
555 /// @param topic The topic.
556 /// @param key The key.
557 /// @param name The optional reader name.
558 /// @param config The optional reader configuration.
559 template<typename K, typename V, typename UT>
561 const Topic<K, V, UT>& topic,
562 const typename Topic<K, V, UT>::KeyType& key,
563 std::string name = std::string(),
564 const ReaderConfig& config = ReaderConfig())
565 {
566 return SingleKeyReader<K, V, UT>(topic, key, std::move(name), config);
567 }
568
569 /// Creates a key reader for the given topic, key and sample filter. This helper method deduces the topic Key
570 /// and Value types from the topic argument.
571 /// @param topic The topic.
572 /// @param key The key.
573 /// @param sampleFilter The sample filter.
574 /// @param name The optional reader name.
575 /// @param config The optional reader configuration.
576 template<typename SFC, typename K, typename V, typename UT>
578 const Topic<K, V, UT>& topic,
579 const typename Topic<K, V, UT>::KeyType& key,
580 const Filter<SFC>& sampleFilter,
581 std::string name = std::string(),
582 const ReaderConfig& config = ReaderConfig())
583 {
584 return SingleKeyReader<K, V, UT>(topic, key, sampleFilter, std::move(name), config);
585 }
586
587 /// Creates a multi-key reader for the given topic. This helper method deduces the topic Key, Value and
588 /// UpdateTag types from the topic argument.
589 /// The reader will only receive samples for the given set of keys.
590 /// @param topic The topic.
591 /// @param keys The keys.
592 /// @param name The optional reader name.
593 /// @param config The optional reader configuration.
594 template<typename K, typename V, typename UT>
596 const Topic<K, V, UT>& topic,
597 const std::vector<typename Topic<K, V, UT>::KeyType>& keys,
598 std::string name = std::string(),
599 const ReaderConfig& config = ReaderConfig())
600 {
601 return MultiKeyReader<K, V, UT>(topic, keys, std::move(name), config);
602 }
603
604 /// Creates a multi-key reader for the given topic, keys and sample filter. This helper method deduces the
605 /// topic Key and Value types from the topic argument.
606 /// The reader will only receive samples for the given set of keys.
607 /// @param topic The topic.
608 /// @param keys The keys.
609 /// @param sampleFilter The sample filter.
610 /// @param name The optional reader name.
611 /// @param config The optional reader configuration.
612 template<typename SFC, typename K, typename V, typename UT>
614 const Topic<K, V, UT>& topic,
615 const std::vector<typename Topic<K, V, UT>::KeyType>& keys,
616 const Filter<SFC>& sampleFilter,
617 std::string name = std::string(),
618 const ReaderConfig& config = ReaderConfig())
619 {
620 return MultiKeyReader<K, V, UT>(topic, keys, sampleFilter, std::move(name), config);
621 }
622
623 /// Creates an any-key reader for the given topic. This helper method deduces the topic Key, Value and
624 /// UpdateTag types from the topic argument.
625 /// The reader will receive samples for any keys from the topic.
626 /// @param topic The topic.
627 /// @param name The optional reader name.
628 /// @param config The optional reader configuration.
629 template<typename K, typename V, typename UT>
631 const Topic<K, V, UT>& topic,
632 std::string name = std::string(),
633 const ReaderConfig& config = ReaderConfig())
634 {
635 return MultiKeyReader<K, V, UT>(topic, {}, std::move(name), config);
636 }
637
638 /// Creates an any-key reader for the given topic and sample filter. This helper method deduces the topic Key
639 /// and Value types from the topic argument.
640 /// The reader will receive samples for the keys from the topic.
641 /// @param topic The topic.
642 /// @param sampleFilter The sample filter.
643 /// @param name The optional reader name.
644 /// @param config The optional reader configuration.
645 template<typename SFC, typename K, typename V, typename UT>
647 const Topic<K, V, UT>& topic,
648 const Filter<SFC>& sampleFilter,
649 std::string name = std::string(),
650 const ReaderConfig& config = ReaderConfig())
651 {
652 return MultiKeyReader<K, V, UT>(topic, {}, sampleFilter, std::move(name), config);
653 }
654
655 /// The filtered reader to read data elements whose key match a given filter.
656 ///
657 /// A filtered reader retains the current value of every key it has received and not since seen removed, so that it
658 /// can resolve later partial updates against it. This per-key state is independent of the reader's `sampleCount`
659 /// and `sampleLifetime` history settings, and is released when the reader receives the key's remove sample. A
660 /// reader matching an unbounded set of keys therefore accumulates one current value per key.
661 /// @headerfile DataStorm/DataStorm.h
662 template<typename Key, typename Value, typename UpdateTag = std::string>
663 class FilteredKeyReader : public Reader<Key, Value, UpdateTag>
664 {
665 public:
666 /// Constructs a new reader for the given key filter. The construction of the reader connects the reader to
667 /// writers whose key matches the key filter criteria.
668 /// @param topic The topic.
669 /// @param keyFilter The key filter.
670 /// @param name The optional reader name.
671 /// @param config The reader configuration.
672 /// @throws std::invalid_argument Thrown when the key filter is not registered with the topic or the filter is
673 /// invalid.
674 template<typename KeyFilterCriteria>
676 const Topic<Key, Value, UpdateTag>& topic,
677 const Filter<KeyFilterCriteria>& keyFilter,
678 std::string name = std::string(),
679 const ReaderConfig& config = ReaderConfig());
680
681 /// Constructs a new reader for the given key filter and sample filter criteria. The construction of the
682 /// reader connects the reader to writers whose key matches the key filter criteria.
683 /// @param topic The topic.
684 /// @param keyFilter The key filter.
685 /// @param sampleFilter The sample filter.
686 /// @param name The optional reader name.
687 /// @param config The reader configuration.
688 /// @throws std::invalid_argument Thrown when the key filter is not registered with the topic or the filter is
689 /// invalid.
690 template<typename KeyFilterCriteria, typename SampleFilterCriteria>
692 const Topic<Key, Value, UpdateTag>& topic,
693 const Filter<KeyFilterCriteria>& keyFilter,
694 const Filter<SampleFilterCriteria>& sampleFilter,
695 std::string name = std::string(),
696 const ReaderConfig& config = ReaderConfig());
697
698 /// Move constructor
699 /// @param reader The reader to move from.
700 FilteredKeyReader(FilteredKeyReader&& reader) noexcept;
701
702 /// Move assignment operator.
703 /// @param reader The reader to move from.
704 /// @return A reference to this reader.
706 };
707
708 /// Creates a new filtered reader for the given topic and key filter. This helper method deduces the topic Key,
709 /// Value and UpdateTag types from the topic argument.
710 /// @param topic The topic.
711 /// @param filter The key filter.
712 /// @param name The optional reader name.
713 /// @param config The optional reader configuration.
714 template<typename KFC, typename K, typename V, typename UT>
716 const Topic<K, V, UT>& topic,
717 const Filter<KFC>& filter,
718 std::string name = std::string(),
719 const ReaderConfig& config = ReaderConfig())
720 {
721 return FilteredKeyReader<K, V, UT>(topic, filter, std::move(name), config);
722 }
723
724 /// Creates a new filter reader for the given topic, key filter and sample filter. This helper method deduces
725 /// the topic Key, Value and UpdateTag types from the topic argument.
726 /// @param topic The topic.
727 /// @param keyFilter The key filter.
728 /// @param sampleFilter The sample filter.
729 /// @param name The optional reader name.
730 /// @param config The optional reader configuration.
731 template<typename KFC, typename SFC, typename K, typename V, typename UT>
733 const Topic<K, V, UT>& topic,
734 const Filter<KFC>& keyFilter,
735 const Filter<SFC>& sampleFilter,
736 std::string name = std::string(),
737 const ReaderConfig& config = ReaderConfig())
738 {
739 return FilteredKeyReader<K, V, UT>(topic, keyFilter, sampleFilter, std::move(name), config);
740 }
741
742 /// The key writer to write the data element associated with a given key.
743 /// @headerfile DataStorm/DataStorm.h
744 template<typename Key, typename Value, typename UpdateTag = std::string>
745 class SingleKeyWriter : public Writer<Key, Value, UpdateTag>
746 {
747 public:
748 /// Constructs a new writer for the given key. The construction of the writer connects the writer to readers
749 /// with a matching key.
750 /// @param topic The topic.
751 /// @param key The key of the data element to write.
752 /// @param name The optional writer name.
753 /// @param config The writer configuration.
755 const Topic<Key, Value, UpdateTag>& topic,
756 const Key& key,
757 std::string name = std::string(),
758 const WriterConfig& config = WriterConfig());
759
760 /// Move constructor.
761 /// @param writer The writer to move from.
762 SingleKeyWriter(SingleKeyWriter&& writer) noexcept;
763
764 /// Move assignment operator.
765 /// @param writer The writer to move from.
766 /// @return A reference to this writer.
767 SingleKeyWriter& operator=(SingleKeyWriter&& writer) noexcept;
768
769 /// Adds the data element. This generates a SampleEvent::Add sample with the given value.
770 /// @param value The data element value.
771 void add(const Value& value);
772
773 /// Updates the data element. This generates a SampleEvent::Update sample with the given value.
774 /// @param value The data element value.
775 void update(const Value& value);
776
777 /// Gets a partial update generator function for the given partial update tag. When called, the returned
778 /// function generates a SampleEvent::PartialUpdate sample with the given partial update value.
779 /// The UpdateValue template parameter must match the UpdateValue type used to register the updater with
780 /// the Topic::setUpdater method.
781 /// A partial update resolves against the key's current value, so the key must have a current value when the
782 /// returned function is called: a full value was written for the key and the key was not since removed.
783 /// Calling the returned function for a key with no current value is an application error that throws
784 /// std::logic_error and publishes nothing.
785 /// @param tag The partial update tag.
786 template<typename UpdateValue>
787 [[nodiscard]] std::function<void(const UpdateValue&)> partialUpdate(const UpdateTag& tag);
788
789 /// Removes the data element. This generates a SampleEvent::Remove sample and releases the key's current value
790 /// on the writer and on the readers that receive the sample, so a later partial update has no value to resolve
791 /// against and is rejected until a new full value is written.
792 void remove() noexcept;
793
794 private:
795 const std::shared_ptr<DataStormI::TagFactoryT<UpdateTag>> _tagFactory;
796 };
797
798 /// The key writer to write data elements associated with a given set of keys.
799 ///
800 /// A multi-key writer retains the current value of every key it has written and not since removed, so that later
801 /// partial updates and late-joining readers can resolve against it. This per-key state is the writer's current data
802 /// set, not retained history: it is independent of the `sampleCount` and `sampleLifetime` history settings, which
803 /// bound the retained samples but never the current value of a live key. An any-key writer (one constructed with
804 /// an empty key vector) that writes to an unbounded set of keys therefore accumulates one current value per key;
805 /// call remove(const Key&) to retire a key and release its state once the key is no longer in use.
806 /// @headerfile DataStorm/DataStorm.h
807 template<typename Key, typename Value, typename UpdateTag = std::string>
808 class MultiKeyWriter : public Writer<Key, Value, UpdateTag>
809 {
810 public:
811 /// Constructs a new writer for the given keys. The construction of the writer connects the writer to
812 /// readers with matching keys. If an empty vector of keys is provided, the writer will connect to all the
813 /// available readers.
814 /// @param topic The topic.
815 /// @param keys The keys.
816 /// @param name The optional writer name.
817 /// @param config The writer configuration.
819 const Topic<Key, Value, UpdateTag>& topic,
820 const std::vector<Key>& keys,
821 std::string name = std::string(),
822 const WriterConfig& config = WriterConfig());
823
824 /// Move constructor
825 /// @param writer The writer to move from.
826 MultiKeyWriter(MultiKeyWriter&& writer) noexcept;
827
828 /// Move assignment operator.
829 /// @param writer The writer to move from.
830 /// @return A reference to this writer.
831 MultiKeyWriter& operator=(MultiKeyWriter&& writer) noexcept;
832
833 /// Adds the data element. This generates a SampleEvent::Add sample with the given value.
834 /// @param key The key
835 /// @param value The data element value.
836 void add(const Key& key, const Value& value);
837
838 /// Updates the data element. This generates a SampleEvent::Update sample with the given value.
839 /// @param key The key
840 /// @param value The data element value.
841 void update(const Key& key, const Value& value);
842
843 /// Gets a partial update generator function for the given partial update tag. When called, the returned
844 /// function generates a SampleEvent::PartialUpdate sample with the given partial update value.
845 /// The UpdateValue template parameter must match the UpdateValue type used to register the updater with
846 /// the Topic::setUpdater method.
847 /// A partial update resolves against the key's current value, so the key must have a current value when the
848 /// returned function is called: a full value was written for the key and the key was not since removed.
849 /// Calling the returned function for a key with no current value is an application error that throws
850 /// std::logic_error and publishes nothing.
851 /// @param tag The partial update tag.
852 template<typename UpdateValue>
853 [[nodiscard]] std::function<void(const Key&, const UpdateValue&)> partialUpdate(const UpdateTag& tag);
854
855 /// Removes the data element. This generates a SampleEvent::Remove sample and retires the key: its current value
856 /// is released on the writer and on the readers that receive the sample, so a later partial update for the key
857 /// has no value to resolve against and is rejected until a new full value is written.
858 /// @param key The key
859 void remove(const Key& key) noexcept;
860
861 private:
862 const std::shared_ptr<DataStormI::KeyFactoryT<Key>> _keyFactory;
863 const std::shared_ptr<DataStormI::TagFactoryT<UpdateTag>> _tagFactory;
864 };
865
866 /// Creates a key writer for the given topic and key. This helper method deduces the topic Key, Value and
867 /// UpdateTag types from the topic argument.
868 /// @param topic The topic.
869 /// @param key The key.
870 /// @param name The optional writer name.
871 /// @param config The optional writer configuration.
872 template<typename K, typename V, typename UT>
874 const Topic<K, V, UT>& topic,
875 const typename Topic<K, V, UT>::KeyType& key,
876 std::string name = std::string(),
877 const WriterConfig& config = WriterConfig())
878 {
879 return SingleKeyWriter<K, V, UT>(topic, key, std::move(name), config);
880 }
881
882 /// Creates a multi-key writer for the given topic and keys. This helper method deduces the topic Key, Value
883 /// and UpdateTag types from the topic argument.
884 /// @param topic The topic.
885 /// @param keys The keys.
886 /// @param name The optional writer name.
887 /// @param config The optional writer configuration.
888 template<typename K, typename V, typename UT>
890 const Topic<K, V, UT>& topic,
891 const std::vector<typename Topic<K, V, UT>::KeyType>& keys,
892 std::string name = std::string(),
893 const WriterConfig& config = WriterConfig())
894 {
895 return MultiKeyWriter<K, V, UT>(topic, keys, std::move(name), config);
896 }
897
898 /// Creates an any-key writer for the given topic. This helper method deduces the topic Key, Value and
899 /// UpdateTag types from the topic argument.
900 /// @param topic The topic.
901 /// @param name The optional writer name.
902 /// @param config The optional writer configuration.
903 template<typename K, typename V, typename UT>
905 const Topic<K, V, UT>& topic,
906 std::string name = std::string(),
907 const WriterConfig& config = WriterConfig())
908 {
909 return MultiKeyWriter<K, V, UT>(topic, {}, std::move(name), config);
910 }
911
912 //
913 // Public template based API implementation
914 //
915
916 //
917 // Sample template implementation
918 //
919 template<typename Key, typename Value, typename UpdateTag>
921 {
922 return _impl->event;
923 }
924
925 template<typename Key, typename Value, typename UpdateTag>
926 const Key& Sample<Key, Value, UpdateTag>::getKey() const noexcept
927 {
928 return _impl->getKey();
929 }
930
931 template<typename Key, typename Value, typename UpdateTag>
932 const Value& Sample<Key, Value, UpdateTag>::getValue() const noexcept
933 {
934 return _impl->getValue();
935 }
936
937 template<typename Key, typename Value, typename UpdateTag>
939 {
940 return _impl->getTag();
941 }
942
943 template<typename Key, typename Value, typename UpdateTag>
944 std::chrono::time_point<std::chrono::system_clock> Sample<Key, Value, UpdateTag>::getTimeStamp() const noexcept
945 {
946 return _impl->timestamp;
947 }
948
949 template<typename Key, typename Value, typename UpdateTag>
950 const std::string& Sample<Key, Value, UpdateTag>::getOrigin() const noexcept
951 {
952 return _impl->origin;
953 }
954
955 template<typename Key, typename Value, typename UpdateTag>
956 const std::string& Sample<Key, Value, UpdateTag>::getSession() const noexcept
957 {
958 return _impl->session;
959 }
960
961 template<typename Key, typename Value, typename UpdateTag>
962 Sample<Key, Value, UpdateTag>::Sample(const std::shared_ptr<DataStormI::Sample>& impl) noexcept
963 : _impl(std::static_pointer_cast<DataStormI::SampleT<Key, Value, UpdateTag>>(impl))
964 {
965 }
966
967 //
968 // Reader template implementation
969 //
970 template<typename Key, typename Value, typename UpdateTag>
972 : _impl(std::move(reader._impl))
973 {
974 }
975
976 template<typename Key, typename Value, typename UpdateTag> Reader<Key, Value, UpdateTag>::~Reader()
977 {
978 if (_impl)
979 {
980 _impl->destroy();
981 }
982 }
983
984 template<typename Key, typename Value, typename UpdateTag>
986 {
987 if (_impl)
988 {
989 _impl->destroy();
990 }
991 _impl = std::move(reader._impl);
992 return *this;
993 }
994
995 template<typename Key, typename Value, typename UpdateTag>
997 {
998 return _impl->hasWriters();
999 }
1000
1001 template<typename Key, typename Value, typename UpdateTag>
1003 {
1004 _impl->waitForWriters(static_cast<int>(count));
1005 }
1006
1007 template<typename Key, typename Value, typename UpdateTag>
1009 {
1010 _impl->waitForWriters(-1);
1011 }
1012
1013 template<typename Key, typename Value, typename UpdateTag>
1015 {
1016 return _impl->getConnectedElements();
1017 }
1018
1019 template<typename Key, typename Value, typename UpdateTag>
1021 {
1022 std::vector<Key> keys;
1023 auto connectedKeys = _impl->getConnectedKeys();
1024 keys.reserve(connectedKeys.size());
1025 for (const auto& k : connectedKeys)
1026 {
1027 keys.push_back(std::static_pointer_cast<DataStormI::KeyT<Key>>(k)->get());
1028 }
1029 return keys;
1030 }
1031
1032 template<typename Key, typename Value, typename UpdateTag>
1033 std::vector<Sample<Key, Value, UpdateTag>> Reader<Key, Value, UpdateTag>::getAllUnread()
1034 {
1035 auto unread = _impl->getAllUnread();
1036 std::vector<Sample<Key, Value, UpdateTag>> samples;
1037 samples.reserve(unread.size());
1038 for (const auto& sample : unread)
1039 {
1040 samples.push_back(sample);
1041 }
1042 return samples;
1043 }
1044
1045 template<typename Key, typename Value, typename UpdateTag>
1047 {
1048 _impl->waitForUnread(count);
1049 }
1050
1051 template<typename Key, typename Value, typename UpdateTag>
1053 {
1054 return _impl->hasUnread();
1055 }
1056
1057 template<typename Key, typename Value, typename UpdateTag>
1062
1063 template<typename Key, typename Value, typename UpdateTag>
1065 std::function<void(std::vector<Key>)> init,
1066 std::function<void(CallbackReason, Key)> update) noexcept
1067 {
1068 _impl->onConnectedKeys(
1069 init ?
1070 [init = std::move(init)](const std::vector<std::shared_ptr<DataStormI::Key>>& connectedKeys)
1071 {
1072 std::vector<Key> keys;
1073 keys.reserve(connectedKeys.size());
1074 for(const auto& k : connectedKeys)
1075 {
1076 keys.push_back(std::static_pointer_cast<DataStormI::KeyT<Key>>(k)->get());
1077 }
1078 init(std::move(keys));
1079 } : std::function<void(std::vector<std::shared_ptr<DataStormI::Key>>)>{},
1080 update ?
1081 [update = std::move(update)](CallbackReason action, const std::shared_ptr<DataStormI::Key>& key)
1082 {
1083 update(action, std::static_pointer_cast<DataStormI::KeyT<Key>>(key)->get());
1084 } : std::function<void(CallbackReason, std::shared_ptr<DataStormI::Key>)>{});
1085 }
1086
1087 template<typename Key, typename Value, typename UpdateTag>
1089 std::function<void(std::vector<std::string>)> init,
1090 std::function<void(CallbackReason, std::string)> update) noexcept
1091 {
1092 _impl->onConnectedElements(std::move(init), std::move(update));
1093 }
1094
1095 template<typename Key, typename Value, typename UpdateTag>
1097 std::function<void(std::vector<Sample<Key, Value, UpdateTag>>)> init,
1098 std::function<void(Sample<Key, Value, UpdateTag>)> update) noexcept
1099 {
1100 auto communicator = _impl->getCommunicator();
1101 _impl->onSamples(
1102 init ?
1103 [communicator, init = std::move(init)](const std::vector<std::shared_ptr<DataStormI::Sample>>& samplesI)
1104 {
1105 std::vector<Sample<Key, Value, UpdateTag>> samples;
1106 samples.reserve(samplesI.size());
1107 for(const auto& s : samplesI)
1108 {
1109 samples.emplace_back(s);
1110 }
1111 init(std::move(samples));
1112 } : std::function<void(const std::vector<std::shared_ptr<DataStormI::Sample>>&)>(),
1113 update ?
1114 [communicator, update = std::move(update)](const std::shared_ptr<DataStormI::Sample>& sampleI)
1115 {
1116 update(sampleI);
1117 } : std::function<void(const std::shared_ptr<DataStormI::Sample>&)>{});
1118 }
1119
1120 template<typename Key, typename Value, typename UpdateTag>
1122 const Topic<Key, Value, UpdateTag>& topic,
1123 const Key& key,
1124 std::string name,
1125 const ReaderConfig& config)
1126 : Reader<Key, Value, UpdateTag>(
1127 topic.getReader()->create({topic._keyFactory->create(key)}, std::move(name), config))
1128 {
1129 }
1130
1131 template<typename Key, typename Value, typename UpdateTag>
1132 template<typename SampleFilterCriteria>
1134 const Topic<Key, Value, UpdateTag>& topic,
1135 const Key& key,
1136 const Filter<SampleFilterCriteria>& sampleFilter,
1137 std::string name,
1138 const ReaderConfig& config)
1139 : Reader<Key, Value, UpdateTag>(topic.getReader()->create(
1140 {topic._keyFactory->create(key)},
1141 std::move(name),
1142 config,
1143 sampleFilter.name,
1144 DataStormI::EncoderT<SampleFilterCriteria>::encode(topic.getCommunicator(), sampleFilter.criteria)))
1145 {
1146 }
1147
1148 template<typename Key, typename Value, typename UpdateTag>
1153
1154 template<typename Key, typename Value, typename UpdateTag>
1157 {
1159 return *this;
1160 }
1161
1162 template<typename Key, typename Value, typename UpdateTag>
1164 const Topic<Key, Value, UpdateTag>& topic,
1165 const std::vector<Key>& keys,
1166 std::string name,
1167 const ReaderConfig& config)
1168 : Reader<Key, Value, UpdateTag>(
1169 topic.getReader()->create(topic._keyFactory->create(keys), std::move(name), config))
1170 {
1171 }
1172
1173 template<typename Key, typename Value, typename UpdateTag>
1174 template<typename SampleFilterCriteria>
1176 const Topic<Key, Value, UpdateTag>& topic,
1177 const std::vector<Key>& keys,
1178 const Filter<SampleFilterCriteria>& sampleFilter,
1179 std::string name,
1180 const ReaderConfig& config)
1181 : Reader<Key, Value, UpdateTag>(topic.getReader()->create(
1182 topic._keyFactory->create(keys),
1183 std::move(name),
1184 config,
1185 sampleFilter.name,
1186 DataStormI::EncoderT<SampleFilterCriteria>::encode(topic.getCommunicator(), sampleFilter.criteria)))
1187 {
1188 }
1189
1190 template<typename Key, typename Value, typename UpdateTag>
1195
1196 template<typename Key, typename Value, typename UpdateTag>
1199 {
1201 return *this;
1202 }
1203
1204 template<typename Key, typename Value, typename UpdateTag>
1205 template<typename KeyFilterCriteria>
1207 const Topic<Key, Value, UpdateTag>& topic,
1208 const Filter<KeyFilterCriteria>& filter,
1209 std::string name,
1210 const ReaderConfig& config)
1211 : Reader<Key, Value, UpdateTag>(topic.getReader()->createFiltered(
1212 topic._keyFilterFactories->create(filter.name, filter.criteria),
1213 std::move(name),
1214 config))
1215 {
1216 }
1217
1218 template<typename Key, typename Value, typename UpdateTag>
1219 template<typename KeyFilterCriteria, typename SampleFilterCriteria>
1221 const Topic<Key, Value, UpdateTag>& topic,
1222 const Filter<KeyFilterCriteria>& keyFilter,
1223 const Filter<SampleFilterCriteria>& sampleFilter,
1224 std::string name,
1225 const ReaderConfig& config)
1226 : Reader<Key, Value, UpdateTag>(topic.getReader()->createFiltered(
1227 topic._keyFilterFactories->create(keyFilter.name, keyFilter.criteria),
1228 std::move(name),
1229 config,
1230 sampleFilter.name,
1231 DataStormI::EncoderT<SampleFilterCriteria>::encode(topic.getCommunicator(), sampleFilter.criteria)))
1232 {
1233 }
1234
1235 template<typename Key, typename Value, typename UpdateTag>
1241
1242 template<typename Key, typename Value, typename UpdateTag>
1245 {
1247 return *this;
1248 }
1249
1250 //
1251 // Writer template implementation
1252 //
1253 template<typename Key, typename Value, typename UpdateTag>
1254 Writer<Key, Value, UpdateTag>::Writer(Writer&& writer) noexcept : _impl(std::move(writer._impl))
1255 {
1256 }
1257
1258 template<typename Key, typename Value, typename UpdateTag> Writer<Key, Value, UpdateTag>::~Writer()
1259 {
1260 if (_impl)
1261 {
1262 _impl->destroy();
1263 }
1264 }
1265
1266 template<typename Key, typename Value, typename UpdateTag>
1268 {
1269 if (_impl)
1270 {
1271 _impl->destroy();
1272 }
1273 _impl = std::move(writer._impl);
1274 return *this;
1275 }
1276
1277 template<typename Key, typename Value, typename UpdateTag>
1279 {
1280 return _impl->hasReaders();
1281 }
1282
1283 template<typename Key, typename Value, typename UpdateTag>
1285 {
1286 return _impl->waitForReaders(static_cast<int>(count));
1287 }
1288
1289 template<typename Key, typename Value, typename UpdateTag>
1291 {
1292 return _impl->waitForReaders(-1);
1293 }
1294
1295 template<typename Key, typename Value, typename UpdateTag>
1297 {
1298 return _impl->getConnectedElements();
1299 }
1300
1301 template<typename Key, typename Value, typename UpdateTag>
1303 {
1304 std::vector<Key> keys;
1305 auto connectedKeys = _impl->getConnectedKeys();
1306 keys.reserve(connectedKeys.size());
1307 for (const auto& k : connectedKeys)
1308 {
1309 keys.push_back(std::static_pointer_cast<DataStormI::KeyT<Key>>(k)->get());
1310 }
1311 return keys;
1312 }
1313
1314 template<typename Key, typename Value, typename UpdateTag>
1316 {
1317 auto sample = _impl->getLast();
1318 if (!sample)
1319 {
1320 throw std::logic_error("no sample");
1321 }
1322 return Sample<Key, Value, UpdateTag>(sample);
1323 }
1324
1325 template<typename Key, typename Value, typename UpdateTag>
1326 std::vector<Sample<Key, Value, UpdateTag>> Writer<Key, Value, UpdateTag>::getAll()
1327 {
1328 auto all = _impl->getAll();
1329 std::vector<Sample<Key, Value, UpdateTag>> samples;
1330 samples.reserve(all.size());
1331 for (const auto& sample : all)
1332 {
1333 samples.push_back(sample);
1334 }
1335 return samples;
1336 }
1337
1338 template<typename Key, typename Value, typename UpdateTag>
1340 std::function<void(std::vector<Key>)> init,
1341 std::function<void(CallbackReason, Key)> update) noexcept
1342 {
1343 _impl->onConnectedKeys(
1344 init ?
1345 [init = std::move(init)](const std::vector<std::shared_ptr<DataStormI::Key>>& connectedKeys)
1346 {
1347 std::vector<Key> keys;
1348 keys.reserve(connectedKeys.size());
1349 for(const auto& k : connectedKeys)
1350 {
1351 keys.push_back(std::static_pointer_cast<DataStormI::KeyT<Key>>(k)->get());
1352 }
1353 init(std::move(keys));
1354 } : std::function<void(std::vector<std::shared_ptr<DataStormI::Key>>)>{},
1355 update ?
1356 [update = std::move(update)](CallbackReason action, const std::shared_ptr<DataStormI::Key>& key)
1357 {
1358 update(action, std::static_pointer_cast<DataStormI::KeyT<Key>>(key)->get());
1359 } : std::function<void(CallbackReason, std::shared_ptr<DataStormI::Key>)>{});
1360 }
1361
1362 template<typename Key, typename Value, typename UpdateTag>
1364 std::function<void(std::vector<std::string>)> init,
1365 std::function<void(CallbackReason, std::string)> update) noexcept
1366 {
1367 _impl->onConnectedElements(std::move(init), std::move(update));
1368 }
1369
1370 template<typename Key, typename Value, typename UpdateTag>
1372 const Topic<Key, Value, UpdateTag>& topic,
1373 const Key& key,
1374 std::string name,
1375 const WriterConfig& config)
1376 : Writer<Key, Value, UpdateTag>(
1377 topic.getWriter()->create({topic._keyFactory->create(key)}, std::move(name), config)),
1378 _tagFactory(topic._tagFactory)
1379 {
1380 }
1381
1382 template<typename Key, typename Value, typename UpdateTag>
1384 : Writer<Key, Value, UpdateTag>(std::move(writer)),
1385 _tagFactory(std::move(writer._tagFactory))
1386 {
1387 }
1388
1389 template<typename Key, typename Value, typename UpdateTag>
1392 {
1394 return *this;
1395 }
1396
1397 template<typename Key, typename Value, typename UpdateTag>
1399 {
1400 Writer<Key, Value, UpdateTag>::_impl->publish(
1401 nullptr,
1402 std::make_shared<DataStormI::SampleT<Key, Value, UpdateTag>>(SampleEvent::Add, value));
1403 }
1404
1405 template<typename Key, typename Value, typename UpdateTag>
1407 {
1408 Writer<Key, Value, UpdateTag>::_impl->publish(
1409 nullptr,
1410 std::make_shared<DataStormI::SampleT<Key, Value, UpdateTag>>(SampleEvent::Update, value));
1411 }
1412
1413 template<typename Key, typename Value, typename UpdateTag>
1414 template<typename UpdateValue>
1415 std::function<void(const UpdateValue&)> SingleKeyWriter<Key, Value, UpdateTag>::partialUpdate(const UpdateTag& tag)
1416 {
1417 auto impl = Writer<Key, Value, UpdateTag>::_impl;
1418 auto updateTag = _tagFactory->create(tag);
1419 return [impl, updateTag](const UpdateValue& value)
1420 {
1421 auto encoded = DataStormI::EncoderT<UpdateValue>::encode(impl->getCommunicator(), value);
1422 impl->publish(nullptr, std::make_shared<DataStormI::SampleT<Key, Value, UpdateTag>>(encoded, updateTag));
1423 };
1424 }
1425
1426 template<typename Key, typename Value, typename UpdateTag>
1428 {
1429 Writer<Key, Value, UpdateTag>::_impl->publish(
1430 nullptr,
1431 std::make_shared<DataStormI::SampleT<Key, Value, UpdateTag>>(SampleEvent::Remove));
1432 }
1433
1434 template<typename Key, typename Value, typename UpdateTag>
1436 const Topic<Key, Value, UpdateTag>& topic,
1437 const std::vector<Key>& keys,
1438 std::string name,
1439 const WriterConfig& config)
1440 : Writer<Key, Value, UpdateTag>(
1441 topic.getWriter()->create(topic._keyFactory->create(keys), std::move(name), config)),
1442 _keyFactory(topic._keyFactory),
1443 _tagFactory(topic._tagFactory)
1444 {
1445 }
1446
1447 template<typename Key, typename Value, typename UpdateTag>
1449 : Writer<Key, Value, UpdateTag>(std::move(writer)),
1450 _keyFactory(std::move(writer._keyFactory)),
1451 _tagFactory(std::move(writer._tagFactory))
1452 {
1453 }
1454
1455 template<typename Key, typename Value, typename UpdateTag>
1458 {
1460 return *this;
1461 }
1462
1463 template<typename Key, typename Value, typename UpdateTag>
1464 void MultiKeyWriter<Key, Value, UpdateTag>::add(const Key& key, const Value& value)
1465 {
1466 Writer<Key, Value, UpdateTag>::_impl->publish(
1467 _keyFactory->create(key),
1468 std::make_shared<DataStormI::SampleT<Key, Value, UpdateTag>>(SampleEvent::Add, value));
1469 }
1470
1471 template<typename Key, typename Value, typename UpdateTag>
1472 void MultiKeyWriter<Key, Value, UpdateTag>::update(const Key& key, const Value& value)
1473 {
1474 Writer<Key, Value, UpdateTag>::_impl->publish(
1475 _keyFactory->create(key),
1476 std::make_shared<DataStormI::SampleT<Key, Value, UpdateTag>>(SampleEvent::Update, value));
1477 }
1478
1479 template<typename Key, typename Value, typename UpdateTag>
1480 template<typename UpdateValue>
1481 std::function<void(const Key&, const UpdateValue&)>
1483 {
1484 auto impl = Writer<Key, Value, UpdateTag>::_impl;
1485 auto updateTag = _tagFactory->create(tag);
1486 auto keyFactory = _keyFactory;
1487 return [impl, updateTag, keyFactory](const Key& key, const UpdateValue& value)
1488 {
1489 auto encoded = DataStormI::EncoderT<UpdateValue>::encode(impl->getCommunicator(), value);
1490 impl->publish(
1491 keyFactory->create(key),
1492 std::make_shared<DataStormI::SampleT<Key, Value, UpdateTag>>(encoded, updateTag));
1493 };
1494 }
1495
1496 template<typename Key, typename Value, typename UpdateTag>
1498 {
1499 Writer<Key, Value, UpdateTag>::_impl->publish(
1500 _keyFactory->create(key),
1501 std::make_shared<DataStormI::SampleT<Key, Value, UpdateTag>>(SampleEvent::Remove));
1502 }
1503
1504 /// @private
1505 template<typename Value> std::function<std::function<bool(const Value&)>(const std::string&)> makeRegexFilter()
1506 {
1507 // std::regex's constructor accepts a const string&; it does not accept a string_view.
1508 return [](const std::string& criteria)
1509 {
1510 std::regex expr(criteria);
1511 return [expr = std::move(expr)](const Value& value)
1512 {
1513 std::ostringstream os;
1514 os << value;
1515 return std::regex_match(os.str(), expr);
1516 };
1517 };
1518 }
1519
1520 /// @private
1521 template<typename Key, typename Value, typename UpdateTag>
1522 std::function<std::function<bool(const Sample<Key, Value, UpdateTag>&)>(const SampleEventSeq&)>
1523 makeSampleEventFilter(const Topic<Key, Value, UpdateTag>&)
1524 {
1525 return [](const SampleEventSeq& criteria)
1526 {
1527 return [criteria](const Sample<Key, Value, UpdateTag>& sample)
1528 { return std::find(criteria.begin(), criteria.end(), sample.getEvent()) != criteria.end(); };
1529 };
1530 }
1531
1532 /// @private
1533 template<typename T, typename V, typename Enabler = void> struct RegexFilter
1534 {
1535 template<typename F> static void add(const F&) {}
1536 };
1537
1538 /// @private
1539 template<typename T, typename V> struct RegexFilter<T, V, std::enable_if_t<DataStormI::is_streamable<V>::value>>
1540 {
1541 template<typename F> static void add(const F& factory)
1542 {
1543 factory->set("_regex", makeRegexFilter<T>()); // Only set the _regex filter if the value is streamable
1544 }
1545 };
1546
1547 //
1548 // Topic template implementation
1549 //
1550 template<typename Key, typename Value, typename UpdateTag>
1551 Topic<Key, Value, UpdateTag>::Topic(const Node& node, std::string name) noexcept
1552 : _name(std::move(name)),
1553 _topicFactory(node._factory),
1554 _keyFactory(DataStormI::KeyFactoryT<Key>::createFactory()),
1555 _tagFactory(DataStormI::TagFactoryT<UpdateTag>::createFactory()),
1556 _keyFilterFactories(std::make_shared<DataStormI::FilterManagerT<DataStormI::KeyT<Key>>>()),
1557 _sampleFilterFactories(
1558 std::make_shared<DataStormI::FilterManagerT<DataStormI::SampleT<Key, Value, UpdateTag>>>())
1559 {
1560 RegexFilter<Key, Key>::add(_keyFilterFactories);
1561 RegexFilter<Sample<Key, Value, UpdateTag>, Value>::add(_sampleFilterFactories);
1562 _sampleFilterFactories->set("_event", makeSampleEventFilter(*this));
1563 }
1564
1565 template<typename Key, typename Value, typename UpdateTag> Topic<Key, Value, UpdateTag>::~Topic()
1566 {
1567 std::lock_guard<std::mutex> lock(_mutex);
1568 if (_reader)
1569 {
1570 _reader->destroy();
1571 }
1572 if (_writer)
1573 {
1574 _writer->destroy();
1575 }
1576 }
1577
1578 template<typename Key, typename Value, typename UpdateTag>
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 _name = std::move(topic._name);
1591 _topicFactory = std::move(topic._topicFactory);
1592 _keyFactory = std::move(topic._keyFactory);
1593 _tagFactory = std::move(topic._tagFactory);
1594 _keyFilterFactories = std::move(topic._keyFilterFactories);
1595 _sampleFilterFactories = std::move(topic._sampleFilterFactories);
1596 _reader = std::move(topic._reader);
1597 _writer = std::move(topic._writer);
1598 _updaters = std::move(topic._updaters);
1599 return *this;
1600 }
1601
1602 template<typename Key, typename Value, typename UpdateTag>
1604 {
1605 return getReader()->hasWriters();
1606 }
1607
1608 template<typename Key, typename Value, typename UpdateTag>
1610 {
1611 getReader()->waitForWriters(static_cast<int>(count));
1612 }
1613
1614 template<typename Key, typename Value, typename UpdateTag>
1616 {
1617 getReader()->waitForWriters(-1);
1618 }
1619
1620 template<typename Key, typename Value, typename UpdateTag>
1622 {
1623 getReader()->setDefaultConfig(config);
1624 }
1625
1626 template<typename Key, typename Value, typename UpdateTag>
1628 {
1629 return getWriter()->hasReaders();
1630 }
1631
1632 template<typename Key, typename Value, typename UpdateTag>
1634 {
1635 getWriter()->waitForReaders(static_cast<int>(count));
1636 }
1637
1638 template<typename Key, typename Value, typename UpdateTag>
1640 {
1641 getWriter()->waitForReaders(-1);
1642 }
1643
1644 template<typename Key, typename Value, typename UpdateTag>
1646 {
1647 getWriter()->setDefaultConfig(config);
1648 }
1649
1650 template<typename Key, typename Value, typename UpdateTag>
1651 template<typename UpdateValue>
1653 const UpdateTag& tag,
1654 std::function<void(Value&, UpdateValue)> updater) noexcept
1655 {
1656 std::lock_guard<std::mutex> lock(_mutex);
1657 auto tagI = _tagFactory->create(std::move(tag));
1658 auto updaterImpl =
1659 updater ?
1660 [updater = std::move(updater)](const std::shared_ptr<DataStormI::Sample>& previous,
1661 const std::shared_ptr<DataStormI::Sample>& next,
1662 const Ice::CommunicatorPtr& communicator)
1663 {
1664 // Every updater call site ensures the previous sample exists and has a value before invoking the
1665 // updater (the writer throws otherwise, the reader drops the sample), so this assert holds and the
1666 // clone below always runs. The guarded branch is not a safe release-build fallback for a broken
1667 // invariant: a default-constructed base is null for class-typed values, which the user's updater
1668 // would dereference just as if the guard were absent.
1669 assert(previous && previous->hasValue());
1670 Value value{};
1671 if (previous && previous->hasValue())
1672 {
1673 value = Cloner<Value>::clone(
1674 std::static_pointer_cast<DataStormI::SampleT<Key, Value, UpdateTag>>(previous)->getValue());
1675 }
1676 updater(value, DataStormI::DecoderT<UpdateValue>::decode(communicator, next->getEncodedValue()));
1677 std::static_pointer_cast<DataStormI::SampleT<Key, Value, UpdateTag>>(next)->setValue(std::move(value));
1678 } : std::function<void(const std::shared_ptr<DataStormI::Sample>&,
1679 const std::shared_ptr<DataStormI::Sample>&,
1680 const Ice::CommunicatorPtr&)>{};
1681
1682 if (_reader && !_writer)
1683 {
1684 _reader->setUpdater(tagI, updaterImpl);
1685 }
1686 else if (_writer && !_reader)
1687 {
1688 _writer->setUpdater(tagI, updaterImpl);
1689 }
1690 else if (_reader && _writer)
1691 {
1692 _reader->setUpdater(tagI, updaterImpl);
1693 _writer->setUpdater(tagI, updaterImpl);
1694 }
1695 else
1696 {
1697 _updaters[tagI] = updaterImpl;
1698 }
1699 }
1700
1701 template<typename Key, typename Value, typename UpdateTag>
1702 template<typename Criteria>
1704 std::string name,
1705 std::function<std::function<bool(const Key&)>(const Criteria&)> factory) noexcept
1706 {
1707 std::lock_guard<std::mutex> lock(_mutex);
1708 _keyFilterFactories->set(std::move(name), std::move(factory));
1709 }
1710
1711 template<typename Key, typename Value, typename UpdateTag>
1712 template<typename Criteria>
1714 std::string name,
1715 std::function<std::function<bool(const SampleType&)>(const Criteria&)> factory) noexcept
1716 {
1717 std::lock_guard<std::mutex> lock(_mutex);
1718 _sampleFilterFactories->set(std::move(name), std::move(factory));
1719 }
1720
1721 template<typename Key, typename Value, typename UpdateTag>
1722 std::shared_ptr<DataStormI::TopicReader> Topic<Key, Value, UpdateTag>::getReader() const
1723 {
1724 std::lock_guard<std::mutex> lock(_mutex);
1725 if (!_reader)
1726 {
1727 auto sampleFactory = std::make_shared<DataStormI::SampleFactoryT<Key, Value, UpdateTag>>();
1728 _reader = _topicFactory->createTopicReader(
1729 _name,
1730 _keyFactory,
1731 _tagFactory,
1732 std::move(sampleFactory),
1733 _keyFilterFactories,
1734 _sampleFilterFactories);
1735 _reader->setUpdaters(_writer ? _writer->getUpdaters() : _updaters);
1736 _updaters.clear();
1737 }
1738 return _reader;
1739 }
1740
1741 template<typename Key, typename Value, typename UpdateTag>
1742 std::shared_ptr<DataStormI::TopicWriter> Topic<Key, Value, UpdateTag>::getWriter() const
1743 {
1744 std::lock_guard<std::mutex> lock(_mutex);
1745 if (!_writer)
1746 {
1747 _writer = _topicFactory->createTopicWriter(
1748 _name,
1749 _keyFactory,
1750 _tagFactory,
1751 nullptr,
1752 _keyFilterFactories,
1753 _sampleFilterFactories);
1754 _writer->setUpdaters(_reader ? _reader->getUpdaters() : _updaters);
1755 _updaters.clear();
1756 }
1757 return _writer;
1758 }
1759
1760 template<typename Key, typename Value, typename UpdateTag>
1761 Ice::CommunicatorPtr Topic<Key, Value, UpdateTag>::getCommunicator() const noexcept
1762 {
1763 return _topicFactory->getCommunicator();
1764 }
1765}
1766
1767#if defined(__clang__)
1768# pragma clang diagnostic pop
1769#elif defined(__GNUC__)
1770# pragma GCC diagnostic pop
1771#endif
1772
1773#endif
FilteredKeyReader & operator=(FilteredKeyReader &&reader) noexcept
Move assignment operator.
Definition DataStorm.h:1244
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:1206
The filtered reader to read data elements whose key match a given filter.
Definition DataStorm.h:664
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:1163
MultiKeyReader & operator=(MultiKeyReader &&reader) noexcept
Move assignment operator.
Definition DataStorm.h:1198
The key reader to read the data element associated with a given set of keys.
Definition DataStorm.h:511
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:1482
void add(const Key &key, const Value &value)
Adds the data element.
Definition DataStorm.h:1464
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:1435
void remove(const Key &key) noexcept
Removes the data element.
Definition DataStorm.h:1497
void update(const Key &key, const Value &value)
Updates the data element.
Definition DataStorm.h:1472
MultiKeyWriter & operator=(MultiKeyWriter &&writer) noexcept
Move assignment operator.
Definition DataStorm.h:1457
The key writer to write data elements associated with a given set of keys.
Definition DataStorm.h:809
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:92
std::vector< Key > getConnectedKeys() const
Gets the keys for which writers are connected to this reader.
Definition DataStorm.h:1020
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:1088
std::vector< std::string > getConnectedWriters() const
Gets the connected writers.
Definition DataStorm.h:1014
Reader & operator=(Reader &&reader) noexcept
Move assignment operator.
Definition DataStorm.h:985
void waitForNoWriters() const
Waits for writers to be offline.
Definition DataStorm.h:1008
Value ValueType
The value type.
Definition DataStorm.h:116
Reader(Reader &&reader) noexcept
Move constructor.
Definition DataStorm.h:971
void waitForWriters(unsigned int count=1) const
Waits for the given number of writers to be online.
Definition DataStorm.h:1002
bool hasUnread() const noexcept
Returns whether or not unread samples are available.
Definition DataStorm.h:1052
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:1064
std::vector< Sample< Key, Value, UpdateTag > > getAllUnread()
Returns all the unread samples.
Definition DataStorm.h:1033
Sample< Key, Value, UpdateTag > getNextUnread()
Returns the next unread sample.
Definition DataStorm.h:1058
Key KeyType
The key type.
Definition DataStorm.h:113
bool hasWriters() const noexcept
Indicates whether or not writers are online.
Definition DataStorm.h:996
void waitForUnread(unsigned int count=1) const
Waits for the given number of unread samples to be available.
Definition DataStorm.h:1046
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:1096
~Reader()
Destructor.
Definition DataStorm.h:976
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:920
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:1156
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:1121
The key reader to read the data element associated with a given key.
Definition DataStorm.h:461
std::function< void(const UpdateValue &)> partialUpdate(const UpdateTag &tag)
Gets a partial update generator function for the given partial update tag.
Definition DataStorm.h:1415
void add(const Value &value)
Adds the data element.
Definition DataStorm.h:1398
void update(const Value &value)
Updates the data element.
Definition DataStorm.h:1406
void remove() noexcept
Removes the data element.
Definition DataStorm.h:1427
SingleKeyWriter & operator=(SingleKeyWriter &&writer) noexcept
Move assignment operator.
Definition DataStorm.h:1391
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:1371
The key writer to write the data element associated with a given key.
Definition DataStorm.h:746
void setUpdater(const UpdateTag &tag, std::function< void(Value &, UpdateValue)> updater) noexcept
Sets an updater function for the given update tag.
Definition DataStorm.h:1652
Topic(const Node &node, std::string name) noexcept
Constructs a new Topic for the topic with the given name.
Definition DataStorm.h:1551
void setKeyFilter(std::string name, std::function< std::function< bool(const Key &)>(const Criteria &)> factory) noexcept
Sets a key filter factory.
Definition DataStorm.h:1703
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:1633
void waitForNoWriters() const
Waits for data writers to be offline.
Definition DataStorm.h:1615
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:1627
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:1713
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:1603
void setWriterDefaultConfig(const WriterConfig &config) noexcept
Sets the default configuration used to construct writers.
Definition DataStorm.h:1645
Topic & operator=(Topic &&topic) noexcept
Move assignment operator.
Definition DataStorm.h:1579
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:1621
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:1609
void waitForNoReaders() const
Waits for data readers to be offline.
Definition DataStorm.h:1639
~Topic()
Destructor.
Definition DataStorm.h:1565
The Topic class.
Definition DataStorm.h:297
The WriterConfig class specifies configuration options specific to writers.
Definition Types.h:118
Sample< Key, Value, UpdateTag > getLast()
Gets the last written sample.
Definition DataStorm.h:1315
Writer & operator=(Writer &&writer) noexcept
Move assignment operator.
Definition DataStorm.h:1267
std::vector< Sample< Key, Value, UpdateTag > > getAll()
Gets all the written sample kept in the writer history.
Definition DataStorm.h:1326
std::vector< std::string > getConnectedReaders() const
Gets the connected readers.
Definition DataStorm.h:1296
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:1363
void waitForReaders(unsigned int count=1) const
Waits for the given number of readers to be online.
Definition DataStorm.h:1284
~Writer()
Destructor.
Definition DataStorm.h:1258
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:1339
bool hasReaders() const noexcept
Indicates whether or not readers are online.
Definition DataStorm.h:1278
std::vector< Key > getConnectedKeys() const
Gets the keys for which readers are connected to this writer.
Definition DataStorm.h:1302
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:1254
void waitForNoReaders() const
Waits for readers to be offline.
Definition DataStorm.h:1290
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: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:560
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:715
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:630
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:889
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:873
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:595
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:904
CallbackReason
The callback action enumerator specifies the reason why a callback is called.
Definition Types.h:141
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:186
Filter(std::string name, TT &&criteria) noexcept
Constructs a filter structure with the given name and criteria.
Definition DataStorm.h:445
std::string name
The filter name.
Definition DataStorm.h:451
T criteria
The filter criteria value.
Definition DataStorm.h:454
Filter structure to specify the filter name and criteria value.
Definition DataStorm.h:440