Line data Source code
1 : /* 2 : * 3 : * 4 : * Distributed under the OpenDDS License. 5 : * See: http://www.opendds.org/license.html 6 : */ 7 : 8 : #ifndef OPENDDS_DCPS_SEQUENCENUMBER_H 9 : #define OPENDDS_DCPS_SEQUENCENUMBER_H 10 : 11 : #include "Serializer.h" 12 : 13 : #include <ace/Global_Macros.h> 14 : 15 : #if !defined (ACE_LACKS_PRAGMA_ONCE) 16 : #pragma once 17 : #endif /* ACE_LACKS_PRAGMA_ONCE */ 18 : 19 : #include <utility> 20 : 21 : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL 22 : 23 : namespace OpenDDS { 24 : namespace DCPS { 25 : 26 : /// Sequence number abstraction. Only allows positive 64 bit values. 27 : class OpenDDS_Dcps_Export SequenceNumber { 28 : public: 29 : typedef ACE_INT64 Value; 30 : /// Construct with a value, default to one (starting point). 31 3833 : SequenceNumber(Value value = INITIAL_VALUE) { 32 3833 : setValue(value); 33 3833 : } 34 : 35 : /// Pre-increment. 36 67 : SequenceNumber& operator++() { 37 67 : if (this->low_ == ACE_UINT32_MAX) { 38 2 : if (this->high_ == ACE_INT32_MAX) { 39 : // this code is here, despite the RTPS spec statement: 40 : // "sequence numbers never wrap" 41 1 : this->high_ = 0; 42 1 : this->low_ = 1; 43 : } else { 44 1 : ++this->high_; 45 1 : this->low_ = 0; 46 : } 47 : } else { 48 65 : ++this->low_; 49 : } 50 67 : return *this; 51 : } 52 : 53 : /// Post-increment. 54 1 : SequenceNumber operator++(int) { 55 1 : SequenceNumber value(*this); 56 1 : ++*this; 57 1 : return value; 58 : } 59 : 60 35 : SequenceNumber previous() const { 61 35 : SequenceNumber retVal(*this); 62 35 : if ((this->low_ == 0) && (this->high_ == 0)) { 63 1 : retVal.high_ = ACE_INT32_MAX; 64 1 : retVal.low_ = ACE_UINT32_MAX; 65 1 : return retVal; 66 : } 67 34 : if (this->low_ == 0) { 68 1 : --retVal.high_; 69 1 : retVal.low_ = ACE_UINT32_MAX; 70 : } else { 71 33 : --retVal.low_; 72 : } 73 34 : return retVal; 74 : } 75 : 76 3833 : void setValue(Value value) { 77 3833 : if (value < MIN_VALUE) { 78 0 : value = MIN_VALUE; 79 : } 80 3833 : this->high_ = ACE_INT32(value / LOW_BASE); 81 3833 : this->low_ = ACE_UINT32(value % LOW_BASE); 82 3833 : } 83 : 84 0 : void setValue(ACE_INT32 high, ACE_UINT32 low) { 85 0 : this->high_ = high; 86 0 : this->low_ = low; 87 0 : if (this->getValue() < MIN_VALUE) { 88 0 : this->setValue(MIN_VALUE); 89 : } 90 0 : } 91 : 92 2825 : Value getValue() const { 93 2825 : return LOW_BASE * this->high_ + this->low_; 94 : } 95 : 96 6051 : bool operator<(const SequenceNumber& rvalue) const { 97 6051 : return (this->high_ < rvalue.high_) 98 6051 : || (this->high_ == rvalue.high_ && this->low_ < rvalue.low_); 99 : } 100 : 101 : /// Derive a full suite of logical operations. 102 735 : bool operator==(const SequenceNumber& rvalue) const { 103 1470 : return (this->high_ == rvalue.high_) && 104 1470 : (this->low_ == rvalue.low_); 105 : } 106 603 : bool operator!=(const SequenceNumber& rvalue) const { 107 1205 : return (this->high_ != rvalue.high_) || 108 1205 : (this->low_ != rvalue.low_); 109 : } 110 13 : bool operator>=(const SequenceNumber& rvalue) const { 111 13 : return !(*this < rvalue); 112 : } 113 515 : bool operator<=(const SequenceNumber& rvalue) const { 114 515 : return !(rvalue < *this); 115 : } 116 67 : bool operator>(const SequenceNumber& rvalue) const { 117 67 : return (rvalue < *this) 118 67 : && (*this != rvalue); 119 : } 120 : 121 131 : ACE_INT32 getHigh() const { 122 131 : return high_; 123 : } 124 131 : ACE_UINT32 getLow() const { 125 131 : return low_; 126 : } 127 : 128 : // SEQUENCENUMBER_UNKNOWN is defined by the RTPS spec. 129 6 : static SequenceNumber SEQUENCENUMBER_UNKNOWN() { 130 6 : return SequenceNumber(-1, 0); 131 : } 132 : 133 56 : static SequenceNumber ZERO() { 134 56 : return SequenceNumber(0, 0); 135 : } 136 : 137 : static const Value MAX_VALUE = ACE_INT64_MAX; 138 : static const Value INITIAL_VALUE = 1; 139 : static const Value MIN_VALUE = 0; 140 : static const Value LOW_BASE = 0x0000000100000000LL; 141 : 142 : friend ACE_CDR::Boolean operator>>(Serializer& s, SequenceNumber& x); 143 : 144 : private: 145 : 146 : // Private constructor used to force construction of SEQUENCENUMBER_UNKNOWN. 147 : // Also used by operator>> to allow deserialization of the same value. 148 95 : SequenceNumber(ACE_INT32 high, ACE_UINT32 low) 149 95 : : high_(high), low_(low) { 150 95 : } 151 : 152 : ACE_INT32 high_; 153 : ACE_UINT32 low_; 154 : }; 155 : 156 : inline ACE_CDR::Boolean 157 23 : operator<<(Serializer& s, const SequenceNumber& x) { 158 23 : s << x.getHigh(); 159 23 : s << x.getLow(); 160 23 : return s.good_bit(); 161 : } 162 : 163 : inline ACE_CDR::Boolean 164 33 : operator>>(Serializer& s, SequenceNumber& x) { 165 : ACE_INT32 high; 166 : ACE_UINT32 low; 167 33 : if (!(s >> high)) { 168 0 : return false; 169 : } 170 33 : if (!(s >> low)) { 171 0 : return false; 172 : } 173 33 : x = SequenceNumber(high, low); 174 33 : return true; 175 : } 176 : 177 : inline SequenceNumber 178 16 : operator+(const SequenceNumber& lhs, int rhs) 179 : { 180 16 : return SequenceNumber(lhs.getValue() + rhs); 181 : } 182 : 183 : inline SequenceNumber 184 : operator+=(SequenceNumber& lhs, int rhs) 185 : { 186 : lhs.setValue(lhs.getValue() + rhs); 187 : return lhs; 188 : } 189 : 190 : inline SequenceNumber 191 : operator+(int lhs, const SequenceNumber& rhs) 192 : { 193 : return rhs + lhs; 194 : } 195 : 196 : inline 197 33 : void serialized_size(const Encoding& encoding, size_t& size, 198 : const SequenceNumber& /*sn*/) 199 : { 200 33 : primitive_serialized_size_ulong(encoding, size, 2); 201 33 : } 202 : 203 : typedef std::pair<SequenceNumber, SequenceNumber> SequenceRange; 204 : extern OpenDDS_Dcps_Export const SequenceRange unknown_sequence_range; 205 : 206 : typedef SequenceNumber::Value FragmentNumber; 207 : static const FragmentNumber INVALID_FRAGMENT = -1; 208 : 209 : } // namespace DCPS 210 : } // namespace OpenDDS 211 : 212 : OPENDDS_END_VERSIONED_NAMESPACE_DECL 213 : 214 : #endif /* OPENDDS_DCPS_SEQUENCENUMBER_H */