OpenDDS  Snapshot(2023/04/07-19:43)
Classes | Public Member Functions | Static Public Member Functions | Private Types | Private Member Functions | Private Attributes | List of all members
OpenDDS::DCPS::DisjointSequence Class Reference

#include <DisjointSequence.h>

Collaboration diagram for OpenDDS::DCPS::DisjointSequence:
Collaboration graph
[legend]

Classes

class  OrderedRanges
 

Public Member Functions

 DisjointSequence ()
 
void reset ()
 
bool empty () const
 
SequenceNumber low () const
 
SequenceNumber high () const
 
SequenceNumber cumulative_ack () const
 
SequenceNumber last_ack () const
 
bool disjoint () const
 
bool contains (SequenceNumber value) const
 
bool contains_any (const SequenceRange &range) const
 
bool insert (const SequenceRange &range, OPENDDS_VECTOR(SequenceRange)&added)
 
bool insert (const SequenceRange &range)
 Insert all numbers between range.first and range.second (both inclusive). More...
 
bool insert (SequenceNumber value)
 Shorthand for "insert(SequenceRange(value, value))". More...
 
void erase (SequenceNumber value)
 
bool insert (SequenceNumber value, ACE_CDR::ULong num_bits, const ACE_CDR::Long bits[])
 
bool insert_filtered (const SequenceRange &range, const DisjointSequence &filter)
 Insert the intersection of range and filter. More...
 
bool to_bitmap (ACE_CDR::Long bitmap[], ACE_CDR::ULong length, ACE_CDR::ULong &num_bits, ACE_CDR::ULong &cumulative_bits_added, bool invert=false) const
 
 OPENDDS_VECTOR (SequenceRange) missing_sequence_ranges() const
 Returns missing ranges of SequenceNumbers (internal gaps in the sequence) More...
 
 OPENDDS_VECTOR (SequenceRange) present_sequence_ranges() const
 
void dump () const
 

Static Public Member Functions

static bool fill_bitmap_range (ACE_CDR::ULong low, ACE_CDR::ULong high, ACE_CDR::Long bitmap[], ACE_CDR::ULong length, ACE_CDR::ULong &num_bits, ACE_CDR::ULong &cumulative_bits_added)
 Set the bits in range [low, high] in the bitmap, updating num_bits. More...
 
static ACE_CDR::ULong bitmap_num_longs (const SequenceNumber &low, const SequenceNumber &high)
 

Private Types

typedef OrderedRanges< SequenceNumberRangeSet
 

Private Member Functions

bool insert_i (const SequenceRange &range, OPENDDS_VECTOR(SequenceRange) *gaps=0)
 
bool insert_bitmap_range (RangeSet::Container::iterator &iter, const SequenceRange &sr)
 

Private Attributes

RangeSet sequences_
 

Detailed Description

Data structure for a set of SequenceNumbers. Sequence numbers can be inserted as single numbers, ranges, or RTPS-style bitmaps. The DisjointSequence can then be queried for contiguous ranges and internal gaps.

Definition at line 23 of file DisjointSequence.h.

Member Typedef Documentation

◆ RangeSet

Definition at line 274 of file DisjointSequence.h.

Constructor & Destructor Documentation

◆ DisjointSequence()

ACE_INLINE OpenDDS::DCPS::DisjointSequence::DisjointSequence ( )

Definition at line 54 of file DisjointSequence.inl.

References ACE_INLINE.

55 {
56 }

Member Function Documentation

◆ bitmap_num_longs()

ACE_CDR::ULong OpenDDS::DCPS::DisjointSequence::bitmap_num_longs ( const SequenceNumber low,
const SequenceNumber high 
)
static

Return the number of CORBA::Longs required for the bitmap representation of sequence numbers between low and high, inclusive (maximum 8 longs).

Definition at line 331 of file DisjointSequence.cpp.

References OpenDDS::DCPS::SequenceNumber::getValue().

