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