A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
sequence-number.h
Go to the documentation of this file.
1//
2// Copyright (c) 2008-2010 INESC Porto
3//
4// SPDX-License-Identifier: GPL-2.0-only
5//
6// Author: Gustavo J. A. M. Carneiro <gjc@inescporto.pt> <gjcarneiro@gmail.com>
7//
8
9#ifndef NS3_SEQ_NUM_H
10#define NS3_SEQ_NUM_H
11
12#include "ns3/type-name.h"
13
14#include <compare>
15#include <iostream>
16#include <limits>
17#include <stdint.h>
18
19namespace ns3
20{
21
22/**
23 * @ingroup network
24 * @defgroup seq-counters Sequence Counter
25 * @brief "sequence number" classes
26 */
27
28/**
29 * @ingroup seq-counters
30 * @brief Generic "sequence number" class
31 *
32 * This class can be used to handle sequence numbers. In networking
33 * protocols, sequence numbers are fixed precision integer numbers
34 * that are used to order events relative to each other. A sequence
35 * number is expected to increase over time but, since it has a
36 * limited number of bits, the number will "wrap around" from the
37 * maximum value that can represented with the given number of bits
38 * back to zero. For this reason, comparison of two sequence numbers,
39 * and subtraction, is non-trivial. The SequenceNumber class behaves
40 * like a number, with the usual arithmetic operators implemented, but
41 * knows how to correctly compare and subtract sequence numbers.
42 *
43 * This is a templated class. To use it you need to supply two
44 * fundamental types as template parameters: NUMERIC_TYPE and
45 * SIGNED_TYPE. For instance, SequenceNumber<uint32_t, int32_t> gives
46 * you a 32-bit sequence number, while SequenceNumber<uint16_t,
47 * int16_t> is a 16-bit one. For your convenience, these are
48 * typedef'ed as SequenceNumber32 and SequenceNumber16, respectively.
49 */
50template <typename NUMERIC_TYPE, typename SIGNED_TYPE>
52{
53 public:
55 : m_value(0)
56 {
57 }
58
59 /**
60 * @brief Constructs a SequenceNumber with the given value
61 * @param value the sequence number value
62 */
63 explicit SequenceNumber(NUMERIC_TYPE value)
64 : m_value(value)
65 {
66 }
67
68 /**
69 * @brief Constructs a SequenceNumber from a copy
70 * @param value sequence number to copy
71 */
76
77 /**
78 * @brief Constructs a SequenceNumber from an assignment of given value
79 * @param value sequence number to copy
80 * @returns reference to the assignee
81 */
83 {
84 m_value = value;
85 return *this;
86 }
87
88 /**
89 * @brief Constructs a SequenceNumber from an assignment of another sequence number
90 * @param value sequence number to copy
91 * @returns reference to the assignee
92 */
95 {
96 m_value = value.m_value;
97 return *this;
98 }
99
100#if 0
101 // a SequenceNumber implicitly converts to a plain number, but not the other way around
102 operator NUMERIC_TYPE () const
103 {
104 return m_value;
105 }
106#endif
107
108 /**
109 * @brief Extracts the numeric value of the sequence number
110 * @returns the sequence number value
111 */
112 NUMERIC_TYPE GetValue() const
113 {
114 return m_value;
115 }
116
117 /**
118 * @brief Prefix increment operator
119 * @returns incremented sequence number
120 */
122 {
123 m_value++;
124 return *this;
125 }
126
127 /**
128 * @brief Postfix increment operator
129 * @returns incremented sequence number
130 */
137
138 /**
139 * @brief Prefix decrement operator
140 * @returns decremented sequence number
141 */
143 {
144 m_value--;
145 return *this;
146 }
147
148 /**
149 * @brief Postfix decrement operator
150 * @returns decremented sequence number
151 */
158
159 /**
160 * @brief Plus equals operator
161 * @param value value to add to sequence number
162 * @returns incremented sequence number
163 */
165 {
166 m_value += value;
167 return *this;
168 }
169
170 /**
171 * @brief Minus equals operator
172 * @param value value to subtract from sequence number
173 * @returns decremented sequence number
174 */
176 {
177 m_value -= value;
178 return *this;
179 }
180
181 /**
182 * @brief Operator defining addition of two sequence numbers
183 * @param other sequence number added to this
184 * @returns sequence number representing sum
185 */
191
192 /**
193 * @brief Addition operator for adding numeric value to sequence number
194 * @param delta value to add to sequence number
195 * @returns sequence number representing sum
196 */
201
202 /**
203 * @brief Subtraction operator for subtracting numeric value from sequence number
204 * @param delta value to subtract from sequence number
205 * @returns sequence number representing difference
206 */
211
212 /**
213 * @brief Subtraction operator for subtracting sequence number from sequence number
214 * @param other sequence number to subtract from this sequence number
215 * @returns numeric value representing the difference
216 */
218 {
219 static const NUMERIC_TYPE maxValue = std::numeric_limits<NUMERIC_TYPE>::max();
220 static const NUMERIC_TYPE halfMaxValue = std::numeric_limits<NUMERIC_TYPE>::max() / 2;
221 if (m_value > other.m_value)
222 {
223 NUMERIC_TYPE diff = m_value - other.m_value;
224 if (diff < halfMaxValue)
225 {
226 return static_cast<SIGNED_TYPE>(diff);
227 }
228 else
229 {
230 // |------------|------------|
231 // ==== ===
232 // ^ ^
233 // other.m_value m_value
234 return -(static_cast<SIGNED_TYPE>(maxValue - m_value + 1 + other.m_value));
235 }
236 }
237 else
238 {
239 NUMERIC_TYPE diff = other.m_value - m_value;
240 if (diff < halfMaxValue)
241 {
242 // |------------|------------|
243 // ========
244 // ^ ^
245 // m_value other.m_value
246 return -(static_cast<SIGNED_TYPE>(diff));
247 }
248 else
249 {
250 // |------------|------------|
251 // ==== ===
252 // ^ ^
253 // m_value other.m_value
254 return static_cast<SIGNED_TYPE>(maxValue - other.m_value + 1 + m_value);
255 }
256 }
257 }
258
259 /**
260 * @brief Equality operator for comparing sequence number
261 * @param other sequence number to compare to this sequence number
262 * @returns true if the sequence numbers are equal
263 */
265 {
266 return m_value == other.m_value;
267 }
268
269 /**
270 * Spaceship comparison operator. All the other comparison operators
271 * are automatically generated from this one.
272 *
273 * Here is the critical part, how the comparison is made taking into
274 * account wrap-around. From RFC 3626:
275 *
276 * The sequence number S1 is said to be "greater than" the sequence
277 * number S2 if:
278 * S1 > S2 AND S1 - S2 <= MAXVALUE/2 OR
279 * S2 > S1 AND S2 - S1 > MAXVALUE/2
280 *
281 * @param other sequence number to compare to this one
282 * @returns The result of the comparison.
283 */
284 constexpr std::strong_ordering operator<=>(
286 {
287 constexpr auto halfMaxValue = std::numeric_limits<NUMERIC_TYPE>::max() / 2;
288
289 if (m_value == other.m_value)
290 {
291 return std::strong_ordering::equivalent;
292 }
293 if (((m_value > other.m_value) && (m_value - other.m_value) <= halfMaxValue) ||
294 ((other.m_value > m_value) && (other.m_value - m_value) > halfMaxValue))
295 {
296 return std::strong_ordering::greater;
297 }
298 return std::strong_ordering::less;
299 }
300
301 /**
302 * @brief For printing sequence number
303 * @param os output stream
304 * @param val sequence number to display
305 * @returns output stream os
306 */
307 template <typename NUMERIC_TYPE2, typename SIGNED_TYPE2>
308 friend std::ostream& operator<<(std::ostream& os,
310
311 /**
312 * @brief For loading sequence number from input streams
313 * @param is input stream
314 * @param val sequence number to load
315 * @returns input stream is
316 */
317 template <typename NUMERIC_TYPE2, typename SIGNED_TYPE2>
318 friend std::istream& operator>>(std::istream& is,
320
321 public:
322 // Unimplemented operators
328 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
330 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
332 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
333 bool operator!() const = delete;
338 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
340 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
342 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
344 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
346 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
347 int operator*() = delete;
348 // SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>* operator& () = delete;
349
350 private:
351 NUMERIC_TYPE m_value; //!< Sequence number value
352};
353
354/**
355 * @brief Stream insertion operator.
356 *
357 * @param os the stream
358 * @param val the value
359 * @returns a reference to the stream
360 */
361template <typename NUMERIC_TYPE, typename SIGNED_TYPE>
362std::ostream&
363operator<<(std::ostream& os, const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& val)
364{
365 os << val.m_value;
366 return os;
367}
368
369/**
370 * @brief Stream extraction operator.
371 *
372 * @param is the stream
373 * @param val the value
374 * @returns a reference to the stream
375 */
376template <typename NUMERIC_TYPE, typename SIGNED_TYPE>
377std::istream&
379{
380 is >> val.m_value;
381 return is;
382}
383
384/**
385 * @ingroup seq-counters
386 * 32 bit Sequence number.
387 */
389/**
390 * @ingroup seq-counters
391 * 16 bit Sequence number.
392 */
394/**
395 * @ingroup seq-counters
396 * 8 bit Sequence number.
397 */
399
400namespace TracedValueCallback
401{
402
403/**
404 * @ingroup seq-counters
405 * TracedValue callback signature for SequenceNumber32
406 *
407 * @param [in] oldValue original value of the traced variable
408 * @param [in] newValue new value of the traced variable
409 */
410typedef void (*SequenceNumber32)(SequenceNumber32 oldValue, SequenceNumber32 newValue);
411
412} // namespace TracedValueCallback
413
414/**
415 * @ingroup seq-counters
416 *
417 * ns3::TypeNameGet<SequenceNumber32>() specialization.
418 * @returns The type name as a string.
419 */
421
422} // namespace ns3
423
424#endif /* NS3_SEQ_NUM_H */
Generic "sequence number" class.
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > operator%(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &) const =delete
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > operator--(int)
Postfix decrement operator.
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > operator/(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &) const =delete
int operator*()=delete
constexpr std::strong_ordering operator<=>(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &other) const
Spaceship comparison operator.
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > operator+(SIGNED_TYPE delta) const
Addition operator for adding numeric value to sequence number.
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > operator++(int)
Postfix increment operator.
bool operator&&(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &) const =delete
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > & operator+=(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &)=delete
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > & operator-=(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &)=delete
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > operator|(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &) const =delete
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > operator-(SIGNED_TYPE delta) const
Subtraction operator for subtracting numeric value from sequence number.
bool operator!() const =delete
SequenceNumber(NUMERIC_TYPE value)
Constructs a SequenceNumber with the given value.
SIGNED_TYPE operator-(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &other) const
Subtraction operator for subtracting sequence number from sequence number.
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > & operator=(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &value)
Constructs a SequenceNumber from an assignment of another sequence number.
bool operator==(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &other) const
Equality operator for comparing sequence number.
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > operator^(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &) const =delete
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > & operator-=(SIGNED_TYPE value)
Minus equals operator.
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > & operator+=(SIGNED_TYPE value)
Plus equals operator.
friend std::ostream & operator<<(std::ostream &os, const SequenceNumber< NUMERIC_TYPE2, SIGNED_TYPE2 > &val)
For printing sequence number.
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > & operator=(NUMERIC_TYPE value)
Constructs a SequenceNumber from an assignment of given value.
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > operator*(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &) const =delete
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > operator&(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &) const =delete
NUMERIC_TYPE GetValue() const
Extracts the numeric value of the sequence number.
bool operator||(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &) const =delete
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > operator+(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &other) const
Operator defining addition of two sequence numbers.
friend std::istream & operator>>(std::istream &is, const SequenceNumber< NUMERIC_TYPE2, SIGNED_TYPE2 > &val)
For loading sequence number from input streams.
SequenceNumber(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &value)
Constructs a SequenceNumber from a copy.
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > operator>>(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &) const =delete
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > operator--()
Prefix decrement operator.
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > operator++()
Prefix increment operator.
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > operator~() const =delete
#define TYPENAMEGET_DEFINE(T)
Macro that defines a template specialization for TypeNameGet<T>() .
Definition type-name.h:49
void(* SequenceNumber32)(SequenceNumber32 oldValue, SequenceNumber32 newValue)
TracedValue callback signature for SequenceNumber32.
SequenceNumber< uint8_t, int8_t > SequenceNumber8
8 bit Sequence number.
SequenceNumber< uint32_t, int32_t > SequenceNumber32
32 bit Sequence number.
SequenceNumber< uint16_t, int16_t > SequenceNumber16
16 bit Sequence number.
TracedValue Callback function types.
Definition nstime.h:874
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition angles.cc:148
std::istream & operator>>(std::istream &is, Angles &a)
Definition angles.cc:172