OpenDDS::DCPS::DisjointSequence Class Reference

#include <DisjointSequence.h>

List of all members.

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 insert (const SequenceRange &range, OPENDDS_VECTOR(SequenceRange)&added)
bool insert (const SequenceRange &range)
 Insert all numbers between range.first and range.second (both inclusive).
bool insert (SequenceNumber value)
 Shorthand for "insert(SequenceRange(value, value))".
bool insert (SequenceNumber value, CORBA::ULong num_bits, const CORBA::Long bits[])
bool to_bitmap (CORBA::Long bitmap[], CORBA::ULong length, CORBA::ULong &num_bits, bool invert=false) const
 OPENDDS_VECTOR (SequenceRange) missing_sequence_ranges() const
 Returns missing ranges of SequenceNumbers (internal gaps in the sequence).
 OPENDDS_VECTOR (SequenceRange) present_sequence_ranges() const
void dump () const

Static Public Member Functions

static bool fill_bitmap_range (CORBA::ULong low, CORBA::ULong high, CORBA::Long bitmap[], CORBA::ULong length, CORBA::ULong &num_bits)
 Set the bits in range [low, high] in the bitmap, updating num_bits.

Private Types

typedef bool(*) SRCompare (const SequenceRange &, const SequenceRange &)

Private Member Functions

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

Static Private Member Functions

static void validate (const SequenceRange &range)
static bool SequenceRange_LessThan (const SequenceRange &lhs, const SequenceRange &rhs)

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

typedef bool(*) OpenDDS::DCPS::DisjointSequence::SRCompare(const SequenceRange &, const SequenceRange &) [private]

Definition at line 115 of file DisjointSequence.h.


Constructor & Destructor Documentation

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

Definition at line 52 of file DisjointSequence.inl.

00053   : sequences_(SequenceRange_LessThan)
00054 {
00055 }


Member Function Documentation

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

Definition at line 326 of file DisjointSequence.cpp.

00327 {
00328   RangeSet::const_iterator iter =
00329     sequences_.lower_bound(SequenceRange(0 /*ignored*/, value));
00330   return iter != sequences_.end() && iter->first <= value;
00331 }

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 24 of file DisjointSequence.inl.

References OpenDDS::RTPS::SEQUENCENUMBER_UNKNOWN, and sequences_.

Referenced by OpenDDS::DCPS::WriterInfo::ack_sequence(), OpenDDS::DCPS::WriteDataContainer::data_delivered(), OpenDDS::DCPS::RtpsUdpDataLink::deliver_held_data(), OpenDDS::DCPS::ReliableSession::deliver_held_data(), OpenDDS::DCPS::RtpsUdpDataLink::generate_nack_frags(), OpenDDS::DCPS::RtpsUdpDataLink::marshal_gaps(), OpenDDS::DCPS::ReliableSession::ready_to_deliver(), OpenDDS::DCPS::ReliableSession::send_naks(), OpenDDS::DCPS::WriteDataContainer::sequence_acknowledged(), OpenDDS::DCPS::RtpsUdpDataLink::WriterInfo::should_nack(), and to_bitmap().

00025 {
00026   return sequences_.empty()
00027     ? SequenceNumber::SEQUENCENUMBER_UNKNOWN()
00028     : sequences_.begin()->second;
00029 }

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

Objects with the disjoint() property have an internal gap in the inserted SequenceNumbers.

Definition at line 46 of file DisjointSequence.inl.

References sequences_.

Referenced by OpenDDS::DCPS::RtpsUdpDataLink::marshal_gaps(), OpenDDS::DCPS::ReliableSession::ready_to_deliver(), OpenDDS::DCPS::ReliableSession::send_naks(), OpenDDS::DCPS::RtpsUdpDataLink::WriterInfo::should_nack(), and to_bitmap().

00047 {
00048   return sequences_.size() > 1;
00049 }

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

Definition at line 343 of file DisjointSequence.cpp.

References sequences_.

Referenced by OpenDDS::DCPS::RtpsUdpDataLink::received(), OpenDDS::DCPS::RtpsUdpDataLink::send_nack_replies(), and OpenDDS::DCPS::ReliableSession::send_naks().

