Ocean
Loading...
Searching...
No Matches
DataSerializer.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_IO_SERIALIZATION_DATA_SERIALIZER_H
9#define META_OCEAN_IO_SERIALIZATION_DATA_SERIALIZER_H
10
12
14#include "ocean/base/Thread.h"
15
16#include "ocean/io/Bitstream.h"
19
20namespace Ocean
21{
22
23namespace IO
24{
25
26namespace Serialization
27{
28
29/**
30 * This class implements the base class for data serializers.
31 * Data serializers are used to serialize and deserialize data samples across multiple channels.
32 * Each channel can have a different sample type, name, and content type.
33 * @ingroup ioserialization
34 */
35class OCEAN_IO_SERIALIZATION_EXPORT DataSerializer : protected Thread
36{
37 public:
38
39 /// Definition of a channel id.
40 using ChannelId = uint32_t;
41
42 /**
43 * Returns an invalid channel id.
44 * @return The invalid channel id
45 */
46 static constexpr ChannelId invalidChannelId();
47
48 /**
49 * This class holds channel configuration (sample type, name, and content type).
50 */
52 {
53 public:
54
55 /**
56 * Definition of a hash function for ChannelConfiguration objects.
57 */
58 struct Hash
59 {
60 /**
61 * Calculates the hash value for a given channel configuration.
62 * @param channelConfiguration The channel configuration for which the hash will be calculated
63 * @return The hash value
64 */
65 inline size_t operator()(const ChannelConfiguration& channelConfiguration) const;
66 };
67
68 public:
69
70 /**
71 * Creates a new invalid channel configuration.
72 */
74
75 /**
76 * Creates a new channel configuration with given sample type, name, and content type.
77 * @param sampleType The sample type
78 * @param name The name of the channel
79 * @param contentType The content type
80 */
81 inline ChannelConfiguration(const std::string& sampleType, const std::string& name, const std::string& contentType);
82
83 /**
84 * Returns the sample type.
85 * @return The sample type
86 */
87 inline const std::string& sampleType() const;
88
89 /**
90 * Returns the name of the channel.
91 * @return The channel name
92 */
93 inline const std::string& name() const;
94
95 /**
96 * Returns the content type.
97 * @return The content type
98 */
99 inline const std::string& contentType() const;
100
101 /**
102 * Returns whether this channel configuration is valid.
103 * @return True, if all fields (sample type, name, and content type) are non-empty
104 */
105 inline bool isValid() const;
106
107 /**
108 * Returns whether two channel configurations are equal.
109 * @param channelConfiguration The second channel configuration to compare
110 * @return True, if both configurations are equal
111 */
112 inline bool operator==(const ChannelConfiguration& channelConfiguration) const;
113
114 protected:
115
116 /// The sample type.
117 std::string sampleType_;
118
119 /// The name of the channel.
120 std::string name_;
121
122 /// The content type.
123 std::string contentType_;
124 };
125
126 /**
127 * This class implements a channel with configuration and channel id.
128 */
130 {
131 public:
132
133 /**
134 * Definition of a hash function for Channel objects.
135 */
136 struct Hash
137 {
138 /**
139 * Calculates the hash value for a given channel.
140 * @param channel The channel for which the hash will be calculated
141 * @return The hash value
142 */
143 inline size_t operator()(const Channel& channel) const;
144 };
145
146 public:
147
148 /**
149 * Creates a new invalid channel.
150 */
151 Channel() = default;
152
153 /**
154 * Creates a new channel with given configuration and channel id.
155 * @param channelConfiguration The channel configuration
156 * @param channelId The channel id
157 */
158 inline Channel(const ChannelConfiguration& channelConfiguration, const ChannelId channelId);
159
160 /**
161 * Returns the channel id.
162 * @return The channel id
163 */
164 inline ChannelId channelId() const;
165
166 /**
167 * Returns whether this channel is valid.
168 * @return True, if the channel id is valid and the configuration is valid
169 */
170 inline bool isValid() const;
171
172 /**
173 * Returns whether two channels are equal.
174 * @param channel The second channel to compare
175 * @return True, if both channels are equal
176 */
177 inline bool operator==(const Channel& channel) const;
178
179 protected:
180
181 /// The channel id.
182 ChannelId channelId_ = invalidChannelId();
183 };
184
185 /// Definition of a vector holding channels.
186 using Channels = std::vector<Channel>;
187
188 protected:
189
190 /**
191 * Definition of individual states the serializer can have.
192 */
193 enum State
194 {
195 /// The serializer has not yet been initialized or started.
197 /// The serializer has been initialized and is ready to start.
199 /// The serializer has been started and is currently actively processing data samples.
201 /// The serializer is currently stopping but may still process remaining data samples.
203 /// The serializer has been stopped and all active processing of data samples has finished. However, there may still be samples left which could be requested by the user.
204 S_STOPPED
205 };
206
207 /// Definition of a map mapping channel configurations to channel ids.
208 using ChannelConfigurationMap = std::unordered_map<ChannelConfiguration, ChannelId, ChannelConfiguration::Hash>;
209
210 /// Definition of a pair holding a channel id and a unique data sample.
211 using SamplePair = std::pair<ChannelId, UniqueDataSample>;
212
213 /// Definition of a queue holding sample pairs.
214 using SampleQueue = std::queue<SamplePair>;
215
216 /**
217 * This class implements a data sample holding channel configuration information.
218 */
220 public DataSample,
222 {
223 public:
224
225 /**
226 * Creates a new invalid data sample channel configuration.
227 */
229
230 /**
231 * Creates a new data sample channel configuration from a data sample and channel configuration.
232 * @param sample The data sample
233 * @param channelConfiguration The channel configuration
234 */
235 inline explicit DataSampleChannelConfiguration(const DataSample& sample, const ChannelConfiguration& channelConfiguration);
236
237 /**
238 * Creates a new data sample channel configuration from a data timestamp and channel configuration.
239 * @param dataTimestamp The data timestamp
240 * @param channelConfiguration The channel configuration
241 * @param sampleCreationTimestamp The timestamp when the sample was created, this timestamp is not serialized and is only used to automatically determine the playback timestamp
242 */
243 inline explicit DataSampleChannelConfiguration(const DataTimestamp& dataTimestamp, const ChannelConfiguration& channelConfiguration, const Timestamp sampleCreationTimestamp = Timestamp(true));
244
245 /**
246 * Reads the sample from an input bitstream.
247 * @param inputBitstream The input bitstream from which the sample will be read
248 * @return True, if succeeded
249 */
250 inline bool readSample(InputBitstream& inputBitstream) override;
251
252 /**
253 * Writes the sample to an output bitstream.
254 * @param outputBitstream The output bitstream to which the sample will be written
255 * @return True, if succeeded
256 */
257 inline bool writeSample(OutputBitstream& outputBitstream) const override;
258
259 /**
260 * Returns the type of the sample.
261 * @return The sample type
262 */
263 inline const std::string& type() const override;
264 };
265
266 public:
267
268 /**
269 * Destructs the data serializer.
270 */
271 virtual ~DataSerializer() = default;
272
273 /**
274 * Starts the serializer.
275 * @return True, if succeeded
276 */
277 virtual bool start() = 0;
278
279 /**
280 * Stops the serializer.
281 * This function sets a stopping flag and returns immediately; it does not wait for the serializer to actually stop.
282 * The background thread will check the stopping flag and terminate asynchronously.
283 * Use stopAndWait() to wait until the serializer has fully stopped, or poll hasStopped() to check if it has stopped.
284 * @return True, if the stop request was accepted; False, if the serializer was not started
285 * @see stopAndWait(), hasStopped().
286 */
287 virtual bool stop() = 0;
288
289 /**
290 * Stops the serializer and waits until the serializer has stopped.
291 * @param timeout The timeout in seconds, with range (0, infinity)
292 * @return True, if the serializer stopped within the given timeout
293 */
294 virtual bool stopAndWait(const double timeout = 60.0);
295
296 /**
297 * Returns whether the serializer has been started.
298 * @return True, if so
299 */
300 [[nodiscard]] virtual bool isStarted() const = 0;
301
302 /**
303 * Returns whether the serializer has stopped.
304 * @return True, if so
305 */
306 [[nodiscard]] virtual bool hasStopped() const = 0;
307
308 protected:
309
310 /**
311 * Returns whether the given channel value has the configuration bit set.
312 * @param channelValue The channel value to check
313 * @return True, if the channel value is a configuration channel id
314 */
315 [[nodiscard]] static constexpr bool isConfigurationChannelId(const uint32_t channelValue);
316
317 /**
318 * Creates a configuration channel id from a regular channel id by setting the highest bit.
319 * @param channelId The channel id
320 * @return The configuration channel id
321 */
322 [[nodiscard]] static constexpr uint32_t makeConfigurationChannelId(const ChannelId channelId);
323
324 /**
325 * Extracts the channel id from a channel value by clearing the configuration bit.
326 * @param channelValue The channel value
327 * @return The channel id
328 */
329 [[nodiscard]] static constexpr ChannelId extractChannelId(const uint32_t channelValue);
330
331 protected:
332
333 /// The timestamp when the serializer was started.
335
336 /// The current state of the serializer.
337 State state_ = S_IDLE;
338
339 /// True, if the serializer succeeded; False, if an error occurred.
340 bool succeeded_ = true;
341
342 /// The queue holding samples which are pending to be processed.
344
345 /// The lock for thread-safe access.
346 mutable Lock lock_;
347};
348
353
355{
356 size_t seed = std::hash<std::string>()(channelConfiguration.sampleType_);
357 seed ^= std::hash<std::string>{}(channelConfiguration.name_) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
358 seed ^= std::hash<std::string>{}(channelConfiguration.contentType_) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
359
360 return seed;
361}
362
363inline DataSerializer::ChannelConfiguration::ChannelConfiguration(const std::string& sampleType, const std::string& name, const std::string& contentType) :
365 name_(name),
367{
368 // nothing to do here
369}
370
372{
373 return sampleType_;
374}
375
376inline const std::string& DataSerializer::ChannelConfiguration::name() const
377{
378 return name_;
379}
380
382{
383 return contentType_;
384}
385
387{
388 return !sampleType_.empty() && !name_.empty() && !contentType_.empty();
389}
390
391inline bool DataSerializer::ChannelConfiguration::operator==(const ChannelConfiguration& channelConfiguration) const
392{
393 return sampleType_ == channelConfiguration.sampleType_ && name_ == channelConfiguration.name_ && contentType_ == channelConfiguration.contentType_;
394}
395
396inline size_t DataSerializer::Channel::Hash::operator()(const Channel& channel) const
397{
398 size_t seed = std::hash<uint32_t>()(channel.channelId_);
399 seed ^= ChannelConfiguration::Hash{}(channel) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
400
401 return seed;
402}
403
404inline DataSerializer::Channel::Channel(const ChannelConfiguration& channelConfiguration, const ChannelId channelId) :
405 ChannelConfiguration(channelConfiguration),
406 channelId_(channelId)
407{
408 // nothing to do here
409}
410
412{
413 return channelId_;
414}
415
417{
418 return channelId_ != invalidChannelId() && ChannelConfiguration::isValid();
419}
420
421inline bool DataSerializer::Channel::operator==(const Channel& channel) const
422{
423 return channelId_ == channel.channelId_ && ChannelConfiguration::operator==(channel);
424}
425
426constexpr bool DataSerializer::isConfigurationChannelId(const uint32_t channelValue)
427{
428 constexpr uint32_t highestBit = 1u << 31u;
429
430 return channelValue & highestBit;
431}
432
433constexpr uint32_t DataSerializer::makeConfigurationChannelId(const ChannelId channelId)
434{
435 ocean_assert(channelId != invalidChannelId());
436 ocean_assert(!isConfigurationChannelId(channelId));
437
438 constexpr uint32_t highestBit = 1u << 31u;
439
440 return channelId | highestBit;
441}
442
444{
445 constexpr uint32_t highestBit = 1u << 31u;
446
447 return ChannelId(channelValue & ~highestBit);
448}
449
451 DataSample(sample),
452 ChannelConfiguration(channelConfiguration)
453{
454 // nothing to do here
455}
456
457inline DataSerializer::DataSampleChannelConfiguration::DataSampleChannelConfiguration(const DataTimestamp& dataTimestamp, const ChannelConfiguration& channelConfiguration, const Timestamp sampleCreationTimestamp) :
458 DataSample(dataTimestamp, sampleCreationTimestamp),
459 ChannelConfiguration(channelConfiguration)
460{
461 // nothing to do here
462}
463
465{
466 if (!DataSample::readSample(inputBitstream))
467 {
468 return false;
469 }
470
471 return inputBitstream.read<std::string>(sampleType_) && inputBitstream.read<std::string>(name_) && inputBitstream.read<std::string>(contentType_);
472}
473
475{
476 if (!DataSample::writeSample(outputBitstream))
477 {
478 return false;
479 }
480
481 return outputBitstream.write<std::string>(sampleType_) && outputBitstream.write<std::string>(name_) && outputBitstream.write<std::string>(contentType_);
482}
483
485{
486 return sampleType_;
487}
488
489}
490
491}
492
493}
494
495#endif // META_OCEAN_IO_SERIALIZATION_DATA_SERIALIZER_H
This class implements an input bitstream.
Definition Bitstream.h:51
bool read(T &value)
Reads a value from the bitstream and moves the internal position inside the bitstream accordingly.
This class implements an output bitstream.
Definition Bitstream.h:215
bool write(const T &value)
Writes a data object to the stream and moves the internal position inside the bitstream accordingly.
This class implements a base class for data samples.
Definition DataSample.h:46
virtual bool readSample(InputBitstream &inputBitstream)
Reads the sample from an input bitstream.
virtual bool writeSample(OutputBitstream &outputBitstream) const
Writes the sample to an output bitstream.
This class holds channel configuration (sample type, name, and content type).
Definition DataSerializer.h:52
bool operator==(const ChannelConfiguration &channelConfiguration) const
Returns whether two channel configurations are equal.
Definition DataSerializer.h:391
std::string name_
The name of the channel.
Definition DataSerializer.h:120
std::string contentType_
The content type.
Definition DataSerializer.h:123
ChannelConfiguration()=default
Creates a new invalid channel configuration.
bool isValid() const
Returns whether this channel configuration is valid.
Definition DataSerializer.h:386
const std::string & sampleType() const
Returns the sample type.
Definition DataSerializer.h:371
const std::string & contentType() const
Returns the content type.
Definition DataSerializer.h:381
const std::string & name() const
Returns the name of the channel.
Definition DataSerializer.h:376
std::string sampleType_
The sample type.
Definition DataSerializer.h:117
This class implements a channel with configuration and channel id.
Definition DataSerializer.h:130
Channel()=default
Creates a new invalid channel.
bool operator==(const Channel &channel) const
Returns whether two channels are equal.
Definition DataSerializer.h:421
ChannelId channelId() const
Returns the channel id.
Definition DataSerializer.h:411
bool isValid() const
Returns whether this channel is valid.
Definition DataSerializer.h:416
ChannelId channelId_
The channel id.
Definition DataSerializer.h:182
This class implements a data sample holding channel configuration information.
Definition DataSerializer.h:222
bool readSample(InputBitstream &inputBitstream) override
Reads the sample from an input bitstream.
Definition DataSerializer.h:464
DataSampleChannelConfiguration()=default
Creates a new invalid data sample channel configuration.
bool writeSample(OutputBitstream &outputBitstream) const override
Writes the sample to an output bitstream.
Definition DataSerializer.h:474
const std::string & type() const override
Returns the type of the sample.
Definition DataSerializer.h:484
This class implements the base class for data serializers.
Definition DataSerializer.h:36
std::queue< SamplePair > SampleQueue
Definition of a queue holding sample pairs.
Definition DataSerializer.h:214
static constexpr uint32_t makeConfigurationChannelId(const ChannelId channelId)
Creates a configuration channel id from a regular channel id by setting the highest bit.
Definition DataSerializer.h:433
SampleQueue sampleQueue_
The queue holding samples which are pending to be processed.
Definition DataSerializer.h:343
static constexpr ChannelId invalidChannelId()
Returns an invalid channel id.
Definition DataSerializer.h:349
std::unordered_map< ChannelConfiguration, ChannelId, ChannelConfiguration::Hash > ChannelConfigurationMap
Definition of a map mapping channel configurations to channel ids.
Definition DataSerializer.h:208
virtual bool hasStopped() const =0
Returns whether the serializer has stopped.
Timestamp startTimestamp_
The timestamp when the serializer was started.
Definition DataSerializer.h:334
std::pair< ChannelId, UniqueDataSample > SamplePair
Definition of a pair holding a channel id and a unique data sample.
Definition DataSerializer.h:211
std::vector< Channel > Channels
Definition of a vector holding channels.
Definition DataSerializer.h:186
Lock lock_
The lock for thread-safe access.
Definition DataSerializer.h:346
static constexpr bool isConfigurationChannelId(const uint32_t channelValue)
Returns whether the given channel value has the configuration bit set.
Definition DataSerializer.h:426
virtual bool start()=0
Starts the serializer.
virtual bool stop()=0
Stops the serializer.
virtual bool isStarted() const =0
Returns whether the serializer has been started.
uint32_t ChannelId
Definition of a channel id.
Definition DataSerializer.h:40
virtual bool stopAndWait(const double timeout=60.0)
Stops the serializer and waits until the serializer has stopped.
State
Definition of individual states the serializer can have.
Definition DataSerializer.h:194
@ S_IDLE
The serializer has not yet been initialized or started.
Definition DataSerializer.h:196
@ S_INITIALIZED
The serializer has been initialized and is ready to start.
Definition DataSerializer.h:198
@ S_STARTED
The serializer has been started and is currently actively processing data samples.
Definition DataSerializer.h:200
@ S_STOPPING
The serializer is currently stopping but may still process remaining data samples.
Definition DataSerializer.h:202
virtual ~DataSerializer()=default
Destructs the data serializer.
static constexpr ChannelId extractChannelId(const uint32_t channelValue)
Extracts the channel id from a channel value by clearing the configuration bit.
Definition DataSerializer.h:443
This class implements a data timestamp which can hold either a double or int64_t value.
Definition DataTimestamp.h:29
This class implements a recursive lock object.
Definition Lock.h:31
This class implements a thread.
Definition Thread.h:115
This class implements a timestamp.
Definition Timestamp.h:63
The namespace covering the entire Ocean framework.
Definition Accessor.h:15
Definition of a hash function for Channel objects.
Definition DataSerializer.h:137
size_t operator()(const Channel &channel) const
Calculates the hash value for a given channel.
Definition DataSerializer.h:396
Definition of a hash function for ChannelConfiguration objects.
Definition DataSerializer.h:59
size_t operator()(const ChannelConfiguration &channelConfiguration) const
Calculates the hash value for a given channel configuration.
Definition DataSerializer.h:354