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 /**
214 * This class implements a data sample holding channel configuration information.
215 */
217 public DataSample,
219 {
220 public:
221
222 /**
223 * Creates a new invalid data sample channel configuration.
224 */
226
227 /**
228 * Creates a new data sample channel configuration from a data sample and channel configuration.
229 * @param sample The data sample
230 * @param channelConfiguration The channel configuration
231 */
232 inline explicit DataSampleChannelConfiguration(const DataSample& sample, const ChannelConfiguration& channelConfiguration);
233
234 /**
235 * Creates a new data sample channel configuration from a data timestamp and channel configuration.
236 * @param dataTimestamp The data timestamp
237 * @param channelConfiguration The channel configuration
238 * @param sampleCreationTimestamp The timestamp when the sample was created, this timestamp is not serialized and is only used to automatically determine the playback timestamp
239 */
240 inline explicit DataSampleChannelConfiguration(const DataTimestamp& dataTimestamp, const ChannelConfiguration& channelConfiguration, const Timestamp sampleCreationTimestamp = Timestamp(true));
241
242 /**
243 * Reads the sample from an input bitstream.
244 * @param inputBitstream The input bitstream from which the sample will be read
245 * @return True, if succeeded
246 */
247 inline bool readSample(InputBitstream& inputBitstream) override;
248
249 /**
250 * Writes the sample to an output bitstream.
251 * @param outputBitstream The output bitstream to which the sample will be written
252 * @return True, if succeeded
253 */
254 inline bool writeSample(OutputBitstream& outputBitstream) const override;
255
256 /**
257 * Returns the type of the sample.
258 * @return The sample type
259 */
260 inline const std::string& type() const override;
261 };
262
263 public:
264
265 /**
266 * Destructs the data serializer.
267 */
268 virtual ~DataSerializer() = default;
269
270 /**
271 * Starts the serializer.
272 * @return True, if succeeded
273 */
274 virtual bool start() = 0;
275
276 /**
277 * Stops the serializer.
278 * This function sets a stopping flag and returns immediately; it does not wait for the serializer to actually stop.
279 * The background thread will check the stopping flag and terminate asynchronously.
280 * Use stopAndWait() to wait until the serializer has fully stopped, or poll hasStopped() to check if it has stopped.
281 * @return True, if the stop request was accepted; False, if the serializer was not started
282 * @see stopAndWait(), hasStopped().
283 */
284 virtual bool stop() = 0;
285
286 /**
287 * Stops the serializer and waits until the serializer has stopped.
288 * @param timeout The timeout in seconds, with range (0, infinity)
289 * @return True, if the serializer stopped within the given timeout
290 */
291 virtual bool stopAndWait(const double timeout = 60.0);
292
293 /**
294 * Returns whether the serializer has been started.
295 * @return True, if so
296 */
297 [[nodiscard]] virtual bool isStarted() const = 0;
298
299 /**
300 * Returns whether the serializer has stopped but does not check wehther remaining samples have not yet been processed or retrieved.
301 * @return True, if so
302 */
303 [[nodiscard]] virtual bool hasStopped() const;
304
305 /**
306 * Returns whether the serializer has stopped and all remaining samples have been processed or retrieved.
307 * @return True, if so
308 * @see DataSerializer::hasFinished().
309 */
310 [[nodiscard]] virtual bool hasFinished() const = 0;
311
312 protected:
313
314 /**
315 * Returns whether the given channel value has the configuration bit set.
316 * @param channelValue The channel value to check
317 * @return True, if the channel value is a configuration channel id
318 */
319 [[nodiscard]] static constexpr bool isConfigurationChannelId(const uint32_t channelValue);
320
321 /**
322 * Creates a configuration channel id from a regular channel id by setting the highest bit.
323 * @param channelId The channel id
324 * @return The configuration channel id
325 */
326 [[nodiscard]] static constexpr uint32_t makeConfigurationChannelId(const ChannelId channelId);
327
328 /**
329 * Extracts the channel id from a channel value by clearing the configuration bit.
330 * @param channelValue The channel value
331 * @return The channel id
332 */
333 [[nodiscard]] static constexpr ChannelId extractChannelId(const uint32_t channelValue);
334
335 protected:
336
337 /// The timestamp when the serializer was started.
339
340 /// The current state of the serializer.
341 State state_ = S_IDLE;
342
343 /// True, if the serializer succeeded; False, if an error occurred.
344 bool succeeded_ = true;
345
346 /// The lock for thread-safe access.
347 mutable Lock lock_;
348};
349
354
356{
357 size_t seed = std::hash<std::string>()(channelConfiguration.sampleType_);
358 seed ^= std::hash<std::string>{}(channelConfiguration.name_) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
359 seed ^= std::hash<std::string>{}(channelConfiguration.contentType_) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
360
361 return seed;
362}
363
364inline DataSerializer::ChannelConfiguration::ChannelConfiguration(const std::string& sampleType, const std::string& name, const std::string& contentType) :
366 name_(name),
368{
369 // nothing to do here
370}
371
373{
374 return sampleType_;
375}
376
377inline const std::string& DataSerializer::ChannelConfiguration::name() const
378{
379 return name_;
380}
381
383{
384 return contentType_;
385}
386
388{
389 return !sampleType_.empty() && !name_.empty() && !contentType_.empty();
390}
391
392inline bool DataSerializer::ChannelConfiguration::operator==(const ChannelConfiguration& channelConfiguration) const
393{
394 return sampleType_ == channelConfiguration.sampleType_ && name_ == channelConfiguration.name_ && contentType_ == channelConfiguration.contentType_;
395}
396
397inline size_t DataSerializer::Channel::Hash::operator()(const Channel& channel) const
398{
399 size_t seed = std::hash<uint32_t>()(channel.channelId_);
400 seed ^= ChannelConfiguration::Hash{}(channel) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
401
402 return seed;
403}
404
405inline DataSerializer::Channel::Channel(const ChannelConfiguration& channelConfiguration, const ChannelId channelId) :
406 ChannelConfiguration(channelConfiguration),
407 channelId_(channelId)
408{
409 // nothing to do here
410}
411
413{
414 return channelId_;
415}
416
418{
419 return channelId_ != invalidChannelId() && ChannelConfiguration::isValid();
420}
421
422inline bool DataSerializer::Channel::operator==(const Channel& channel) const
423{
424 return channelId_ == channel.channelId_ && ChannelConfiguration::operator==(channel);
425}
426
427constexpr bool DataSerializer::isConfigurationChannelId(const uint32_t channelValue)
428{
429 constexpr uint32_t highestBit = 1u << 31u;
430
431 return channelValue & highestBit;
432}
433
434constexpr uint32_t DataSerializer::makeConfigurationChannelId(const ChannelId channelId)
435{
436 ocean_assert(channelId != invalidChannelId());
437 ocean_assert(!isConfigurationChannelId(channelId));
438
439 constexpr uint32_t highestBit = 1u << 31u;
440
441 return channelId | highestBit;
442}
443
445{
446 constexpr uint32_t highestBit = 1u << 31u;
447
448 return ChannelId(channelValue & ~highestBit);
449}
450
452 DataSample(sample),
453 ChannelConfiguration(channelConfiguration)
454{
455 // nothing to do here
456}
457
458inline DataSerializer::DataSampleChannelConfiguration::DataSampleChannelConfiguration(const DataTimestamp& dataTimestamp, const ChannelConfiguration& channelConfiguration, const Timestamp sampleCreationTimestamp) :
459 DataSample(dataTimestamp, sampleCreationTimestamp),
460 ChannelConfiguration(channelConfiguration)
461{
462 // nothing to do here
463}
464
466{
467 if (!DataSample::readSample(inputBitstream))
468 {
469 return false;
470 }
471
472 return inputBitstream.read<std::string>(sampleType_) && inputBitstream.read<std::string>(name_) && inputBitstream.read<std::string>(contentType_);
473}
474
476{
477 if (!DataSample::writeSample(outputBitstream))
478 {
479 return false;
480 }
481
482 return outputBitstream.write<std::string>(sampleType_) && outputBitstream.write<std::string>(name_) && outputBitstream.write<std::string>(contentType_);
483}
484
486{
487 return sampleType_;
488}
489
490}
491
492}
493
494}
495
496#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:392
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:387
const std::string & sampleType() const
Returns the sample type.
Definition DataSerializer.h:372
const std::string & contentType() const
Returns the content type.
Definition DataSerializer.h:382
const std::string & name() const
Returns the name of the channel.
Definition DataSerializer.h:377
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:422
ChannelId channelId() const
Returns the channel id.
Definition DataSerializer.h:412
bool isValid() const
Returns whether this channel is valid.
Definition DataSerializer.h:417
ChannelId channelId_
The channel id.
Definition DataSerializer.h:182
This class implements a data sample holding channel configuration information.
Definition DataSerializer.h:219
bool readSample(InputBitstream &inputBitstream) override
Reads the sample from an input bitstream.
Definition DataSerializer.h:465
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:475
const std::string & type() const override
Returns the type of the sample.
Definition DataSerializer.h:485
This class implements the base class for data serializers.
Definition DataSerializer.h:36
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:434
static constexpr ChannelId invalidChannelId()
Returns an invalid channel id.
Definition DataSerializer.h:350
std::unordered_map< ChannelConfiguration, ChannelId, ChannelConfiguration::Hash > ChannelConfigurationMap
Definition of a map mapping channel configurations to channel ids.
Definition DataSerializer.h:208
Timestamp startTimestamp_
The timestamp when the serializer was started.
Definition DataSerializer.h:338
virtual bool hasStopped() const
Returns whether the serializer has stopped but does not check wehther remaining samples have not yet ...
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:347
static constexpr bool isConfigurationChannelId(const uint32_t channelValue)
Returns whether the given channel value has the configuration bit set.
Definition DataSerializer.h:427
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.
virtual bool hasFinished() const =0
Returns whether the serializer has stopped and all remaining samples have been processed or retrieved...
static constexpr ChannelId extractChannelId(const uint32_t channelValue)
Extracts the channel id from a channel value by clearing the configuration bit.
Definition DataSerializer.h:444
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:64
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:397
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:355