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 <iostream>
15#include <limits>
16#include <stdint.h>
17
18namespace ns3
19{
20
21/**
22 * @ingroup network
23 * @defgroup seq-counters Sequence Counter
24 * @brief "sequence number" classes
25 */
26
27/**
28 * @ingroup seq-counters
29 * @brief Generic "sequence number" class
30 *
31 * This class can be used to handle sequence numbers. In networking
32 * protocols, sequence numbers are fixed precision integer numbers
33 * that are used to order events relative to each other. A sequence
34 * number is expected to increase over time but, since it has a
35 * limited number of bits, the number will "wrap around" from the
36 * maximum value that can represented with the given number of bits
37 * back to zero. For this reason, comparison of two sequence numbers,
38 * and subtraction, is non-trivial. The SequenceNumber class behaves
39 * like a number, with the usual arithmetic operators implemented, but
40 * knows how to correctly compare and subtract sequence numbers.
41 *
42 * This is a templated class. To use it you need to supply two
43 * fundamental types as template parameters: NUMERIC_TYPE and
44 * SIGNED_TYPE. For instance, SequenceNumber<uint32_t, int32_t> gives
45 * you a 32-bit sequence number, while SequenceNumber<uint16_t,
46 * int16_t> is a 16-bit one. For your convenience, these are
47 * typedef'ed as SequenceNumber32 and SequenceNumber16, respectively.
48 */
49template <typename NUMERIC_TYPE, typename SIGNED_TYPE>
51{
52 public:
54 : m_value(0)
55 {
56 }
57
58 /**
59 * @brief Constructs a SequenceNumber with the given value
60 * @param value the sequence number value
61 */
62 explicit SequenceNumber(NUMERIC_TYPE value)
63 : m_value(value)
64 {
65 }
66
67 /**
68 * @brief Constructs a SequenceNumber from a copy
69 * @param value sequence number to copy
70 */
75
76 /**
77 * @brief Constructs a SequenceNumber from an assignment of given value
78 * @param value sequence number to copy
79 * @returns reference to the assignee
80 */
82 {
83 m_value = value;
84 return *this;
85 }
86
87 /**
88 * @brief Constructs a SequenceNumber from an assignment of another sequence number
89 * @param value sequence number to copy
90 * @returns reference to the assignee
91 */
94 {
95 m_value = value.m_value;
96 return *this;
97 }
98
99#if 0
100 // a SequenceNumber implicitly converts to a plain number, but not the other way around
101 operator NUMERIC_TYPE () const
102 {
103 return m_value;
104 }
105#endif
106
107 /**
108 * @brief Extracts the numeric value of the sequence number
109 * @returns the sequence number value
110 */
111 NUMERIC_TYPE GetValue() const
112 {
113 return m_value;
114 }
115
116 /**
117 * @brief Prefix increment operator
118 * @returns incremented sequence number
119 */
121 {
122 m_value++;
123 return *this;
124 }
125
126 /**
127 * @brief Postfix increment operator
128 * @returns incremented sequence number
129 */
136
137 /**
138 * @brief Prefix decrement operator
139 * @returns decremented sequence number
140 */
142 {
143 m_value--;
144 return *this;
145 }
146
147 /**
148 * @brief Postfix decrement operator
149 * @returns decremented sequence number
150 */
157
158 /**
159 * @brief Plus equals operator
160 * @param value value to add to sequence number
161 * @returns incremented sequence number
162 */
164 {
165 m_value += value;
166 return *this;
167 }
168
169 /**
170 * @brief Minus equals operator
171 * @param value value to subtract from sequence number
172 * @returns decremented sequence number
173 */
175 {
176 m_value -= value;
177 return *this;
178 }
179
180 /**
181 * @brief Operator defining addition of two sequence numbers
182 * @param other sequence number added to this
183 * @returns sequence number representing sum
184 */
190
191 /**
192 * @brief Addition operator for adding numeric value to sequence number
193 * @param delta value to add to sequence number
194 * @returns sequence number representing sum
195 */
200
201 /**
202 * @brief Subtraction operator for subtracting numeric value from sequence number
203 * @param delta value to subtract from sequence number
204 * @returns sequence number representing difference
205 */
210
211 /**
212 * @brief Subtraction operator for subtracting sequence number from sequence number
213 * @param other sequence number to subtract from this sequence number
214 * @returns numeric value representing the difference
215 */
217 {
218 static const NUMERIC_TYPE maxValue = std::numeric_limits<NUMERIC_TYPE>::max();
219 static const NUMERIC_TYPE halfMaxValue = std::numeric_limits<NUMERIC_TYPE>::max() / 2;
220 if (m_value > other.m_value)
221 {
222 NUMERIC_TYPE diff = m_value - other.m_value;
223 if (diff < halfMaxValue)
224 {
225 return static_cast<SIGNED_TYPE>(diff);
226 }
227 else
228 {
229 // |------------|------------|
230 // ==== ===
231 // ^ ^
232 // other.m_value m_value
233 return -(static_cast<SIGNED_TYPE>(maxValue - m_value + 1 + other.m_value));
234 }
235 }
236 else
237 {
238 NUMERIC_TYPE diff = other.m_value - m_value;
239 if (diff < halfMaxValue)
240 {
241 // |------------|------------|
242 // ========
243 // ^ ^
244 // m_value other.m_value
245 return -(static_cast<SIGNED_TYPE>(diff));
246 }
247 else
248 {
249 // |------------|------------|
250 // ==== ===
251 // ^ ^
252 // m_value other.m_value
253 return static_cast<SIGNED_TYPE>(maxValue - other.m_value + 1 + m_value);
254 }
255 }
256 }
257
258 /**
259 * Here is the critical part, how the comparison is made taking into
260 * account wrap-around. From RFC 3626:
261 *
262 * The sequence number S1 is said to be "greater than" the sequence
263 * number S2 if:
264 * S1 > S2 AND S1 - S2 <= MAXVALUE/2 OR
265 * S2 > S1 AND S2 - S1 > MAXVALUE/2
266 *
267 * @param other sequence number to compare to this one
268 * @returns true if this sequence number is greater than other
269 */
271 {
272 static const NUMERIC_TYPE halfMaxValue = std::numeric_limits<NUMERIC_TYPE>::max() / 2;
273
274 return (((m_value > other.m_value) && (m_value - other.m_value) <= halfMaxValue) ||
275 ((other.m_value > m_value) && (other.m_value - m_value) > halfMaxValue));
276 }
277
278 /**
279 * @brief Equality operator for comparing sequence number
280 * @param other sequence number to compare to this sequence number
281 * @returns true if the sequence numbers are equal
282 */
284 {
285 return m_value == other.m_value;
286 }
287
288 /**
289 * @brief Inequality operator for comparing sequence numbers
290 * @param other sequence number to compare to this sequence number
291 * @returns true if the sequence numbers are not equal
292 */
294 {
295 return m_value != other.m_value;
296 }
297
298 /**
299 * @brief Less than or equal operator for comparing sequence numbers
300 * @param other sequence number to compare to this sequence number
301 * @returns true if this sequence number is less than or equal to other
302 */
304 {
305 return (!this->operator>(other));
306 }
307
308 /**
309 * @brief Greater than or equal operator for comparing sequence numbers
310 * @param other sequence number to compare to this sequence number
311 * @returns true if this sequence number is greater than or equal to other
312 */
314 {
315 return (this->operator>(other) || this->operator==(other));
316 }
317
318 /**
319 * @brief Less than operator for comparing sequence numbers
320 * @param other sequence number to compare to this sequence number
321 * @returns true if this sequence number is less than other
322 */
324 {
325 return !this->operator>(other) && m_value != other.m_value;
326 }
327
328 /**
329 * @brief For printing sequence number
330 * @param os output stream
331 * @param val sequence number to display
332 * @returns output stream os
333 */
334 template <typename NUMERIC_TYPE2, typename SIGNED_TYPE2>
335 friend std::ostream& operator<<(std::ostream& os,
337
338 /**
339 * @brief For loading sequence number from input streams
340 * @param is input stream
341 * @param val sequence number to load
342 * @returns input stream is
343 */
344 template <typename NUMERIC_TYPE2, typename SIGNED_TYPE2>
345 friend std::istream& operator>>(std::istream& is,
347
348 public:
349 // Unimplemented operators
355 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
357 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
359 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
360 bool operator!() const = delete;
365 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
367 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
369 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
371 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
373 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
374 int operator*() = delete;
375 // SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>* operator& () = delete;
376
377 private:
378 NUMERIC_TYPE m_value; //!< Sequence number value
379};
380
381/**
382 * @brief Stream insertion operator.
383 *
384 * @param os the stream
385 * @param val the value
386 * @returns a reference to the stream
387 */
388template <typename NUMERIC_TYPE, typename SIGNED_TYPE>
389std::ostream&
390operator<<(std::ostream& os, const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& val)
391{
392 os << val.m_value;
393 return os;
394}
395
396/**
397 * @brief Stream extraction operator.
398 *
399 * @param is the stream
400 * @param val the value
401 * @returns a reference to the stream
402 */
403template <typename NUMERIC_TYPE, typename SIGNED_TYPE>
404std::istream&
406{
407 is >> val.m_value;
408 return is;
409}
410
411/**
412 * @ingroup seq-counters
413 * 32 bit Sequence number.
414 */
416/**
417 * @ingroup seq-counters
418 * 16 bit Sequence number.
419 */
421/**
422 * @ingroup seq-counters
423 * 8 bit Sequence number.
424 */
426
427namespace TracedValueCallback
428{
429
430/**
431 * @ingroup seq-counters
432 * TracedValue callback signature for SequenceNumber32
433 *
434 * @param [in] oldValue original value of the traced variable
435 * @param [in] newValue new value of the traced variable
436 */
437typedef void (*SequenceNumber32)(SequenceNumber32 oldValue, SequenceNumber32 newValue);
438
439} // namespace TracedValueCallback
440
441/**
442 * @ingroup seq-counters
443 *
444 * ns3::TypeNameGet<SequenceNumber32>() specialization.
445 * @returns The type name as a string.
446 */
448
449} // namespace ns3
450
451#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
bool operator<(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &other) const
Less than operator for comparing sequence numbers.
int operator*()=delete
SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > operator+(SIGNED_TYPE delta) const
Addition operator for adding numeric value to sequence number.
bool operator>(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &other) const
Here is the critical part, how the comparison is made taking into account wrap-around.
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 SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &other) const
Less than or equal operator for comparing sequence numbers.
bool operator!() const =delete
bool operator!=(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &other) const
Inequality operator for comparing sequence numbers.
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
NUMERIC_TYPE m_value
Sequence number value.
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
bool operator>=(const SequenceNumber< NUMERIC_TYPE, SIGNED_TYPE > &other) const
Greater than or equal operator for comparing sequence numbers.
#define TYPENAMEGET_DEFINE(T)
Macro that defines a template specialization for TypeNameGet<T>() .
Definition type-name.h:49
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.
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