Overte C++ Documentation
SequenceNumber.h
1 //
2 // SequenceNumber.h
3 // libraries/networking/src/udt
4 //
5 // Created by Clement on 7/23/15.
6 // Copyright 2015 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 
12 #ifndef hifi_SequenceNumber_h
13 #define hifi_SequenceNumber_h
14 
15 #include <functional>
16 
17 #include <glm/common.hpp>
18 
19 namespace udt {
20 
21 class SequenceNumber {
22 public:
23  // Base type of sequence numbers
24  using Type = int32_t;
25  using UType = uint32_t;
26 
27  // Values are for 27 bit SequenceNumber
28  static const Type THRESHOLD = 0x03FFFFFF; // Threshold for comparing sequence numbers.
29  static const Type MAX = 0x07FFFFFF; // Maximum sequence number used in UDT.
30 
31  SequenceNumber() = default;
32  SequenceNumber(const SequenceNumber& other) : _value(other._value) {}
33 
34  // Only explicit conversions
35  explicit SequenceNumber(char* value) { _value = (*reinterpret_cast<int32_t*>(value)) & MAX; }
36  explicit SequenceNumber(Type value) { _value = (value <= MAX) ? ((value >= 0) ? value : 0) : MAX; }
37  explicit SequenceNumber(UType value) { _value = (value <= MAX) ? value : MAX; }
38  explicit operator Type() const { return _value; }
39  explicit operator UType() const { return static_cast<UType>(_value); }
40 
41  inline SequenceNumber& operator++() {
42  _value = (_value + 1) % (MAX + 1);
43  return *this;
44  }
45  inline SequenceNumber& operator--() {
46  _value = (_value == 0) ? MAX : _value - 1;
47  return *this;
48  }
49  inline SequenceNumber operator++(int) {
50  SequenceNumber before = *this;
51  ++(*this);
52  return before;
53  }
54  inline SequenceNumber operator--(int) {
55  SequenceNumber before = *this;
56  --(*this);
57  return before;
58  }
59 
60  inline SequenceNumber& operator=(const SequenceNumber& other) {
61  _value = other._value;
62  return *this;
63  }
64  inline SequenceNumber& operator+=(Type inc) {
65  _value = (_value + inc > MAX) ? _value + inc - (MAX + 1) : _value + inc;
66  return *this;
67  }
68  inline SequenceNumber& operator-=(Type dec) {
69  _value = (_value < dec) ? MAX - (dec - _value + 1) : _value - dec;
70  return *this;
71  }
72 
73  inline bool operator==(const SequenceNumber& other) const {
74  return _value == other._value;
75  }
76  inline bool operator!=(const SequenceNumber& other) const {
77  return _value != other._value;
78  }
79 
80  friend bool operator<(const SequenceNumber& a, const SequenceNumber& b);
81  friend bool operator>(const SequenceNumber& a, const SequenceNumber& b);
82  friend bool operator<=(const SequenceNumber& a, const SequenceNumber& b);
83  friend bool operator>=(const SequenceNumber& a, const SequenceNumber& b);
84 
85  friend SequenceNumber operator+(const SequenceNumber a, const Type& b);
86  friend SequenceNumber operator+(const Type& a, const SequenceNumber b);
87  friend SequenceNumber operator-(const SequenceNumber a, const Type& b);
88  friend SequenceNumber operator-(const Type& a, const SequenceNumber b);
89 
90  friend int seqlen(const SequenceNumber& seq1, const SequenceNumber& seq2);
91  friend int seqoff(const SequenceNumber& seq1, const SequenceNumber& seq2);
92 
93 private:
94  Type _value { 0 };
95 
96  friend struct std::hash<SequenceNumber>;
97 };
98 static_assert(sizeof(SequenceNumber) == sizeof(uint32_t), "SequenceNumber invalid size");
99 
100 
101 inline bool operator<(const SequenceNumber& a, const SequenceNumber& b) {
102  return (glm::abs(a._value - b._value) < SequenceNumber::THRESHOLD) ? a._value < b._value : b._value < a._value;
103 }
104 
105 inline bool operator>(const SequenceNumber& a, const SequenceNumber& b) {
106  return (glm::abs(a._value - b._value) < SequenceNumber::THRESHOLD) ? a._value > b._value : b._value > a._value;
107 }
108 
109 inline bool operator<=(const SequenceNumber& a, const SequenceNumber& b) {
110  return (glm::abs(a._value - b._value) < SequenceNumber::THRESHOLD) ? a._value <= b._value : b._value <= a._value;
111 }
112 
113 inline bool operator>=(const SequenceNumber& a, const SequenceNumber& b) {
114  return (glm::abs(a._value - b._value) < SequenceNumber::THRESHOLD) ? a._value >= b._value : b._value >= a._value;
115 }
116 
117 
118 inline SequenceNumber operator+(SequenceNumber a, const SequenceNumber::Type& b) {
119  a += b;
120  return a;
121 }
122 
123 inline SequenceNumber operator+(const SequenceNumber::Type& a, SequenceNumber b) {
124  b += a;
125  return b;
126 }
127 
128 inline SequenceNumber operator-(SequenceNumber a, const SequenceNumber::Type& b) {
129  a -= b;
130  return a;
131 }
132 
133 inline SequenceNumber operator-(const SequenceNumber::Type& a, SequenceNumber b) {
134  b -= a;
135  return b;
136 }
137 
138 int seqlen(const SequenceNumber& seq1, const SequenceNumber& seq2);
139 int seqoff(const SequenceNumber& seq1, const SequenceNumber& seq2);
140 
141 }
142 
143 namespace std {
144  template<> struct hash<udt::SequenceNumber> {
145  size_t operator()(const udt::SequenceNumber& SequenceNumber) const {
146  return hash<unsigned long>()(SequenceNumber._value);
147  }
148  };
149 }
150 
151 #endif // hifi_SequenceNumber_h