00344 {
00345   ACE_DEBUG((LM_DEBUG, "(%P|%t) DisjointSequence[%X]::dump Ranges of seen "
00346                        "SequenceNumbers:\n", this));
00347   for (RangeSet::const_iterator iter = sequences_.begin();
00348        iter != sequences_.end(); ++iter) {
00349     ACE_DEBUG((LM_DEBUG, "(%P|%t) DisjointSequence[%X]::dump\t%q-%q\n",
00350                this, iter->first.getValue(), iter->second.getValue()));
00351   }
00352 }

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

Definition at line 40 of file DisjointSequence.inl.

References sequences_.

Referenced by OpenDDS::DCPS::RtpsUdpDataLink::deliver_held_data(), OpenDDS::DCPS::ReliableSession::deliver_held_data(), OpenDDS::DCPS::RtpsUdpDataLink::generate_nack_frags(), OpenDDS::DCPS::RtpsUdpDataLink::RtpsReader::nack_durable(), OpenDDS::DCPS::RtpsUdpDataLink::process_heartbeat_i(), OpenDDS::DCPS::ReliableSession::ready_to_deliver(), OpenDDS::DCPS::RtpsUdpDataLink::received(), OpenDDS::DCPS::SingleSendBuffer::resend_fragments_i(), OpenDDS::DCPS::RtpsUdpDataLink::send_nack_replies(), and OpenDDS::DCPS::RtpsUdpDataLink::WriterInfo::should_nack().

00041 {
00042   return sequences_.empty();
00043 }

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

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

Definition at line 232 of file DisjointSequence.cpp.

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

00235 {
00236   bool clamped = false;
00237   CORBA::ULong idx_low = low / 32, bit_low = low % 32,
00238                idx_high = high / 32, bit_high = high % 32;
00239 
00240   if (idx_low >= length) {
00241     return false;
00242   }
00243   if (idx_high >= length) {
00244     // clamp to largest number we can represent
00245     high = length * 32 - 1;
00246     idx_high = length - 1;
00247     bit_high = high % 32;
00248     clamped = true;
00249   }
00250 
00251   // clear any full Longs between the last bit we wrote and idx_low
00252   for (CORBA::ULong i = (num_bits + 31) / 32; i < idx_low; ++i) {
00253     bitmap[i] = 0;
00254   }
00255 
00256   // write the Long at idx_low, preserving bits that may already be there
00257   CORBA::ULong x = bitmap[idx_low]; // use unsigned for bitwise operators
00258   //    clear the bits in x in the range [bit_last, bit_low)
00259   if (num_bits > 0) {
00260     const size_t bit_last = ((num_bits - 1) / 32 == idx_low)
00261                             ? ((num_bits - 1) % 32 + 1) : 0;
00262     for (size_t m = bit_last; m < bit_low; ++m) {
00263       x &= ~(1 << (31 - m));
00264     }
00265   } else {
00266     x = 0;
00267   }
00268   //    set the bits in x in the range [bit_low, limit)
00269   const size_t limit = (idx_high == idx_low) ? bit_high : 31;
00270   for (size_t b = bit_low; b <= limit; ++b) {
00271     x |= (1 << (31 - b));
00272   }
00273   bitmap[idx_low] = x;
00274 
00275   // any full Longs inside the current range are set to all 1's
00276   for (CORBA::ULong elt = idx_low + 1; elt < idx_high; ++elt) {
00277     bitmap[elt] = 0xFFFFFFFF;
00278   }
00279 
00280   if (idx_high > idx_low) {
00281     // write the Long at idx_high, no need to preserve bits since this is
00282     // the first iteration that's writing it
00283     x = 0;
00284     for (size_t b = 0; b <= bit_high; ++b) {
00285       x |= (1 << (31 - b));
00286     }
00287     bitmap[idx_high] = x;
00288   }
00289 
00290   num_bits = high + 1;
00291   return !clamped;
00292 }

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

Highest SequenceNumber in the set. Precondition: !empty()

Definition at line 18 of file DisjointSequence.inl.

References sequences_.

Referenced by OpenDDS::DCPS::WriterInfo::coherent_change_received(), OpenDDS::DCPS::RtpsUdpDataLink::generate_nack_frags(), insert_bitmap_range(), OpenDDS::DCPS::RtpsUdpDataLink::marshal_gaps(), OpenDDS::DCPS::RtpsUdpDataLink::received(), OpenDDS::DCPS::RtpsUdpDataLink::WriterInfo::should_nack(), and to_bitmap().

