/src/Fast-DDS/include/fastdds/rtps/common/SequenceNumber.hpp
Line | Count | Source |
1 | | // Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | /** |
16 | | * @file SequenceNumber.hpp |
17 | | */ |
18 | | |
19 | | #ifndef FASTDDS_RTPS_COMMON__SEQUENCENUMBER_HPP |
20 | | #define FASTDDS_RTPS_COMMON__SEQUENCENUMBER_HPP |
21 | | |
22 | | #include <algorithm> |
23 | | #include <cassert> |
24 | | #include <limits> |
25 | | #include <vector> |
26 | | |
27 | | #include <fastdds/fastdds_dll.hpp> |
28 | | #include <fastdds/rtps/common/Types.hpp> |
29 | | #include <fastdds/utils/fixed_size_bitmap.hpp> |
30 | | |
31 | | namespace eprosima { |
32 | | namespace fastdds { |
33 | | namespace rtps { |
34 | | |
35 | | //!@brief Structure SequenceNumber_t, different for each change in the same writer. |
36 | | //!@ingroup COMMON_MODULE |
37 | | struct FASTDDS_EXPORTED_API SequenceNumber_t |
38 | | { |
39 | | //! |
40 | | int32_t high = 0; |
41 | | //! |
42 | | uint32_t low = 0; |
43 | | |
44 | | //! Default constructor |
45 | | SequenceNumber_t() noexcept |
46 | 19.4k | { |
47 | 19.4k | high = 0; |
48 | 19.4k | low = 0; |
49 | 19.4k | } |
50 | | |
51 | | /*! |
52 | | * @param hi |
53 | | * @param lo |
54 | | */ |
55 | | SequenceNumber_t( |
56 | | int32_t hi, |
57 | | uint32_t lo) noexcept |
58 | 14.4k | : high(hi) |
59 | 14.4k | , low(lo) |
60 | 14.4k | { |
61 | 14.4k | } |
62 | | |
63 | | /*! |
64 | | * @param u |
65 | | */ |
66 | | explicit SequenceNumber_t( |
67 | | uint64_t u) noexcept |
68 | 0 | : high(static_cast<int32_t>(u >> 32u)) |
69 | 0 | , low(static_cast<uint32_t>(u)) |
70 | 0 | { |
71 | 0 | } |
72 | | |
73 | | /*! Convert the number to 64 bit. |
74 | | * @return 64 bit representation of the SequenceNumber |
75 | | */ |
76 | | uint64_t to64long() const noexcept |
77 | 0 | { |
78 | 0 | return (static_cast<uint64_t>(high) << 32u) + low; |
79 | 0 | } |
80 | | |
81 | | //! Increase SequenceNumber in 1. |
82 | | SequenceNumber_t& operator ++() noexcept |
83 | 0 | { |
84 | 0 | ++low; |
85 | 0 | if (low == 0) |
86 | 0 | { |
87 | 0 | increase_high_or_cap(*this); |
88 | 0 | } |
89 | |
|
90 | 0 | return *this; |
91 | 0 | } |
92 | | |
93 | | SequenceNumber_t operator ++( |
94 | | int) noexcept |
95 | 0 | { |
96 | 0 | SequenceNumber_t result(*this); |
97 | 0 | ++(*this); |
98 | 0 | return result; |
99 | 0 | } |
100 | | |
101 | | /** |
102 | | * Increase SequenceNumber. |
103 | | * @param inc Number to add to the SequenceNumber |
104 | | */ |
105 | | SequenceNumber_t& operator +=( |
106 | | int inc) noexcept |
107 | 0 | { |
108 | 0 | assert(inc >= 0); |
109 | 0 | uint32_t aux_low = low; |
110 | 0 | low += static_cast<uint32_t>(inc); |
111 | 0 |
|
112 | 0 | if (low < aux_low) |
113 | 0 | { |
114 | 0 | // Being the type of the parameter an 'int', the increment of 'high' will be as much as 1. |
115 | 0 | increase_high_or_cap(*this); |
116 | 0 | } |
117 | 0 |
|
118 | 0 | return *this; |
119 | 0 | } |
120 | | |
121 | | static SequenceNumber_t unknown() noexcept |
122 | 2.14k | { |
123 | 2.14k | return {-1, 0}; |
124 | 2.14k | } |
125 | | |
126 | | static inline void increase_high_or_cap( |
127 | | SequenceNumber_t& seq) noexcept |
128 | 249 | { |
129 | 249 | if (seq.high < std::numeric_limits<int32_t>::max()) |
130 | 249 | { |
131 | 249 | ++seq.high; |
132 | 249 | } |
133 | 0 | else |
134 | 0 | { |
135 | 0 | seq.low = std::numeric_limits<uint32_t>::max(); |
136 | 0 | } |
137 | 249 | } |
138 | | |
139 | | static void decrease_high_or_cap( |
140 | | SequenceNumber_t& seq) noexcept |
141 | 219 | { |
142 | 219 | if (seq.high > 0) |
143 | 219 | { |
144 | 219 | --seq.high; |
145 | 219 | } |
146 | 0 | else |
147 | 0 | { |
148 | 0 | seq.low = 0; |
149 | 0 | } |
150 | 219 | } |
151 | | |
152 | | }; |
153 | | |
154 | | #ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC |
155 | | |
156 | | /** |
157 | | * Compares two SequenceNumber_t. |
158 | | * @param sn1 First SequenceNumber_t to compare |
159 | | * @param sn2 Second SequenceNumber_t to compare |
160 | | * @return True if equal |
161 | | */ |
162 | | inline bool operator ==( |
163 | | const SequenceNumber_t& sn1, |
164 | | const SequenceNumber_t& sn2) noexcept |
165 | 0 | { |
166 | 0 | return (sn1.low == sn2.low) && (sn1.high == sn2.high); |
167 | 0 | } |
168 | | |
169 | | /** |
170 | | * Compares two SequenceNumber_t. |
171 | | * @param sn1 First SequenceNumber_t to compare |
172 | | * @param sn2 Second SequenceNumber_t to compare |
173 | | * @return True if not equal |
174 | | */ |
175 | | inline bool operator !=( |
176 | | const SequenceNumber_t& sn1, |
177 | | const SequenceNumber_t& sn2) noexcept |
178 | 987 | { |
179 | 987 | return (sn1.low != sn2.low) || (sn1.high != sn2.high); |
180 | 987 | } |
181 | | |
182 | | /** |
183 | | * Checks if a SequenceNumber_t is greater than other. |
184 | | * @param seq1 First SequenceNumber_t to compare |
185 | | * @param seq2 Second SequenceNumber_t to compare |
186 | | * @return True if the first SequenceNumber_t is greater than the second |
187 | | */ |
188 | | inline bool operator >( |
189 | | const SequenceNumber_t& seq1, |
190 | | const SequenceNumber_t& seq2) noexcept |
191 | 0 | { |
192 | 0 | if (seq1.high == seq2.high) |
193 | 0 | { |
194 | 0 | return seq1.low > seq2.low; |
195 | 0 | } |
196 | | |
197 | 0 | return seq1.high > seq2.high; |
198 | 0 | } |
199 | | |
200 | | /** |
201 | | * Checks if a SequenceNumber_t is less than other. |
202 | | * @param seq1 First SequenceNumber_t to compare |
203 | | * @param seq2 Second SequenceNumber_t to compare |
204 | | * @return True if the first SequenceNumber_t is less than the second |
205 | | */ |
206 | | inline bool operator <( |
207 | | const SequenceNumber_t& seq1, |
208 | | const SequenceNumber_t& seq2) noexcept |
209 | 2.93k | { |
210 | 2.93k | if (seq1.high == seq2.high) |
211 | 2.23k | { |
212 | 2.23k | return seq1.low < seq2.low; |
213 | 2.23k | } |
214 | | |
215 | 700 | return seq1.high < seq2.high; |
216 | 2.93k | } |
217 | | |
218 | | /** |
219 | | * Checks if a SequenceNumber_t is greater or equal than other. |
220 | | * @param seq1 First SequenceNumber_t to compare |
221 | | * @param seq2 Second SequenceNumber_t to compare |
222 | | * @return True if the first SequenceNumber_t is greater or equal than the second |
223 | | */ |
224 | | inline bool operator >=( |
225 | | const SequenceNumber_t& seq1, |
226 | | const SequenceNumber_t& seq2) noexcept |
227 | 0 | { |
228 | 0 | if (seq1.high == seq2.high) |
229 | 0 | { |
230 | 0 | return seq1.low >= seq2.low; |
231 | 0 | } |
232 | | |
233 | 0 | return seq1.high > seq2.high; |
234 | 0 | } |
235 | | |
236 | | /** |
237 | | * Checks if a SequenceNumber_t is less or equal than other. |
238 | | * @param seq1 First SequenceNumber_t to compare |
239 | | * @param seq2 Second SequenceNumber_t to compare |
240 | | * @return True if the first SequenceNumber_t is less or equal than the second |
241 | | */ |
242 | | inline bool operator <=( |
243 | | const SequenceNumber_t& seq1, |
244 | | const SequenceNumber_t& seq2) noexcept |
245 | 7.97k | { |
246 | 7.97k | if (seq1.high == seq2.high) |
247 | 2.20k | { |
248 | 2.20k | return seq1.low <= seq2.low; |
249 | 2.20k | } |
250 | | |
251 | 5.77k | return seq1.high < seq2.high; |
252 | 7.97k | } |
253 | | |
254 | | /** |
255 | | * Subtract one uint32_t from a SequenceNumber_t |
256 | | * @param seq Base SequenceNumber_t |
257 | | * @param inc uint32_t to subtract |
258 | | * @return Result of the subtraction |
259 | | */ |
260 | | inline SequenceNumber_t operator -( |
261 | | const SequenceNumber_t& seq, |
262 | | const uint32_t inc) noexcept |
263 | 987 | { |
264 | 987 | SequenceNumber_t res(seq.high, seq.low - inc); |
265 | | |
266 | 987 | if (inc > seq.low) |
267 | 219 | { |
268 | | // Being the type of the parameter an 'uint32_t', the decrement of 'high' will be as much as 1. |
269 | 219 | SequenceNumber_t::decrease_high_or_cap(res); |
270 | 219 | } |
271 | | |
272 | 987 | return res; |
273 | 987 | } |
274 | | |
275 | | /** |
276 | | * Add one uint32_t to a SequenceNumber_t |
277 | | * @param [in] seq Base sequence number |
278 | | * @param inc value to add to the base |
279 | | * @return Result of the addition |
280 | | */ |
281 | | inline SequenceNumber_t operator +( |
282 | | const SequenceNumber_t& seq, |
283 | | const uint32_t inc) noexcept |
284 | 5.36k | { |
285 | 5.36k | SequenceNumber_t res(seq.high, seq.low + inc); |
286 | | |
287 | 5.36k | if (res.low < seq.low) |
288 | 249 | { |
289 | | // Being the type of the parameter an 'uint32_t', the increment of 'high' will be as much as 1. |
290 | 249 | SequenceNumber_t::increase_high_or_cap(res); |
291 | 249 | } |
292 | | |
293 | 5.36k | return res; |
294 | 5.36k | } |
295 | | |
296 | | /** |
297 | | * Subtract one SequenceNumber_t to another |
298 | | * @param minuend Minuend. Has to be greater than or equal to subtrahend. |
299 | | * @param subtrahend Subtrahend. |
300 | | * @return Result of the subtraction |
301 | | */ |
302 | | inline SequenceNumber_t operator -( |
303 | | const SequenceNumber_t& minuend, |
304 | | const SequenceNumber_t& subtrahend) noexcept |
305 | 0 | { |
306 | 0 | assert(minuend >= subtrahend); |
307 | 0 | SequenceNumber_t res(minuend.high - subtrahend.high, minuend.low - subtrahend.low); |
308 | |
|
309 | 0 | if (minuend.low < subtrahend.low) |
310 | 0 | { |
311 | 0 | SequenceNumber_t::decrease_high_or_cap(res); |
312 | 0 | } |
313 | |
|
314 | 0 | return res; |
315 | 0 | } |
316 | | |
317 | | #endif // ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC |
318 | | |
319 | | const SequenceNumber_t c_SequenceNumber_Unknown{-1, 0}; |
320 | | |
321 | | #ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC |
322 | | |
323 | | /** |
324 | | * Sorts two instances of SequenceNumber_t |
325 | | * @param s1 First SequenceNumber_t to compare |
326 | | * @param s2 First SequenceNumber_t to compare |
327 | | * @return True if s1 is less than s2 |
328 | | */ |
329 | | inline bool sort_seqNum( |
330 | | const SequenceNumber_t& s1, |
331 | | const SequenceNumber_t& s2) noexcept |
332 | 0 | { |
333 | 0 | return s1 < s2; |
334 | 0 | } |
335 | | |
336 | | /** |
337 | | * |
338 | | * @param output |
339 | | * @param seqNum |
340 | | * @return |
341 | | */ |
342 | | inline std::ostream& operator <<( |
343 | | std::ostream& output, |
344 | | const SequenceNumber_t& seqNum) |
345 | 0 | { |
346 | 0 | return output << seqNum.to64long(); |
347 | 0 | } |
348 | | |
349 | | inline std::ostream& operator <<( |
350 | | std::ostream& output, |
351 | | const std::vector<SequenceNumber_t>& seqNumSet) |
352 | 0 | { |
353 | 0 | for (const SequenceNumber_t& sn : seqNumSet) |
354 | 0 | { |
355 | 0 | output << sn << " "; |
356 | 0 | } |
357 | 0 |
|
358 | 0 | return output; |
359 | 0 | } |
360 | | |
361 | | /*! |
362 | | * @brief Defines the STL hash function for type SequenceNumber_t. |
363 | | */ |
364 | | struct SequenceNumberHash |
365 | | { |
366 | | std::size_t operator ()( |
367 | | const SequenceNumber_t& sequence_number) const noexcept |
368 | 0 | { |
369 | 0 | return static_cast<std::size_t>(sequence_number.to64long()); |
370 | 0 | } |
371 | | |
372 | | }; |
373 | | |
374 | | struct SequenceNumberDiff |
375 | | { |
376 | | uint32_t operator ()( |
377 | | const SequenceNumber_t& a, |
378 | | const SequenceNumber_t& b) const noexcept |
379 | 0 | { |
380 | 0 | SequenceNumber_t diff = a - b; |
381 | 0 | return diff.low; |
382 | 0 | } |
383 | | |
384 | | }; |
385 | | |
386 | | #endif // ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC |
387 | | |
388 | | //! Structure SequenceNumberSet_t, contains a group of sequencenumbers. |
389 | | using SequenceNumberSet_t = BitmapRange<SequenceNumber_t, SequenceNumberDiff, 256>; |
390 | | |
391 | | #ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC |
392 | | |
393 | | /** |
394 | | * Prints a sequence Number set |
395 | | * @param output Output Stream |
396 | | * @param sns SequenceNumber set |
397 | | * @return OStream. |
398 | | */ |
399 | | inline std::ostream& operator <<( |
400 | | std::ostream& output, |
401 | | const SequenceNumberSet_t& sns) |
402 | 0 | { |
403 | 0 | output << sns.base().to64long() << ":"; |
404 | 0 | sns.for_each([&output]( |
405 | 0 | SequenceNumber_t it) |
406 | 0 | { |
407 | 0 | output << it.to64long() << "-"; |
408 | 0 | }); |
409 | 0 |
|
410 | 0 | return output; |
411 | 0 | } |
412 | | |
413 | | /** |
414 | | * |
415 | | * @param input |
416 | | * @param seqNum |
417 | | * @return |
418 | | */ |
419 | | inline std::istream& operator >>( |
420 | | std::istream& input, |
421 | | SequenceNumber_t& seqNum) |
422 | 0 | { |
423 | 0 | uint64_t aux; |
424 | |
|
425 | 0 | if (input >> aux) |
426 | 0 | { |
427 | 0 | seqNum = SequenceNumber_t(aux); |
428 | 0 | } |
429 | |
|
430 | 0 | return input; |
431 | 0 | } |
432 | | |
433 | | #endif // DOXYGEN_SHOULD_SKIP_THIS_PUBLIC |
434 | | |
435 | | } // namespace rtps |
436 | | } // namespace fastdds |
437 | | } // namespace eprosima |
438 | | |
439 | | #endif // FASTDDS_RTPS_COMMON__SEQUENCENUMBER_HPP |