/src/Fast-DDS/include/fastdds/rtps/common/SequenceNumber.hpp
Line | Count | Source (jump to first uncovered line) |
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 | 27.7k | { |
47 | 27.7k | high = 0; |
48 | 27.7k | low = 0; |
49 | 27.7k | } |
50 | | |
51 | | /*! |
52 | | * @param hi |
53 | | * @param lo |
54 | | */ |
55 | | SequenceNumber_t( |
56 | | int32_t hi, |
57 | | uint32_t lo) noexcept |
58 | 18.4k | : high(hi) |
59 | 18.4k | , low(lo) |
60 | 18.4k | { |
61 | 18.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 | assert(std::numeric_limits<decltype(high)>::max() > high); |
88 | 0 | ++high; |
89 | 0 | } |
90 | |
|
91 | 0 | return *this; |
92 | 0 | } |
93 | | |
94 | | SequenceNumber_t operator ++( |
95 | | int) noexcept |
96 | 0 | { |
97 | 0 | SequenceNumber_t result(*this); |
98 | 0 | ++(*this); |
99 | 0 | return result; |
100 | 0 | } |
101 | | |
102 | | /** |
103 | | * Increase SequenceNumber. |
104 | | * @param inc Number to add to the SequenceNumber |
105 | | */ |
106 | | SequenceNumber_t& operator +=( |
107 | | int inc) noexcept |
108 | 0 | { |
109 | 0 | assert(inc >= 0); |
110 | 0 | uint32_t aux_low = low; |
111 | 0 | low += static_cast<uint32_t>(inc); |
112 | 0 |
|
113 | 0 | if (low < aux_low) |
114 | 0 | { |
115 | 0 | // Being the type of the parameter an 'int', the increment of 'high' will be as much as 1. |
116 | 0 | assert(std::numeric_limits<decltype(high)>::max() > high); |
117 | 0 | ++high; |
118 | 0 | } |
119 | 0 |
|
120 | 0 | return *this; |
121 | 0 | } |
122 | | |
123 | | static SequenceNumber_t unknown() noexcept |
124 | 8 | { |
125 | 8 | return {-1, 0}; |
126 | 8 | } |
127 | | |
128 | | }; |
129 | | |
130 | | #ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC |
131 | | |
132 | | /** |
133 | | * Compares two SequenceNumber_t. |
134 | | * @param sn1 First SequenceNumber_t to compare |
135 | | * @param sn2 Second SequenceNumber_t to compare |
136 | | * @return True if equal |
137 | | */ |
138 | | inline bool operator ==( |
139 | | const SequenceNumber_t& sn1, |
140 | | const SequenceNumber_t& sn2) noexcept |
141 | 0 | { |
142 | 0 | return (sn1.low == sn2.low) && (sn1.high == sn2.high); |
143 | 0 | } |
144 | | |
145 | | /** |
146 | | * Compares two SequenceNumber_t. |
147 | | * @param sn1 First SequenceNumber_t to compare |
148 | | * @param sn2 Second SequenceNumber_t to compare |
149 | | * @return True if not equal |
150 | | */ |
151 | | inline bool operator !=( |
152 | | const SequenceNumber_t& sn1, |
153 | | const SequenceNumber_t& sn2) noexcept |
154 | 1.23k | { |
155 | 1.23k | return (sn1.low != sn2.low) || (sn1.high != sn2.high); |
156 | 1.23k | } |
157 | | |
158 | | /** |
159 | | * Checks if a SequenceNumber_t is greater than other. |
160 | | * @param seq1 First SequenceNumber_t to compare |
161 | | * @param seq2 Second SequenceNumber_t to compare |
162 | | * @return True if the first SequenceNumber_t is greater than the second |
163 | | */ |
164 | | inline bool operator >( |
165 | | const SequenceNumber_t& seq1, |
166 | | const SequenceNumber_t& seq2) noexcept |
167 | 0 | { |
168 | 0 | if (seq1.high == seq2.high) |
169 | 0 | { |
170 | 0 | return seq1.low > seq2.low; |
171 | 0 | } |
172 | | |
173 | 0 | return seq1.high > seq2.high; |
174 | 0 | } |
175 | | |
176 | | /** |
177 | | * Checks if a SequenceNumber_t is less than other. |
178 | | * @param seq1 First SequenceNumber_t to compare |
179 | | * @param seq2 Second SequenceNumber_t to compare |
180 | | * @return True if the first SequenceNumber_t is less than the second |
181 | | */ |
182 | | inline bool operator <( |
183 | | const SequenceNumber_t& seq1, |
184 | | const SequenceNumber_t& seq2) noexcept |
185 | 3.59k | { |
186 | 3.59k | if (seq1.high == seq2.high) |
187 | 2.29k | { |
188 | 2.29k | return seq1.low < seq2.low; |
189 | 2.29k | } |
190 | | |
191 | 1.30k | return seq1.high < seq2.high; |
192 | 3.59k | } |
193 | | |
194 | | /** |
195 | | * Checks if a SequenceNumber_t is greater or equal than other. |
196 | | * @param seq1 First SequenceNumber_t to compare |
197 | | * @param seq2 Second SequenceNumber_t to compare |
198 | | * @return True if the first SequenceNumber_t is greater or equal than the second |
199 | | */ |
200 | | inline bool operator >=( |
201 | | const SequenceNumber_t& seq1, |
202 | | const SequenceNumber_t& seq2) noexcept |
203 | 0 | { |
204 | 0 | if (seq1.high == seq2.high) |
205 | 0 | { |
206 | 0 | return seq1.low >= seq2.low; |
207 | 0 | } |
208 | | |
209 | 0 | return seq1.high > seq2.high; |
210 | 0 | } |
211 | | |
212 | | /** |
213 | | * Checks if a SequenceNumber_t is less or equal than other. |
214 | | * @param seq1 First SequenceNumber_t to compare |
215 | | * @param seq2 Second SequenceNumber_t to compare |
216 | | * @return True if the first SequenceNumber_t is less or equal than the second |
217 | | */ |
218 | | inline bool operator <=( |
219 | | const SequenceNumber_t& seq1, |
220 | | const SequenceNumber_t& seq2) noexcept |
221 | 11.8k | { |
222 | 11.8k | if (seq1.high == seq2.high) |
223 | 2.80k | { |
224 | 2.80k | return seq1.low <= seq2.low; |
225 | 2.80k | } |
226 | | |
227 | 9.02k | return seq1.high < seq2.high; |
228 | 11.8k | } |
229 | | |
230 | | /** |
231 | | * Subtract one uint32_t from a SequenceNumber_t |
232 | | * @param seq Base SequenceNumber_t |
233 | | * @param inc uint32_t to subtract |
234 | | * @return Result of the subtraction |
235 | | */ |
236 | | inline SequenceNumber_t operator -( |
237 | | const SequenceNumber_t& seq, |
238 | | const uint32_t inc) noexcept |
239 | 1.23k | { |
240 | 1.23k | SequenceNumber_t res(seq.high, seq.low - inc); |
241 | | |
242 | 1.23k | if (inc > seq.low) |
243 | 408 | { |
244 | | // Being the type of the parameter an 'uint32_t', the decrement of 'high' will be as much as 1. |
245 | 408 | assert(0 < res.high); |
246 | 408 | --res.high; |
247 | 408 | } |
248 | | |
249 | 1.23k | return res; |
250 | 1.23k | } |
251 | | |
252 | | /** |
253 | | * Add one uint32_t to a SequenceNumber_t |
254 | | * @param [in] seq Base sequence number |
255 | | * @param inc value to add to the base |
256 | | * @return Result of the addition |
257 | | */ |
258 | | inline SequenceNumber_t operator +( |
259 | | const SequenceNumber_t& seq, |
260 | | const uint32_t inc) noexcept |
261 | 8.45k | { |
262 | 8.45k | SequenceNumber_t res(seq.high, seq.low + inc); |
263 | | |
264 | 8.45k | if (res.low < seq.low) |
265 | 352 | { |
266 | | // Being the type of the parameter an 'uint32_t', the increment of 'high' will be as much as 1. |
267 | 352 | assert(std::numeric_limits<decltype(res.high)>::max() > res.high); |
268 | 352 | ++res.high; |
269 | 352 | } |
270 | | |
271 | 8.45k | return res; |
272 | 8.45k | } |
273 | | |
274 | | /** |
275 | | * Subtract one SequenceNumber_t to another |
276 | | * @param minuend Minuend. Has to be greater than or equal to subtrahend. |
277 | | * @param subtrahend Subtrahend. |
278 | | * @return Result of the subtraction |
279 | | */ |
280 | | inline SequenceNumber_t operator -( |
281 | | const SequenceNumber_t& minuend, |
282 | | const SequenceNumber_t& subtrahend) noexcept |
283 | 0 | { |
284 | 0 | assert(minuend >= subtrahend); |
285 | 0 | SequenceNumber_t res(minuend.high - subtrahend.high, minuend.low - subtrahend.low); |
286 | |
|
287 | 0 | if (minuend.low < subtrahend.low) |
288 | 0 | { |
289 | 0 | assert(0 < res.high); |
290 | 0 | --res.high; |
291 | 0 | } |
292 | |
|
293 | 0 | return res; |
294 | 0 | } |
295 | | |
296 | | #endif // ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC |
297 | | |
298 | | const SequenceNumber_t c_SequenceNumber_Unknown{-1, 0}; |
299 | | |
300 | | #ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC |
301 | | |
302 | | /** |
303 | | * Sorts two instances of SequenceNumber_t |
304 | | * @param s1 First SequenceNumber_t to compare |
305 | | * @param s2 First SequenceNumber_t to compare |
306 | | * @return True if s1 is less than s2 |
307 | | */ |
308 | | inline bool sort_seqNum( |
309 | | const SequenceNumber_t& s1, |
310 | | const SequenceNumber_t& s2) noexcept |
311 | 0 | { |
312 | 0 | return s1 < s2; |
313 | 0 | } |
314 | | |
315 | | /** |
316 | | * |
317 | | * @param output |
318 | | * @param seqNum |
319 | | * @return |
320 | | */ |
321 | | inline std::ostream& operator <<( |
322 | | std::ostream& output, |
323 | | const SequenceNumber_t& seqNum) |
324 | 0 | { |
325 | 0 | return output << seqNum.to64long(); |
326 | 0 | } |
327 | | |
328 | | inline std::ostream& operator <<( |
329 | | std::ostream& output, |
330 | | const std::vector<SequenceNumber_t>& seqNumSet) |
331 | 0 | { |
332 | 0 | for (const SequenceNumber_t& sn : seqNumSet) |
333 | 0 | { |
334 | 0 | output << sn << " "; |
335 | 0 | } |
336 | 0 |
|
337 | 0 | return output; |
338 | 0 | } |
339 | | |
340 | | /*! |
341 | | * @brief Defines the STL hash function for type SequenceNumber_t. |
342 | | */ |
343 | | struct SequenceNumberHash |
344 | | { |
345 | | std::size_t operator ()( |
346 | | const SequenceNumber_t& sequence_number) const noexcept |
347 | 0 | { |
348 | 0 | return static_cast<std::size_t>(sequence_number.to64long()); |
349 | 0 | } |
350 | | |
351 | | }; |
352 | | |
353 | | struct SequenceNumberDiff |
354 | | { |
355 | | uint32_t operator ()( |
356 | | const SequenceNumber_t& a, |
357 | | const SequenceNumber_t& b) const noexcept |
358 | 0 | { |
359 | 0 | SequenceNumber_t diff = a - b; |
360 | 0 | return diff.low; |
361 | 0 | } |
362 | | |
363 | | }; |
364 | | |
365 | | #endif // ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC |
366 | | |
367 | | //! Structure SequenceNumberSet_t, contains a group of sequencenumbers. |
368 | | using SequenceNumberSet_t = BitmapRange<SequenceNumber_t, SequenceNumberDiff, 256>; |
369 | | |
370 | | #ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC |
371 | | |
372 | | /** |
373 | | * Prints a sequence Number set |
374 | | * @param output Output Stream |
375 | | * @param sns SequenceNumber set |
376 | | * @return OStream. |
377 | | */ |
378 | | inline std::ostream& operator <<( |
379 | | std::ostream& output, |
380 | | const SequenceNumberSet_t& sns) |
381 | 0 | { |
382 | 0 | output << sns.base().to64long() << ":"; |
383 | 0 | sns.for_each([&output]( |
384 | 0 | SequenceNumber_t it) |
385 | 0 | { |
386 | 0 | output << it.to64long() << "-"; |
387 | 0 | }); |
388 | 0 |
|
389 | 0 | return output; |
390 | 0 | } |
391 | | |
392 | | /** |
393 | | * |
394 | | * @param input |
395 | | * @param seqNum |
396 | | * @return |
397 | | */ |
398 | | inline std::istream& operator >>( |
399 | | std::istream& input, |
400 | | SequenceNumber_t& seqNum) |
401 | 0 | { |
402 | 0 | uint64_t aux; |
403 | |
|
404 | 0 | if (input >> aux) |
405 | 0 | { |
406 | 0 | seqNum = SequenceNumber_t(aux); |
407 | 0 | } |
408 | |
|
409 | 0 | return input; |
410 | 0 | } |
411 | | |
412 | | #endif // DOXYGEN_SHOULD_SKIP_THIS_PUBLIC |
413 | | |
414 | | } // namespace rtps |
415 | | } // namespace fastdds |
416 | | } // namespace eprosima |
417 | | |
418 | | #endif // FASTDDS_RTPS_COMMON__SEQUENCENUMBER_HPP |