00019 {
00020   return sequences_.rbegin()->second;
00021 }

bool OpenDDS::DCPS::DisjointSequence::insert ( SequenceNumber  value,
CORBA::ULong  num_bits,
const CORBA::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 87 of file DisjointSequence.cpp.

References OpenDDS::DCPS::SequenceNumber::getValue(), insert_bitmap_range(), and sequences_.

00089 {
00090   bool inserted = false;
00091   RangeSet::iterator iter = sequences_.end();
00092   SequenceNumber::Value range_start = 0;
00093   const SequenceNumber::Value val = value.getValue();
00094 
00095   // See RTPS v2.1 section 9.4.2.6 SequenceNumberSet
00096   for (CORBA::ULong i = 0, x = 0, bit = 0; i < num_bits; ++i, ++bit) {
00097 
00098     if (bit == 32) bit = 0;
00099 
00100     if (bit == 0) {
00101       x = static_cast<CORBA::ULong>(bits[i / 32]);
00102       if (x == 0) {
00103         // skip an entire Long if it's all 0's (adds 32 due to ++i)
00104         i += 31;
00105         bit = 31;
00106         //FUTURE: this could be generalized with something like the x86 "bsr"
00107         //        instruction using compiler intrinsics, VC++ _BitScanReverse()
00108         //        and GCC __builtin_clz()
00109         continue;
00110       }
00111     }
00112 
00113     if (x & (1 << (31 - bit))) {
00114       if (range_start == 0) {
00115         range_start = val + i;
00116       }
00117 
00118     } else if (range_start != 0) {
00119       // this is a "0" bit and we've previously seen a "1": insert a range
00120       const SequenceNumber::Value to_insert = val + i - 1;
00121       if (insert_bitmap_range(iter, SequenceRange(range_start, to_insert))) {
00122         inserted = true;
00123       }
00124       range_start = 0;
00125 
00126       if (iter != sequences_.end() && iter->second.getValue() != to_insert) {
00127         // skip ahead: next gap in sequence must be past iter->second
00128         CORBA::ULong next_i = CORBA::ULong(iter->second.getValue() - val);
00129         bit = next_i % 32;
00130         if (next_i / 32 != i / 32) {
00131           x = static_cast<CORBA::ULong>(bits[next_i / 32]);
00132         }
00133         i = next_i;
00134       }
00135     }
00136   }
00137 
00138   if (range_start != 0) {
00139     // iteration finished before we saw a "0" (inside a range)
00140     SequenceNumber range_end = (value + num_bits).previous();
00141     if (insert_bitmap_range(iter, SequenceRange(range_start, range_end))) {
00142       return true;
00143     }
00144   }
00145   return inserted;
00146 }

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

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

Definition at line 64 of file DisjointSequence.inl.

References insert_i().

00065 {
00066   return insert_i(SequenceRange(value, value));
00067 }

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

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

Definition at line 70 of file DisjointSequence.inl.

References insert_i().

00071 {
00072   return insert_i(range);
00073 }

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 76 of file DisjointSequence.inl.

References insert_i().

Referenced by OpenDDS::DCPS::WriterInfo::ack_sequence(), OpenDDS::DCPS::ReliableSession::check_header(), OpenDDS::DCPS::WriteDataContainer::data_delivered(), OpenDDS::DCPS::ReliableSession::nakack_received(), OpenDDS::DCPS::RtpsUdpDataLink::process_heartbeat_i(), OpenDDS::DCPS::RtpsUdpDataLink::received(), OpenDDS::DCPS::ReliableSession::record_header_received(), OpenDDS::DCPS::RtpsUdpDataLink::send_nack_replies(), OpenDDS::DCPS::RtpsUdpDataLink::send_nackfrag_replies(), OpenDDS::DCPS::ReliableSession::send_naks(), and OpenDDS::DCPS::ReliableSession::syn_hook().

00078 {
00079   return insert_i(range, &gaps);
00080 }

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

Definition at line 149 of file DisjointSequence.cpp.

References high(), low(), and sequences_.

Referenced by insert().

00151 {
00152   // This is similar to insert_i(), except it doesn't need an O(log(n)) search
00153   // of sequences_ every time to find the starting point, and it doesn't
00154   // compute the 'gaps'.
00155 
00156   const SequenceNumber::Value previous = range.first.getValue() - 1,
00157     next = range.second.getValue() + 1;
00158 
00159   if (!sequences_.empty()) {
00160     if (iter == sequences_.end()) {
00161       iter = sequences_.lower_bound(SequenceRange(1 /*ignored*/, previous));
00162     } else {
00163       // start where we left off last time and get the lower_bound(previous)
00164       for (; iter != sequences_.end() && iter->second < previous; ++iter) ;
00165     }
00166   }
00167 
00168   if (iter == sequences_.end() || iter->first > next) {
00169     // can't combine on either side, insert a new range
00170     iter = sequences_.insert(iter, range);
00171     return true;
00172   }
00173 
00174   if (iter->first <= range.first && iter->second >= range.second) {
00175     // range is already covered by this DisjointSet
00176     return false;
00177   }
00178 
00179   // find the right-most (highest) range we can use
00180   RangeSet::iterator right = iter;
00181   for (; right != sequences_.end() && right->second < next; ++right) ;
00182 
00183   SequenceNumber high = range.second;
00184   if (right != sequences_.end()
00185       && right->first <= next && right->first > range.first) {
00186     high = right->second;
00187     ++right;
00188   }
00189 
00190   const SequenceNumber low = std::min(iter->first, range.first);
00191   sequences_.erase(iter, right);
00192 
00193   iter = sequences_.insert(SequenceRange(low, high)).first;
00194   return true;
00195 }

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

Definition at line 26 of file DisjointSequence.cpp.

References sequences_, validate(), and OpenDDS::DCPS::SequenceNumber::ZERO().

Referenced by insert().

00028 {
00029   validate(range);
00030 
00031   RangeSet::iterator range_above = sequences_.lower_bound(range);
00032   if (range_above != sequences_.end()
00033       && range_above->first <= range.first) {
00034     return false; // already have this range, nothing to insert
00035   }
00036 
00037   SequenceRange newRange = range;
00038   if (range_above != sequences_.end()
00039       && ++SequenceNumber(newRange.second) >= range_above->first) {
00040     // newRange overlaps range_above, replace range_above with modified newRange
00041     newRange.second = range_above->second;
00042     // move to just past this iterator for the erase
00043     ++range_above;
00044   }
00045 
00046   const SequenceNumber::Value previous = range.first.getValue() - 1;
00047   // find the lower_bound for the SequenceNumber just before this range
00048   // to see if any ranges need to combine
00049   const RangeSet::iterator range_below =
00050     sequences_.lower_bound(SequenceRange(1 /*ignored*/,
00051                                          (previous > 0) ? previous
00052                                          : SequenceNumber::ZERO()));
00053   if (range_below != sequences_.end()) {
00054     // if low end falls inside of the range_below range
00055     // then combine
00056     if (newRange.first > range_below->first) {
00057       newRange.first = range_below->first;
00058     }
00059 
00060     if (gaps) {
00061       RangeSet::iterator gap_iter = range_below;
00062       if (range.first < gap_iter->second) {
00063         gaps->push_back(SequenceRange(range.first,
00064                                       gap_iter->second.previous()));
00065       }
00066       SequenceNumber last_gap = gap_iter++->second;
00067       for (; gap_iter != range_above; ++gap_iter) {
00068         const SequenceNumber in_range =
00069           std::min(gap_iter->first.previous().getValue(),
00070                    range.second.getValue());
00071         gaps->push_back(SequenceRange(++last_gap, in_range));
00072         last_gap = gap_iter->second;
00073       }
00074       if (last_gap < range.second) {
00075         gaps->push_back(SequenceRange(++last_gap, range.second));
00076       }
00077     }
00078 
00079     sequences_.erase(range_below, range_above);
00080   }
00081 
00082   sequences_.insert(newRange);
00083   return true;
00084 }

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

Gets the low end of the highest contiguous range, may be thought of as the inverse of cumulative_ack(). If empty(), returns SEQUENCENUMBER_UNKNOWN.

Definition at line 32 of file DisjointSequence.inl.

References OpenDDS::RTPS::SEQUENCENUMBER_UNKNOWN, and sequences_.

Referenced by OpenDDS::DCPS::RtpsUdpDataLink::generate_nack_frags().

00033 {
00034   return sequences_.empty()
00035     ? SequenceNumber::SEQUENCENUMBER_UNKNOWN()
00036     : sequences_.rbegin()->first;
00037 }

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

Lowest SequenceNumber in the set. Precondition: !empty()

Definition at line 12 of file DisjointSequence.inl.

References sequences_.

Referenced by OpenDDS::DCPS::RtpsUdpDataLink::deliver_held_data(), OpenDDS::DCPS::ReliableSession::deliver_held_data(), insert_bitmap_range(), OpenDDS::DCPS::RtpsUdpDataLink::marshal_gaps(), OpenDDS::DCPS::RtpsUdpDataLink::RtpsReader::nack_durable(), OpenDDS::DCPS::RtpsUdpDataLink::process_heartbeat_i(), OpenDDS::DCPS::ReliableSession::ready_to_deliver(), OpenDDS::DCPS::RtpsUdpDataLink::received(), OpenDDS::DCPS::ReliableSession::send_naks(), and to_bitmap().

00013 {
00014   return sequences_.begin()->first;
00015 }

typedef OpenDDS::DCPS::DisjointSequence::OPENDDS_SET_CMP ( SequenceRange  ,
SRCompare   
) [private]

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).

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

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

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