Referenced by OpenDDS::DCPS::RtpsUdpDataLink::RtpsReader::gather_ack_nacks_i(), and OpenDDS::DCPS::RtpsUdpDataLink::RtpsWriter::gather_gaps_i().

332 {
333  return high < low ? 0u : std::min(8u, unsigned((high.getValue() - low.getValue() + 32) / 32));
334 }

◆ contains()

bool OpenDDS::DCPS::DisjointSequence::contains ( SequenceNumber  value) const

◆ contains_any()

bool OpenDDS::DCPS::DisjointSequence::contains_any ( const SequenceRange range) const

◆ cumulative_ack()

ACE_INLINE SequenceNumber OpenDDS::DCPS::DisjointSequence::cumulative_ack ( ) const

Gets the high end of the lowest contiguous range. Named after the use case of tracking received messages (which may be received out-of-order) and then determining the largest value that the receiver is allowed to acknowledge (under a cumulative-acking protocol). If empty(), returns SEQUENCENUMBER_UNKNOWN.

Definition at line 26 of file DisjointSequence.inl.

References ACE_INLINE, OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::begin(), OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::empty(), OpenDDS::DCPS::SequenceNumber::SEQUENCENUMBER_UNKNOWN(), and sequences_.

Referenced by OpenDDS::DCPS::ReliableSession::deliver_held_data(), OpenDDS::DCPS::RtpsUdpDataLink::RtpsReader::gather_ack_nacks_i(), OpenDDS::DCPS::RtpsUdpDataLink::RtpsWriter::gather_gaps_i(), OpenDDS::DCPS::ReliableSession::ready_to_deliver(), OpenDDS::DCPS::ReliableSession::send_naks(), and to_bitmap().

27 {
28  return sequences_.empty()
30  : sequences_.begin()->second;
31 }
static SequenceNumber SEQUENCENUMBER_UNKNOWN()

◆ disjoint()

ACE_INLINE bool OpenDDS::DCPS::DisjointSequence::disjoint ( ) const

◆ dump()

void OpenDDS::DCPS::DisjointSequence::dump ( void  ) const

Definition at line 319 of file DisjointSequence.cpp.

References ACE_DEBUG, OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::begin(), OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::end(), LM_DEBUG, and sequences_.

Referenced by OpenDDS::DCPS::RtpsUdpDataLink::RtpsWriter::gather_nack_replies_i(), and OpenDDS::DCPS::ReliableSession::send_naks().

320 {
321  ACE_DEBUG((LM_DEBUG, "(%P|%t) DisjointSequence[%X]::dump included ranges of "
322  "SequenceNumbers:\n", this));
324  iter != sequences_.end(); ++iter) {
325  ACE_DEBUG((LM_DEBUG, "(%P|%t) DisjointSequence[%X]::dump\t%q-%q\n",
326  this, iter->first.getValue(), iter->second.getValue()));
327  }
328 }
#define ACE_DEBUG(X)

◆ empty()

ACE_INLINE bool OpenDDS::DCPS::DisjointSequence::empty ( void  ) const

◆ erase()

void OpenDDS::DCPS::DisjointSequence::erase ( SequenceNumber  value)

Definition at line 337 of file DisjointSequence.cpp.

References OPENDDS_END_VERSIONED_NAMESPACE_DECL, OpenDDS::DCPS::SequenceNumber::previous(), OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::ranges_, and sequences_.

Referenced by OpenDDS::DCPS::WriteDataContainer::reenqueue_all().

