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// This program is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License version 2 as
6// published by the Free Software Foundation;
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program; if not, write to the Free Software
15// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16//
17// Author: Gustavo J. A. M. Carneiro <gjc@inescporto.pt> <gjcarneiro@gmail.com>
18//
19
20#ifndef NS3_SEQ_NUM_H
21#define NS3_SEQ_NUM_H
22
23#include "ns3/type-name.h"
24
25#include <iostream>
26#include <limits>
27#include <stdint.h>
28
29namespace ns3
30{
31
32/**
33 * \ingroup network
34 * \defgroup seq-counters Sequence Counter
35 * \brief "sequence number" classes
36 */
37
38/**
39 * \ingroup seq-counters
40 * \brief Generic "sequence number" class
41 *
42 * This class can be used to handle sequence numbers. In networking
43 * protocols, sequence numbers are fixed precision integer numbers
44 * that are used to order events relative to each other. A sequence
45 * number is expected to increase over time but, since it has a
46 * limited number of bits, the number will "wrap around" from the
47 * maximum value that can represented with the given number of bits
48 * back to zero. For this reason, comparison of two sequence numbers,
49 * and subtraction, is non-trivial. The SequenceNumber class behaves
50 * like a number, with the usual arithmetic operators implemented, but
51 * knows how to correctly compare and subtract sequence numbers.
52 *
53 * This is a templated class. To use it you need to supply two
54 * fundamental types as template parameters: NUMERIC_TYPE and
55 * SIGNED_TYPE. For instance, SequenceNumber<uint32_t, int32_t> gives
56 * you a 32-bit sequence number, while SequenceNumber<uint16_t,
57 * int16_t> is a 16-bit one. For your convenience, these are
58 * typedef'ed as SequenceNumber32 and SequenceNumber16, respectively.
59 */
60template <typename NUMERIC_TYPE, typename SIGNED_TYPE>
62{
63 public:
65 : m_value(0)
66 {
67 }
68
69 /**
70 * \brief Constructs a SequenceNumber with the given value
71 * \param value the sequence number value
72 */
73 explicit SequenceNumber(NUMERIC_TYPE value)
74 : m_value(value)
75 {
76 }
77
78 /**
79 * \brief Constructs a SequenceNumber from a copy
80 * \param value sequence number to copy
81 */
83 : m_value(value.m_value)
84 {
85 }
86
87 /**
88 * \brief Constructs a SequenceNumber from an assignment of given value
89 * \param value sequence number to copy
90 * \returns reference to the assignee
91 */
93 {
94 m_value = value;
95 return *this;
96 }
97
98 /**
99 * \brief Constructs a SequenceNumber from an assignment of another sequence number
100 * \param value sequence number to copy
101 * \returns reference to the assignee
102 */
105 {
106 m_value = value.m_value;
107 return *this;
108 }
109
110#if 0
111 // a SequenceNumber implicitly converts to a plain number, but not the other way around
112 operator NUMERIC_TYPE () const
113 {
114 return m_value;
115 }
116#endif
117
118 /**
119 * \brief Extracts the numeric value of the sequence number
120 * \returns the sequence number value
121 */
122 NUMERIC_TYPE GetValue() const
123 {
124 return m_value;
125 }
126
127 /**
128 * \brief Prefix increment operator
129 * \returns incremented sequence number
130 */
132 {
133 m_value++;
134 return *this;
135 }
136
137 /**
138 * \brief Postfix increment operator
139 * \returns incremented sequence number
140 */
142 {
144 m_value++;
145 return retval;
146 }
147
148 /**
149 * \brief Prefix decrement operator
150 * \returns decremented sequence number
151 */
153 {
154 m_value--;
155 return *this;
156 }
157
158 /**
159 * \brief Postfix decrement operator
160 * \returns decremented sequence number
161 */
163 {
165 m_value--;
166 return retval;
167 }
168
169 /**
170 * \brief Plus equals operator
171 * \param value value to add to sequence number
172 * \returns incremented sequence number
173 */
175 {
176 m_value += value;
177 return *this;
178 }
179
180 /**
181 * \brief Minus equals operator
182 * \param value value to subtract from sequence number
183 * \returns decremented sequence number
184 */
186 {
187 m_value -= value;
188 return *this;
189 }
190
191 /**
192 * \brief Operator defining addition of two sequence numbers
193 * \param other sequence number added to this
194 * \returns sequence number representing sum
195 */
198 {
200 }
201
202 /**
203 * \brief Addition operator for adding numeric value to sequence number
204 * \param delta value to add to sequence number
205 * \returns sequence number representing sum
206 */
208 {
210 }
211
212 /**
213 * \brief Subtraction operator for subtracting numeric value from sequence number
214 * \param delta value to subtract from sequence number
215 * \returns sequence number representing difference
216 */
218 {
220 }
221
222 /**
223 * \brief Subtraction operator for subtracting sequence number from sequence number
224 * \param other sequence number to subtract from this sequence number
225 * \returns numeric value representing the difference
226 */
228 {
229 static const NUMERIC_TYPE maxValue = std::numeric_limits<NUMERIC_TYPE>::max();
230 static const NUMERIC_TYPE halfMaxValue = std::numeric_limits<NUMERIC_TYPE>::max() / 2;
231 if (m_value > other.m_value)
232 {
233 NUMERIC_TYPE diff = m_value - other.m_value;
234 if (diff < halfMaxValue)
235 {
236 return static_cast<SIGNED_TYPE>(diff);
237 }
238 else
239 {
240 // |------------|------------|
241 // ==== ===
242 // ^ ^
243 // other.m_value m_value
244 return -(static_cast<SIGNED_TYPE>(maxValue - m_value + 1 + other.m_value));
245 }
246 }
247 else
248 {
249 NUMERIC_TYPE diff = other.m_value - m_value;
250 if (diff < halfMaxValue)
251 {
252 // |------------|------------|
253 // ========
254 // ^ ^
255 // m_value other.m_value
256 return -(static_cast<SIGNED_TYPE>(diff));
257 }
258 else
259 {
260 // |------------|------------|
261 // ==== ===
262 // ^ ^
263 // m_value other.m_value
264 return static_cast<SIGNED_TYPE>(maxValue - other.m_value + 1 + m_value);
265 }
266 }
267 }
268
269 /**
270 * Here is the critical part, how the comparison is made taking into
271 * account wrap-around. From RFC 3626:
272 *
273 * The sequence number S1 is said to be "greater than" the sequence
274 * number S2 if:
275 * S1 > S2 AND S1 - S2 <= MAXVALUE/2 OR
276 * S2 > S1 AND S2 - S1 > MAXVALUE/2
277 *
278 * \param other sequence number to compare to this one
279 * \returns true if this sequence number is greater than other
280 */
282 {
283 static const NUMERIC_TYPE halfMaxValue = std::numeric_limits<NUMERIC_TYPE>::max() / 2;
284
285 return (((m_value > other.m_value) && (m_value - other.m_value) <= halfMaxValue) ||
286 ((other.m_value > m_value) && (other.m_value - m_value) > halfMaxValue));
287 }
288
289 /**
290 * \brief Equality operator for comparing sequence number
291 * \param other sequence number to compare to this sequence number
292 * \returns true if the sequence numbers are equal
293 */
295 {
296 return m_value == other.m_value;
297 }
298
299 /**
300 * \brief Inequality operator for comparing sequence numbers
301 * \param other sequence number to compare to this sequence number
302 * \returns true if the sequence numbers are not equal
303 */
305 {
306 return m_value != other.m_value;
307 }
308
309 /**
310 * \brief Less than or equal operator for comparing sequence numbers
311 * \param other sequence number to compare to this sequence number
312 * \returns true if this sequence number is less than or equal to other
313 */
315 {
316 return (!this->operator>(other));
317 }
318
319 /**
320 * \brief Greater than or equal operator for comparing sequence numbers
321 * \param other sequence number to compare to this sequence number
322 * \returns true if this sequence number is greater than or equal to other
323 */
325 {
326 return (this->operator>(other) || this->operator==(other));
327 }
328
329 /**
330 * \brief Less than operator for comparing sequence numbers
331 * \param other sequence number to compare to this sequence number
332 * \returns true if this sequence number is less than other
333 */
335 {
336 return !this->operator>(other) && m_value != other.m_value;
337 }
338
339 /**
340 * \brief For printing sequence number
341 * \param os output stream
342 * \param val sequence number to display
343 * \returns output stream os
344 */
345 template <typename NUMERIC_TYPE2, typename SIGNED_TYPE2>
346 friend std::ostream& operator<<(std::ostream& os,
348
349 /**
350 * \brief For loading sequence number from input streams
351 * \param is input stream
352 * \param val sequence number to load
353 * \returns input stream is
354 */
355 template <typename NUMERIC_TYPE2, typename SIGNED_TYPE2>
356 friend std::istream& operator>>(std::istream& is,
358
359 public:
360 // Unimplemented operators
366 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
368 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
370 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
371 bool operator!() const = delete;
376 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
378 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
380 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
382 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
384 const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>&) const = delete;
385 int operator*() = delete;
386 // SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>* operator& () = delete;
387
388 private:
389 NUMERIC_TYPE m_value; //!< Sequence number value
390};
391
392/**
393 * \brief Stream insertion operator.
394 *
395 * \param os the stream
396 * \param val the value
397 * \returns a reference to the stream
398 */
399template <typename NUMERIC_TYPE, typename SIGNED_TYPE>
400std::ostream&
401operator<<(std::ostream& os, const SequenceNumber<NUMERIC_TYPE, SIGNED_TYPE>& val)
402{
403 os << val.m_value;
404 return os;
405}
406
407/**
408 * \brief Stream extraction operator.
409 *
410 * \param is the stream
411 * \param val the value
412 * \returns a reference to the stream
413 */
414template <typename NUMERIC_TYPE, typename SIGNED_TYPE>
415std::istream&
417{
418 is >> val.m_value;
419 return is;
420}
421
422/**
423 * \ingroup seq-counters
424 * 32 bit Sequence number.
425 */
427/**
428 * \ingroup seq-counters
429 * 16 bit Sequence number.
430 */
432/**
433 * \ingroup seq-counters
434 * 8 bit Sequence number.
435 */
437
438namespace TracedValueCallback
439{
440
441/**
442 * \ingroup seq-counters
443 * TracedValue callback signature for SequenceNumber32
444 *
445 * \param [in] oldValue original value of the traced variable
446 * \param [in] newValue new value of the traced variable
447 */
448typedef void (*SequenceNumber32)(SequenceNumber32 oldValue, SequenceNumber32 newValue);
449
450} // namespace TracedValueCallback
451
452/**
453 * \ingroup seq-counters
454 *
455 * ns3::TypeNameGet<SequenceNumber32>() specialization.
456 * \returns The type name as a string.
457 */
459
460} // namespace ns3
461
462#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:60
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:159
std::istream & operator>>(std::istream &is, Angles &a)
Definition: angles.cc:183