diff --git a/include/libtorrent/bandwidth_manager.hpp b/include/libtorrent/bandwidth_manager.hpp index adba2d453..7ed9a50a3 100644 --- a/include/libtorrent/bandwidth_manager.hpp +++ b/include/libtorrent/bandwidth_manager.hpp @@ -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 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 c = e.peer; shared_ptr 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( qe.peer, t, hand_out_amount, now + bw_window_size)); TORRENT_ASSERT(amount == limit - m_current_quota);