338 {
339  RangeSet::Container::iterator iter =
340  sequences_.ranges_.lower_bound(SequenceRange(0 /*ignored*/, value));
341  if (iter != sequences_.ranges_.end()) {
342  if (iter->first == value &&
343  iter->second == value) {
344  sequences_.ranges_.erase(iter);
345  } else if (iter->first == value) {
346  SequenceRange x(value + 1, iter->second);
347  sequences_.ranges_.erase(iter);
348  sequences_.ranges_.insert(x);
349  } else if (iter->second == value) {
350  SequenceRange x(iter->first, value.previous());
351  sequences_.ranges_.erase(iter);
352  sequences_.ranges_.insert(x);
353  } else {
354  SequenceRange x(iter->first, value.previous());
355  SequenceRange y(value + 1, iter->second);
356  sequences_.ranges_.erase(iter);
357  sequences_.ranges_.insert(x);
358  sequences_.ranges_.insert(y);
359  }
360  }
361 }
const LogLevel::Value value
Definition: debug.cpp:61
std::pair< SequenceNumber, SequenceNumber > SequenceRange

◆ fill_bitmap_range()

bool OpenDDS::DCPS::DisjointSequence::fill_bitmap_range ( ACE_CDR::ULong  low,
ACE_CDR::ULong  high,
ACE_CDR::Long  bitmap[],
ACE_CDR::ULong  length,
ACE_CDR::ULong num_bits,
ACE_CDR::ULong cumulative_bits_added 
)
static

Set the bits in range [low, high] in the bitmap, updating num_bits.

Definition at line 238 of file DisjointSequence.cpp.

References OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::begin(), disjoint(), OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::end(), OPENDDS_VECTOR(), OpenDDS::DCPS::SequenceNumber::previous(), and sequences_.

Referenced by OpenDDS::DCPS::RtpsUdpDataLink::extend_bitmap_range(), OpenDDS::DCPS::RtpsUdpDataLink::RtpsReader::gather_ack_nacks_i(), OpenDDS::DCPS::TransportReassembly::get_gaps(), and to_bitmap().

241 {
242  bool clamped = false;
243  if ((low / 32) >= length) {
244  return false;
245  }
246  if ((high / 32) >= length) {
247  high = length * 32 - 1;
248  clamped = true;
249  }
250 
251  const ACE_CDR::ULong idx_nb = num_bits / 32, bit_nb = num_bits % 32,
252  idx_low = low / 32, bit_low = low % 32,
253  idx_high = high / 32, bit_high = high % 32;
254 
255  // handle idx_nb zeros
256  if (bit_nb) {
257  bitmap[idx_nb] &= ~((0x1u << (32 - bit_nb)) - 1);
258  } else {
259  bitmap[idx_nb] = 0;
260  }
261 
262  // handle zeros between idx_nb and idx_low (if gap exists)
263  for (ACE_CDR::ULong i = idx_nb + 1; i < idx_low; ++i) {
264  bitmap[i] = 0;
265  }
266 
267  // handle idx_nb ones
268  if (bit_low) {
269  if (idx_low > idx_nb) {
270  bitmap[idx_low] = (0x1u << (32 - bit_low)) - 1;
271  } else {
272  bitmap[idx_low] |= (0x1u << (32 - bit_low)) - 1;
273  }
274  } else {
275  bitmap[idx_low] = 0xFFFFFFFF;
276  }
277 
278  // handle ones between idx_low and idx_high (if gap exists)
279  for (ACE_CDR::ULong i = idx_low + 1; i < idx_high; ++i) {
280  bitmap[i] = 0xFFFFFFFF;
281  }
282 
283  // handle idx_high
284  if (idx_high > idx_low) {
285  bitmap[idx_high] = ~((0x1u << (31 - bit_high)) - 1);
286  } else if (bit_high < 31) {
287  bitmap[idx_high] &= ~((0x1u << (31 - bit_high)) - 1);
288  }
289 
290  num_bits = high + 1;
291  cumulative_bits_added += high - low + 1;
292  return !clamped;
293 }
ACE_UINT32 ULong

◆ high()

ACE_INLINE SequenceNumber OpenDDS::DCPS::DisjointSequence::high ( ) const

◆ insert() [1/4]

ACE_INLINE bool OpenDDS::DCPS::DisjointSequence::insert ( const SequenceRange range,
OPENDDS_VECTOR(SequenceRange)&  added 
)

