forked from premiere/premiere-libtorrent
fixed race condition in bandwidth limiter
This commit is contained in:
parent
29ccb9220b
commit
a49cb42345
|
@ -123,6 +123,7 @@ struct bandwidth_manager
|
|||
#ifndef NDEBUG
|
||||
bool is_queued(PeerConnection const* peer) const
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
for (typename queue_t::const_iterator i = m_queue.begin()
|
||||
, end(m_queue.end()); i != end; ++i)
|
||||
{
|
||||
|
@ -133,6 +134,7 @@ struct bandwidth_manager
|
|||
|
||||
bool is_in_history(PeerConnection const* peer) const
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
for (typename history_t::const_iterator i
|
||||
= m_history.begin(), end(m_history.end()); i != end; ++i)
|
||||
{
|
||||
|
@ -152,12 +154,13 @@ struct bandwidth_manager
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
TORRENT_ASSERT(blk > 0);
|
||||
TORRENT_ASSERT(!is_queued(peer.get()));
|
||||
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
TORRENT_ASSERT(!peer->ignore_bandwidth_limits());
|
||||
|
||||
// make sure this peer isn't already in line
|
||||
// waiting for bandwidth
|
||||
TORRENT_ASSERT(!is_queued(peer.get()));
|
||||
TORRENT_ASSERT(peer->max_assignable_bandwidth(m_channel) > 0);
|
||||
|
||||
boost::shared_ptr<Torrent> t = peer->associated_torrent().lock();
|
||||
|
@ -185,7 +188,7 @@ struct bandwidth_manager
|
|||
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
|
||||
std::cerr << " req_bandwidht. m_queue.size() = " << m_queue.size() << std::endl;
|
||||
#endif
|
||||
if (!m_queue.empty()) hand_out_bandwidth();
|
||||
if (!m_queue.empty()) hand_out_bandwidth(l);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
@ -229,6 +232,7 @@ private:
|
|||
|
||||
TORRENT_ASSERT(!m_history.empty());
|
||||
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
ptime now(time_now());
|
||||
while (!m_history.empty() && m_history.back().expires_at <= now)
|
||||
{
|
||||
|
@ -238,8 +242,10 @@ private:
|
|||
TORRENT_ASSERT(m_current_quota >= 0);
|
||||
intrusive_ptr<PeerConnection> c = e.peer;
|
||||
shared_ptr<Torrent> t = e.tor.lock();
|
||||
l.unlock();
|
||||
if (!c->is_disconnecting()) c->expire_bandwidth(m_channel, e.amount);
|
||||
if (t) t->expire_bandwidth(m_channel, e.amount);
|
||||
l.lock();
|
||||
}
|
||||
|
||||
// now, wait for the next chunk to expire
|
||||
|
@ -253,10 +259,10 @@ private:
|
|||
// since some bandwidth just expired, it
|
||||
// means we can hand out more (in case there
|
||||
// are still consumers in line)
|
||||
if (!m_queue.empty()) hand_out_bandwidth();
|
||||
if (!m_queue.empty()) hand_out_bandwidth(l);
|
||||
}
|
||||
|
||||
void hand_out_bandwidth()
|
||||
void hand_out_bandwidth(boost::mutex::scoped_lock& l)
|
||||
{
|
||||
// if we're already handing out bandwidth, just return back
|
||||
// to the loop further down on the callstack
|
||||
|
@ -267,9 +273,7 @@ private:
|
|||
|
||||
ptime now(time_now());
|
||||
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
int limit = m_limit;
|
||||
l.unlock();
|
||||
|
||||
// available bandwidth to hand out
|
||||
int amount = limit - m_current_quota;
|
||||
|
@ -301,7 +305,9 @@ private:
|
|||
if (!t) continue;
|
||||
if (qe.peer->is_disconnecting())
|
||||
{
|
||||
l.unlock();
|
||||
t->expire_bandwidth(m_channel, qe.max_block_size);
|
||||
l.lock();
|
||||
TORRENT_ASSERT(amount == limit - m_current_quota);
|
||||
continue;
|
||||
}
|
||||
|
@ -371,8 +377,10 @@ private:
|
|||
TORRENT_ASSERT(amount == limit - m_current_quota);
|
||||
amount -= hand_out_amount;
|
||||
TORRENT_ASSERT(hand_out_amount <= qe.max_block_size);
|
||||
l.unlock();
|
||||
t->assign_bandwidth(m_channel, hand_out_amount, qe.max_block_size);
|
||||
qe.peer->assign_bandwidth(m_channel, hand_out_amount);
|
||||
l.lock();
|
||||
add_history_entry(history_entry<PeerConnection, Torrent>(
|
||||
qe.peer, t, hand_out_amount, now + bw_window_size));
|
||||
TORRENT_ASSERT(amount == limit - m_current_quota);
|
||||
|
|
Loading…
Reference in New Issue