boost::uint32_t timestamp_history::add_sample(boost::uint32_t sample, bool step) { if (!m_initialized) { for (int i = 0; i < history_size; ++i) m_history[i] = sample; m_base = sample; m_initialized = true; } ++m_num_samples; // if sample is less than base, update the base // and update the history entry (because it will // be less than that too) if (compare_less_wrap(sample, m_base, TIME_MASK)) { m_base = sample; m_history[m_index] = sample; } // if sample is less than our history entry, update it else if (compare_less_wrap(sample, m_history[m_index], TIME_MASK)) { m_history[m_index] = sample; } boost::uint32_t ret = sample - m_base; // don't step base delay history unless we have at least 120 // samples. Anything less would suggest that the connection is // essentially idle and the samples are probably not very reliable if (step && m_num_samples > 120) { m_num_samples = 0; m_index = (m_index + 1) % history_size; m_history[m_index] = sample; // update m_base m_base = sample; for (int i = 0; i < history_size; ++i) { if (compare_less_wrap(m_history[i], m_base, TIME_MASK)) m_base = m_history[i]; } } return ret; }
void timestamp_history::adjust_base(int change) { TORRENT_ASSERT(m_initialized); m_base += change; // make sure this adjustment sticks by updating all history slots for (int i = 0; i < history_size; ++i) { if (compare_less_wrap(m_history[i], m_base, TIME_MASK)) m_history[i] = m_base; } }
void* packet_buffer_impl::at(index_type idx) const { INVARIANT_CHECK; if (idx >= m_first + m_capacity) return 0; if (compare_less_wrap(idx, m_first, 0xffff)) { return 0; } const int mask = int(m_capacity - 1); return m_storage[idx & mask]; }
void* packet_buffer_impl::remove(index_type idx) { INVARIANT_CHECK; // TODO: use compare_less_wrap for this comparison as well if (idx >= m_first + m_capacity) return 0; if (compare_less_wrap(idx, m_first, 0xffff)) return 0; const int mask = int(m_capacity - 1); void* old_value = m_storage[idx & mask]; m_storage[idx & mask] = 0; if (old_value) { --m_size; if (m_size == 0) m_last = m_first; } if (idx == m_first && m_size != 0) { ++m_first; for (std::uint32_t i = 0; i < m_capacity; ++i, ++m_first) if (m_storage[m_first & mask]) break; m_first &= 0xffff; } if (((idx + 1) & 0xffff) == m_last && m_size != 0) { --m_last; for (std::uint32_t i = 0; i < m_capacity; ++i, --m_last) if (m_storage[m_last & mask]) break; ++m_last; m_last &= 0xffff; } TORRENT_ASSERT_VAL(m_first <= 0xffff, m_first); return old_value; }
void* packet_buffer_impl::insert(index_type idx, void* value) { INVARIANT_CHECK; TORRENT_ASSERT_VAL(idx <= 0xffff, idx); // you're not allowed to insert NULLs! TORRENT_ASSERT(value); if (value == 0) return remove(idx); if (m_size != 0) { if (compare_less_wrap(idx, m_first, 0xffff)) { // Index comes before m_first. If we have room, we can simply // adjust m_first backward. std::size_t free_space = 0; for (index_type i = (m_first - 1) & (m_capacity - 1); i != (m_first & (m_capacity - 1)); i = (i - 1) & (m_capacity - 1)) { if (m_storage[i & (m_capacity - 1)]) break; ++free_space; } if (((m_first - idx) & 0xffff) > free_space) reserve(((m_first - idx) & 0xffff) + m_capacity - free_space); m_first = idx; } else if (idx >= m_first + m_capacity) { reserve(idx - m_first + 1); } else if (idx < m_first) { // We have wrapped. if (idx >= ((m_first + m_capacity) & 0xffff) && m_capacity < 0xffff) { reserve(m_capacity + (idx + 1 - ((m_first + m_capacity) & 0xffff))); } } if (compare_less_wrap(m_last, (idx + 1) & 0xffff, 0xffff)) m_last = (idx + 1) & 0xffff; } else { m_first = idx; m_last = (idx + 1) & 0xffff; } if (m_capacity == 0) reserve(16); void* old_value = m_storage[idx & (m_capacity - 1)]; m_storage[idx & (m_capacity - 1)] = value; if (m_size == 0) m_first = idx; // if we're just replacing an old value, the number // of elements in the buffer doesn't actually increase if (old_value == 0) ++m_size; TORRENT_ASSERT_VAL(m_first <= 0xffff, m_first); return old_value; }