All insert() methods return true upon modifying the set and false if the set already contained the SequenceNumber(s) that were to be inserted. This is the general form of insert() whereby the caller receives a list of sub-ranges of 'range' that were not already in the DisjointSequence. For example, given a DisjointSequence 'seq' containing (1, 2, 5, 9), calling seq.insert(SequenceRange(4, 12), v) returns true and yields v = [(4, 4), (6, 8), (10, 12)] and seq = (1, 2, 4, ..., 12).

Definition at line 77 of file DisjointSequence.inl.

References ACE_INLINE, and insert_i().

Referenced by OpenDDS::DCPS::WriteDataContainer::add_reader_acks(), OpenDDS::DCPS::ReliableSession::check_header(), OpenDDS::DCPS::RtpsUdpDataLink::durability_resend(), OpenDDS::DCPS::ReliableSession::expire_naks(), OpenDDS::DCPS::RtpsUdpDataLink::RtpsWriter::gather_nack_replies_i(), insert_filtered(), OpenDDS::DCPS::ReliableSession::nakack_received(), OpenDDS::DCPS::RtpsUdpDataLink::RtpsReader::process_gap_i(), OpenDDS::DCPS::ReliableSession::record_header_received(), OpenDDS::DCPS::SingleSendBuffer::resend_i(), OpenDDS::DCPS::ReliableSession::send_naks(), and OpenDDS::DCPS::ReliableSession::syn_hook().

79 {
80  return insert_i(range, &gaps);
81 }
bool insert_i(const SequenceRange &range, OPENDDS_VECTOR(SequenceRange) *gaps=0)

◆ insert() [2/4]

ACE_INLINE bool OpenDDS::DCPS::DisjointSequence::insert ( const SequenceRange range)

Insert all numbers between range.first and range.second (both inclusive).

Definition at line 71 of file DisjointSequence.inl.

References ACE_INLINE, and insert_i().

72 {
73  return insert_i(range);
74 }
bool insert_i(const SequenceRange &range, OPENDDS_VECTOR(SequenceRange) *gaps=0)

◆ insert() [3/4]

ACE_INLINE bool OpenDDS::DCPS::DisjointSequence::insert ( SequenceNumber  value)

Shorthand for "insert(SequenceRange(value, value))".

Definition at line 65 of file DisjointSequence.inl.

References ACE_INLINE, and insert_i().

66 {
68 }
const LogLevel::Value value
Definition: debug.cpp:61
bool insert_i(const SequenceRange &range, OPENDDS_VECTOR(SequenceRange) *gaps=0)
std::pair< SequenceNumber, SequenceNumber > SequenceRange

◆ insert() [4/4]

bool OpenDDS::DCPS::DisjointSequence::insert ( SequenceNumber  value,
ACE_CDR::ULong  num_bits,
const ACE_CDR::Long  bits[] 
)

Insert using the RTPS compact representation of a set. The three parameters, taken together, describe a set with each 1 bit starting at the msb of bits[0] and extending through num_bits (which are located at the next least significant bits of bits[0] followed by the msb of bits[1], etc.) indicating presence of the number (value + bit_index) in the set. bit_index is 0-based. Precondition: the array 'bits' has at least ceil(num_bits / 32) entries.

Definition at line 91 of file DisjointSequence.cpp.

References OpenDDS::DCPS::SequenceNumber::getValue(), insert_bitmap_range(), OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::ranges_, and sequences_.