Definition at line 58 of file DisjointSequence.inl.

References sequences_.

Referenced by OpenDDS::DCPS::WriterInfo::reset_coherent_info(), and OpenDDS::DCPS::ReliableSession::syn_hook().

00059 {
00060   sequences_.clear();
00061 }

static bool OpenDDS::DCPS::DisjointSequence::SequenceRange_LessThan ( const SequenceRange lhs,
const SequenceRange rhs 
) [inline, static, private]

Definition at line 109 of file DisjointSequence.h.

00111   {
00112     return lhs.second < rhs.second;
00113   }

bool OpenDDS::DCPS::DisjointSequence::to_bitmap ( CORBA::Long  bitmap[],
CORBA::ULong  length,
CORBA::ULong &  num_bits,
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 198 of file DisjointSequence.cpp.

References cumulative_ack(), disjoint(), fill_bitmap_range(), OpenDDS::DCPS::SequenceNumber::getValue(), high(), low(), and sequences_.

Referenced by OpenDDS::DCPS::RtpsUdpDataLink::marshal_gaps().

00200 {
00201   // num_bits will be 1 more than the index of the last bit we wrote
00202   num_bits = 0;
00203   if (!disjoint()) {
00204     return true;
00205   }
00206 
00207   const SequenceNumber base = ++SequenceNumber(cumulative_ack());
00208 
00209   for (RangeSet::const_iterator iter = sequences_.begin(), prev = iter++;
00210        iter != sequences_.end(); ++iter, ++prev) {
00211 
00212     CORBA::ULong low = 0, high = 0;
00213 
00214     if (invert) {
00215       low = CORBA::ULong(prev->second.getValue() + 1 - base.getValue());
00216       high = CORBA::ULong(iter->first.getValue() - 1 - base.getValue());
00217 
00218     } else {
00219       low = CORBA::ULong(iter->first.getValue() - base.getValue());
00220       high = CORBA::ULong(iter->second.getValue() - base.getValue());
00221     }
00222 
00223     if (!fill_bitmap_range(low, high, bitmap, length, num_bits)) {
00224       return false;
00225     }
00226   }
00227 
00228   return true;
00229 }

void OpenDDS::DCPS::DisjointSequence::validate ( const SequenceRange range  )  [static, private]

Definition at line 334 of file DisjointSequence.cpp.

Referenced by insert_i().

00335 {
00336   if (range.first > range.second) {
00337     throw std::runtime_error("SequenceNumber range invalid, range must "
00338                              "be ascending.");
00339   }
00340 }


Member Data Documentation

RangeSet OpenDDS::DCPS::DisjointSequence::sequences_ [private]

Definition at line 117 of file DisjointSequence.h.

Referenced by cumulative_ack(), disjoint(), dump(), empty(), high(), insert(), insert_bitmap_range(), insert_i(), last_ack(), low(), reset(), and to_bitmap().


The documentation for this class was generated from the following files:
Generated on Fri Feb 12 20:06:16 2016 for OpenDDS by  doxygen 1.4.7