93 {
94  bool inserted = false;
95  RangeSet::Container::iterator iter = sequences_.ranges_.end();
96  bool range_start_is_valid = false;
97  SequenceNumber::Value range_start = 0;
98  const SequenceNumber::Value val = value.getValue();
99 
100  // See RTPS v2.1 section 9.4.2.6 SequenceNumberSet
101  for (ACE_CDR::ULong i = 0, x = 0, bit = 0; i < num_bits; ++i, ++bit) {
102 
103  if (bit == 32) bit = 0;
104 
105  if (bit == 0) {
106  x = static_cast<ACE_CDR::ULong>(bits[i / 32]);
107  if (x == 0) {
108  // skip an entire Long if it's all 0's (adds 32 due to ++i)
109  i += 31;
110  bit = 31;
111  //FUTURE: this could be generalized with something like the x86 "bsr"
112  // instruction using compiler intrinsics, VC++ _BitScanReverse()
113  // and GCC __builtin_clz()
114  continue;
115  }
116  }
117 
118  if (x & (1 << (31 - bit))) {
119  if (!range_start_is_valid) {
120  range_start = val + i;
121  range_start_is_valid = true;
122  }
123  } else if (range_start_is_valid) {
124  // this is a "0" bit and we've previously seen a "1": insert a range
125  const SequenceNumber::Value to_insert = val + i - 1;
126  if (insert_bitmap_range(iter, SequenceRange(range_start, to_insert))) {
127  inserted = true;
128  }
129  range_start = 0;
130  range_start_is_valid = false;
131 
132  if (iter != sequences_.ranges_.end() && iter->second.getValue() != to_insert) {
133  // skip ahead: next gap in sequence must be past iter->second
134  ACE_CDR::ULong next_i = ACE_CDR::ULong(iter->second.getValue() - val);
135  bit = next_i % 32;
136  if (next_i / 32 != i / 32 && next_i < num_bits) {
137  x = static_cast<ACE_CDR::ULong>(bits[next_i / 32]);
138  }
139  i = next_i;
140  }
141  }
142  }
143 
144  if (range_start_is_valid) {
145  // iteration finished before we saw a "0" (inside a range)
146  SequenceNumber range_end = (value + num_bits).previous();
147  if (insert_bitmap_range(iter, SequenceRange(range_start, range_end))) {
148  return true;
149  }
150  }
151  return inserted;
152 }
const LogLevel::Value value
Definition: debug.cpp:61
bool insert_bitmap_range(RangeSet::Container::iterator &iter, const SequenceRange &sr)
ACE_UINT32 ULong
std::pair< SequenceNumber, SequenceNumber > SequenceRange

◆ insert_bitmap_range()

bool OpenDDS::DCPS::DisjointSequence::insert_bitmap_range ( RangeSet::Container::iterator iter,
const SequenceRange sr 
)
private

Definition at line 155 of file DisjointSequence.cpp.

References OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::empty(), high(), low(), OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::ranges_, and sequences_.

Referenced by insert().

157 {
158  // This is similar to insert_i(), except it doesn't need an O(log(n)) search
159  // of sequences_ every time to find the starting point, and it doesn't
160  // compute the 'gaps'.
161 
162  const SequenceNumber::Value previous = range.first.getValue() - 1,
163  next = range.second.getValue() + 1;
164 
165  if (!sequences_.empty()) {
166  if (iter == sequences_.ranges_.end()) {
167  iter = sequences_.ranges_.lower_bound(SequenceRange(0 /*ignored*/, previous));
168  } else {
169  // start where we left off last time and get the lower_bound(previous)
170  for (; iter != sequences_.ranges_.end() && iter->second < previous; ++iter) ;
171  }
172  }
173 
174  if (iter == sequences_.ranges_.end() || iter->first > next) {
175  // can't combine on either side, insert a new range
176  iter = sequences_.ranges_.insert(iter, range);
177  return true;
178  }
179 
180  if (iter->first <= range.first && iter->second >= range.second) {
181  // range is already covered by this DisjointSet
182  return false;
183  }
184 
185  // find the right-most (highest) range we can use
186  RangeSet::Container::iterator right = iter;
187  for (; right != sequences_.ranges_.end() && right->second < next; ++right) ;
188 
189  SequenceNumber high = range.second;
190  if (right != sequences_.ranges_.end()
191  && right->first <= next && right->first > range.first) {
192  high = right->second;
193  ++right;
194  }
195 
196  const SequenceNumber low = std::min(iter->first, range.first);
197  sequences_.ranges_.erase(iter, right);
198 
199  iter = sequences_.ranges_.insert(SequenceRange(low, high)).first;
200  return true;
201 }
std::pair< SequenceNumber, SequenceNumber > SequenceRange

◆ insert_filtered()

ACE_INLINE bool OpenDDS::DCPS::DisjointSequence::insert_filtered ( const SequenceRange range,
const DisjointSequence filter 
)

Insert the intersection of range and filter.

Definition at line 84 of file DisjointSequence.inl.

References ACE_INLINE, OpenDDS::DCPS::back_inserter(), OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::begin(), contains(), contains_any(), OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::end(), OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::has(), OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::has_any(), insert(), OPENDDS_END_VERSIONED_NAMESPACE_DECL, OPENDDS_VECTOR(), sequences_, and value.

85 {
86  for (SequenceNumber i = range.first; i <= range.second; ++i) {
87  if (filter.contains(i) && !insert(i)) {
88  return false;
89  }
90  }
91  return true;
92 }
bool insert(const SequenceRange &range, OPENDDS_VECTOR(SequenceRange)&added)

◆ insert_i()

bool OpenDDS::DCPS::DisjointSequence::insert_i ( const SequenceRange range,
OPENDDS_VECTOR(SequenceRange) *  gaps = 0 
)
private

Definition at line 28 of file DisjointSequence.cpp.

References OPENDDS_ASSERT, OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::ranges_, sequences_, and OpenDDS::DCPS::SequenceNumber::ZERO().

Referenced by insert().

30 {
31  OPENDDS_ASSERT(range.first <= range.second);
32 
33  typedef RangeSet::Container::iterator iter_t;
34 
35  iter_t range_above = sequences_.ranges_.lower_bound(range);
36  if (range_above != sequences_.ranges_.end()
37  && range_above->first <= range.first) {
38  return false; // already have this range, nothing to insert
39  }
40 
41  SequenceRange newRange = range;
42  if (range_above != sequences_.ranges_.end()
43  && ++SequenceNumber(newRange.second) >= range_above->first) {
44  // newRange overlaps range_above, replace range_above with modified newRange
45  newRange.second = range_above->second;
46  // move to just past this iterator for the erase
47  ++range_above;
48  }
49 
50  const SequenceNumber::Value previous = range.first.getValue() - 1;
51  // find the lower_bound for the SequenceNumber just before this range
52  // to see if any ranges need to combine
53  const iter_t range_below =
54  sequences_.ranges_.lower_bound(SequenceRange(1 /*ignored*/,
55  (previous > 0) ? previous
57  if (range_below != sequences_.ranges_.end()) {
58  // if low end falls inside of the range_below range
59  // then combine
60  if (newRange.first > range_below->first) {
61  newRange.first = range_below->first;
62  }
63 
64  if (gaps) {
65  iter_t gap_iter = range_below;
66  if (range.first < gap_iter->second) {
67  gaps->push_back(SequenceRange(range.first,
68  gap_iter->second.previous()));
69  }
70  SequenceNumber last_gap = gap_iter++->second;
71  for (; gap_iter != range_above; ++gap_iter) {
72  const SequenceNumber in_range =
73  std::min(gap_iter->first.previous().getValue(),
74  range.second.getValue());
75  gaps->push_back(SequenceRange(++last_gap, in_range));
76  last_gap = gap_iter->second;
77  }
78  if (last_gap < range.second) {
79  gaps->push_back(SequenceRange(++last_gap, range.second));
80  }
81  }
82 
83  sequences_.ranges_.erase(range_below, range_above);
84  }
85 
86  sequences_.ranges_.insert(newRange);
87  return true;
88 }
#define OPENDDS_ASSERT(C)
Definition: Definitions.h:66
static SequenceNumber ZERO()
std::pair< SequenceNumber, SequenceNumber > SequenceRange

◆ last_ack()

ACE_INLINE SequenceNumber OpenDDS::DCPS::DisjointSequence::last_ack ( ) const

◆ low()

ACE_INLINE SequenceNumber OpenDDS::DCPS::DisjointSequence::low ( ) const

◆ OPENDDS_VECTOR() [1/2]

OpenDDS::DCPS::DisjointSequence::OPENDDS_VECTOR ( SequenceRange  ) const

Returns missing ranges of SequenceNumbers (internal gaps in the sequence)

Referenced by fill_bitmap_range(), and insert_filtered().

◆ OPENDDS_VECTOR() [2/2]

OpenDDS::DCPS::DisjointSequence::OPENDDS_VECTOR ( SequenceRange  ) const

Returns a representation of the members of the sequence as a list of contiguous ranges (each Range is inclusive on both sides).

◆ reset()

ACE_INLINE void OpenDDS::DCPS::DisjointSequence::reset ( void  )

◆ to_bitmap()

bool OpenDDS::DCPS::DisjointSequence::to_bitmap ( ACE_CDR::Long  bitmap[],
ACE_CDR::ULong  length,
ACE_CDR::ULong num_bits,
ACE_CDR::ULong cumulative_bits_added,
bool  invert = false 
) const

Inverse of insert(value, num_bits, bits). Populates array of bitmap[length] with the bitmap of ranges above the cumulative_ack() value. Sets the number of significant (used) bits in num_bits. The 'base' of the bitmap is one larger than cumulative_ack(). Returns true if the entire DisjointSequence was able to fit in bitmap[]. Returning false is not an error, it's just that the higher-valued ranges didn't fit. If invert is true, the 1's in the bitmap represent the missing_sequence_ranges() instead of the present_sequence_ranges(). Precondition: the array 'bits' has 'length' entries allocated.

Definition at line 204 of file DisjointSequence.cpp.

References OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::begin(), cumulative_ack(), disjoint(), OpenDDS::DCPS::DisjointSequence::OrderedRanges< T >::end(), fill_bitmap_range(), OpenDDS::DCPS::SequenceNumber::getValue(), high(), low(), and sequences_.

Referenced by OpenDDS::DCPS::RtpsUdpDataLink::RtpsReader::gather_ack_nacks_i(), and OpenDDS::DCPS::RtpsUdpDataLink::RtpsWriter::gather_gaps_i().

206 {
207  // num_bits will be 1 more than the index of the last bit we wrote
208  num_bits = 0;
209  if (!disjoint()) {
210  return true;
211  }
212 
213  const SequenceNumber base = ++SequenceNumber(cumulative_ack());
214 
215  for (RangeSet::const_iterator iter = sequences_.begin(), prev = iter++;
216  iter != sequences_.end(); ++iter, ++prev) {
217 
218  ACE_CDR::ULong low = 0, high = 0;
219 
220  if (invert) {
221  low = ACE_CDR::ULong(prev->second.getValue() + 1 - base.getValue());
222  high = ACE_CDR::ULong(iter->first.getValue() - 1 - base.getValue());
223 
224  } else {
225  low = ACE_CDR::ULong(iter->first.getValue() - base.getValue());
226  high = ACE_CDR::ULong(iter->second.getValue() - base.getValue());
227  }
228 
229  if (!fill_bitmap_range(low, high, bitmap, length, num_bits, cumulative_bits_added)) {
230  return false;
231  }
232  }
233 
234  return true;
235 }
SequenceNumber cumulative_ack() const
ACE_UINT32 ULong
static bool fill_bitmap_range(ACE_CDR::ULong low, ACE_CDR::ULong high, ACE_CDR::Long bitmap[], ACE_CDR::ULong length, ACE_CDR::ULong &num_bits, ACE_CDR::ULong &cumulative_bits_added)
Set the bits in range [low, high] in the bitmap, updating num_bits.

Member Data Documentation

◆ sequences_

RangeSet OpenDDS::DCPS::DisjointSequence::sequences_
private

The documentation for this class was generated from the following files: