From 8cf6e9e37cf02cb393ef6b2882b13a10503ff358 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sat, 4 Mar 2017 23:45:07 -0500 Subject: [PATCH] use span<> to return the block_info for a piece (#1777) use span<> to return the block_info for a piece to improve range checks and loops --- include/libtorrent/aux_/typed_span.hpp | 18 ++-- include/libtorrent/piece_picker.hpp | 6 +- include/libtorrent/span.hpp | 2 +- src/peer_connection.cpp | 9 +- src/piece_picker.cpp | 135 ++++++++++++------------- src/torrent.cpp | 104 +++++++++---------- 6 files changed, 131 insertions(+), 143 deletions(-) diff --git a/include/libtorrent/aux_/typed_span.hpp b/include/libtorrent/aux_/typed_span.hpp index b78513d02..0ea644d4a 100644 --- a/include/libtorrent/aux_/typed_span.hpp +++ b/include/libtorrent/aux_/typed_span.hpp @@ -50,7 +50,7 @@ namespace libtorrent { namespace aux { // pull in constructors from base class using base::base; - auto operator[](IndexType idx) -> decltype(this->base::operator[](underlying_index())) + auto operator[](IndexType idx) const -> decltype(this->base::operator[](underlying_index())) { TORRENT_ASSERT(idx >= IndexType(0)); return this->base::operator[](std::size_t(static_cast(idx))); @@ -64,13 +64,13 @@ namespace libtorrent { namespace aux { template ::value>::type> - typed_span first(underlying_index n) + typed_span first(underlying_index n) const { TORRENT_ASSERT(n >= 0); return this->base::first(std::size_t(n)); } - typed_span first(std::size_t n) + typed_span first(std::size_t n) const { TORRENT_ASSERT(n <= std::size_t((std::numeric_limits::max)())); return this->base::first(n); @@ -78,13 +78,13 @@ namespace libtorrent { namespace aux { template ::value>::type> - typed_span last(underlying_index n) + typed_span last(underlying_index n) const { TORRENT_ASSERT(n >= 0); return this->base::last(std::size_t(n)); } - typed_span last(std::size_t n) + typed_span last(std::size_t n) const { TORRENT_ASSERT(n <= std::size_t((std::numeric_limits::max)())); return this->base::last(n); @@ -92,7 +92,7 @@ namespace libtorrent { namespace aux { template ::value>::type> - typed_span subspan(underlying_index offset) + typed_span subspan(underlying_index offset) const { TORRENT_ASSERT(offset >= 0); return this->base::subspan(std::size_t(offset)); @@ -100,20 +100,20 @@ namespace libtorrent { namespace aux { template ::value>::type> - typed_span subspan(underlying_index offset, underlying_index count) + typed_span subspan(underlying_index offset, underlying_index count) const { TORRENT_ASSERT(offset >= 0); TORRENT_ASSERT(count >= 0); return this->base::subspan(std::size_t(offset), std::size_t(count)); } - typed_span subspan(std::size_t offset) + typed_span subspan(std::size_t offset) const { TORRENT_ASSERT(offset <= std::size_t((std::numeric_limits::max)())); return this->base::subspan(offset); } - typed_span subspan(std::size_t offset, std::size_t count) + typed_span subspan(std::size_t offset, std::size_t count) const { TORRENT_ASSERT(offset <= std::size_t((std::numeric_limits::max)())); TORRENT_ASSERT(count <= std::size_t((std::numeric_limits::max)())); diff --git a/include/libtorrent/piece_picker.hpp b/include/libtorrent/piece_picker.hpp index f04052f28..5ba255340 100644 --- a/include/libtorrent/piece_picker.hpp +++ b/include/libtorrent/piece_picker.hpp @@ -56,6 +56,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/time.hpp" #include "libtorrent/piece_block.hpp" #include "libtorrent/aux_/vector.hpp" +#include "libtorrent/aux_/typed_span.hpp" namespace libtorrent { @@ -429,11 +430,12 @@ namespace libtorrent // return the array of block_info objects for a given downloading_piece. // this array has m_blocks_per_piece elements in it - block_info* blocks_for_piece(downloading_piece const& dp); - block_info const* blocks_for_piece(downloading_piece const& dp) const; + aux::typed_span blocks_for_piece(downloading_piece const& dp) const; private: + aux::typed_span mutable_blocks_for_piece(downloading_piece const& dp); + std::tuple requested_from( piece_picker::downloading_piece const& p , int num_blocks_in_piece, torrent_peer* peer) const; diff --git a/include/libtorrent/span.hpp b/include/libtorrent/span.hpp index f9b51843c..54ae174b5 100644 --- a/include/libtorrent/span.hpp +++ b/include/libtorrent/span.hpp @@ -105,7 +105,7 @@ namespace libtorrent return { data() + offset, count }; } - T& operator[](std::size_t const idx) + T& operator[](std::size_t const idx) const { TORRENT_ASSERT(idx < m_len); return m_ptr[idx]; diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 05b313801..fe0e013ed 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -3053,14 +3053,13 @@ namespace libtorrent #if TORRENT_USE_ASSERTS if (t->has_picker()) { - const std::vector& q + std::vector const& q = picker.get_download_queue(); - for (std::vector::const_iterator - i = q.begin(), end(q.end()); i != end; ++i) + for (piece_picker::downloading_piece const& dp : q) { - if (i->index != block_finished.piece_index) continue; - piece_picker::block_info* info = picker.blocks_for_piece(*i); + if (dp.index != block_finished.piece_index) continue; + auto const info = picker.blocks_for_piece(dp); TORRENT_ASSERT(info[block_finished.block_index].state == piece_picker::block_info::state_finished); } diff --git a/src/piece_picker.cpp b/src/piece_picker.cpp index 90d6eec1b..130e887e1 100644 --- a/src/piece_picker.cpp +++ b/src/piece_picker.cpp @@ -207,15 +207,14 @@ namespace libtorrent TORRENT_ASSERT(int(ret.info_idx) * m_blocks_per_piece + m_blocks_per_piece <= int(m_block_info.size())); - block_info* info = blocks_for_piece(ret); - for (int i = 0; i < m_blocks_per_piece; ++i) + for (auto& info : mutable_blocks_for_piece(ret)) { - info[i].num_peers = 0; - info[i].state = block_info::state_none; - info[i].peer = nullptr; + info.num_peers = 0; + info.state = block_info::state_none; + info.peer = nullptr; #if TORRENT_USE_ASSERTS - info[i].piece_index = piece; - info[i].peers.clear(); + info.piece_index = piece; + info.peers.clear(); #endif } downloading_iter = m_downloads[download_state].insert(downloading_iter, ret); @@ -283,18 +282,18 @@ namespace libtorrent *zero_prio = int(m_downloads[piece_pos::piece_zero_prio].size()); } - piece_picker::block_info* piece_picker::blocks_for_piece( + aux::typed_span piece_picker::mutable_blocks_for_piece( downloading_piece const& dp) { int idx = int(dp.info_idx) * m_blocks_per_piece; TORRENT_ASSERT(idx + m_blocks_per_piece <= int(m_block_info.size())); - return &m_block_info[idx]; + return { &m_block_info[idx], static_cast(blocks_in_piece(dp.index)) }; } - piece_picker::block_info const* piece_picker::blocks_for_piece( + aux::typed_span piece_picker::blocks_for_piece( downloading_piece const& dp) const { - return const_cast(this)->blocks_for_piece(dp); + return const_cast(this)->mutable_blocks_for_piece(dp); } #if TORRENT_USE_INVARIANT_CHECKS @@ -313,12 +312,11 @@ namespace libtorrent TORRENT_ASSERT(dp.index < next.index); TORRENT_ASSERT(int(dp.info_idx) * m_blocks_per_piece + m_blocks_per_piece <= int(m_block_info.size())); - block_info const* info = blocks_for_piece(dp); - for (int j = 0; j < m_blocks_per_piece; ++j) + for (auto const& bl : blocks_for_piece(dp)) { - if (info[j].peer) + if (bl.peer) { - torrent_peer* p = info[j].peer; + torrent_peer* p = bl.peer; TORRENT_ASSERT(p->in_use); TORRENT_ASSERT(p->connection == nullptr || static_cast(p->connection)->m_in_use); @@ -440,11 +438,10 @@ namespace libtorrent TORRENT_ASSERT(int(dp.info_idx) * m_blocks_per_piece + m_blocks_per_piece <= int(m_block_info.size())); #if TORRENT_USE_ASSERTS - block_info const* info = blocks_for_piece(dp); - for (int j = 0; j < m_blocks_per_piece; ++j) + for (auto const& bl : blocks_for_piece(dp)) { - if (!info[j].peer) continue; - torrent_peer* p = info[j].peer; + if (!bl.peer) continue; + torrent_peer* p = bl.peer; TORRENT_ASSERT(p->in_use); TORRENT_ASSERT(p->connection == nullptr || static_cast(p->connection)->m_in_use); @@ -467,32 +464,31 @@ namespace libtorrent int num_finished = 0; int num_writing = 0; int num_open = 0; - block_info const* info = blocks_for_piece(dp); - for (int k = 0; k < num_blocks; ++k) + for (auto const& bl : blocks_for_piece(dp)) { - TORRENT_ASSERT(info[k].piece_index == dp.index); - TORRENT_ASSERT(info[k].peer == nullptr - || info[k].peer->in_use); + TORRENT_ASSERT(bl.piece_index == dp.index); + TORRENT_ASSERT(bl.peer == nullptr + || bl.peer->in_use); - if (info[k].state == block_info::state_finished) + if (bl.state == block_info::state_finished) { ++num_finished; - TORRENT_ASSERT(info[k].num_peers == 0); + TORRENT_ASSERT(bl.num_peers == 0); } - else if (info[k].state == block_info::state_requested) + else if (bl.state == block_info::state_requested) { ++num_requested; - TORRENT_ASSERT(info[k].num_peers > 0); + TORRENT_ASSERT(bl.num_peers > 0); } - else if (info[k].state == block_info::state_writing) + else if (bl.state == block_info::state_writing) { ++num_writing; - TORRENT_ASSERT(info[k].num_peers == 0); + TORRENT_ASSERT(bl.num_peers == 0); } - else if (info[k].state == block_info::state_none) + else if (bl.state == block_info::state_none) { ++num_open; - TORRENT_ASSERT(info[k].num_peers == 0); + TORRENT_ASSERT(bl.num_peers == 0); } } @@ -2317,17 +2313,16 @@ get_out: TORRENT_ASSERT(piece_priority(dp->index) > 0); // fill in with blocks requested from other peers // as backups - int const num_blocks_in_piece = blocks_in_piece(dp->index); TORRENT_ASSERT(dp->requested > 0); - block_info const* binfo = blocks_for_piece(*dp); - for (int j = 0; j < num_blocks_in_piece; ++j) + int idx = -1; + for (auto const& info : blocks_for_piece(*dp)) { - block_info const& info = binfo[j]; + ++idx; TORRENT_ASSERT(info.peer == nullptr || info.peer->in_use); TORRENT_ASSERT(info.piece_index == dp->index); if (info.state != block_info::state_requested || info.peer == peer) continue; - temp.push_back(piece_block(dp->index, j)); + temp.push_back(piece_block(dp->index, idx)); } // are we done? if (!temp.empty()) @@ -2358,15 +2353,14 @@ get_out: && piece_priority(i.index) != priority_levels - 1) continue; - const int num_blocks_in_piece = blocks_in_piece(i.index); - block_info const* binfo = blocks_for_piece(i); - for (int j = 0; j < num_blocks_in_piece; ++j) + int idx = -1; + for (auto const& info : blocks_for_piece(i)) { - block_info const& info = binfo[j]; + ++idx; TORRENT_ASSERT(info.piece_index == i.index); if (info.state != block_info::state_none) continue; auto k = std::find(interesting_blocks.begin(), interesting_blocks.end() - , piece_block(i.index, j)); + , piece_block(i.index, idx)); if (k != interesting_blocks.end()) continue; std::fprintf(stderr, "interesting blocks:\n"); @@ -2379,7 +2373,7 @@ get_out: for (auto const& l : m_downloads[piece_pos::piece_downloading]) { - block_info const* binfo2 = blocks_for_piece(l); + auto const binfo2 = blocks_for_piece(l); std::fprintf(stderr, "%d : ", static_cast(l.index)); const int cnt = blocks_in_piece(l.index); for (int m = 0; m < cnt; ++m) @@ -2485,10 +2479,10 @@ get_out: int contiguous_blocks = 0; int max_contiguous = 0; int first_block = 0; - block_info const* binfo = blocks_for_piece(p); - for (int j = 0; j < num_blocks_in_piece; ++j) + int idx = -1; + for (auto const& info : blocks_for_piece(p)) { - piece_picker::block_info const& info = binfo[j]; + ++idx; TORRENT_ASSERT(info.peer == nullptr || info.peer->in_use); TORRENT_ASSERT(info.piece_index == p.index); if (info.state == piece_picker::block_info::state_none) @@ -2499,7 +2493,7 @@ get_out: if (contiguous_blocks > max_contiguous) { max_contiguous = contiguous_blocks; - first_block = j - contiguous_blocks; + first_block = idx - contiguous_blocks; } contiguous_blocks = 0; if (info.peer != peer) @@ -2631,7 +2625,7 @@ get_out: // pieces that only they have downloaded/requested from if ((options & on_parole) && !exclusive) return num_blocks; - block_info const* binfo = blocks_for_piece(dp); + auto const binfo = blocks_for_piece(dp); // we prefer whole blocks, but there are other peers // downloading from this piece and there aren't enough contiguous blocks @@ -2648,7 +2642,7 @@ get_out: for (int j = 0; j < num_blocks_in_piece; ++j) { // ignore completed blocks and already requested blocks - int block_idx = (j + first_block) % num_blocks_in_piece; + int const block_idx = (j + first_block) % num_blocks_in_piece; block_info const& info = binfo[block_idx]; TORRENT_ASSERT(info.piece_index == dp.index); if (info.state != block_info::state_none) continue; @@ -2660,7 +2654,7 @@ get_out: for (int j = 0; j < num_blocks_in_piece; ++j) { // ignore completed blocks and already requested blocks - int block_idx = (j + first_block) % num_blocks_in_piece; + int const block_idx = (j + first_block) % num_blocks_in_piece; block_info const& info = binfo[block_idx]; TORRENT_ASSERT(info.piece_index == dp.index); if (info.state != block_info::state_none) continue; @@ -2749,17 +2743,16 @@ get_out: std::vector::const_iterator i = find_dl_piece(state, index); TORRENT_ASSERT(i != m_downloads[state].end()); TORRENT_ASSERT(int(i->finished) <= m_blocks_per_piece); - int max_blocks = blocks_in_piece(index); + int const max_blocks = blocks_in_piece(index); if (int(i->finished) + int(i->writing) < max_blocks) return false; TORRENT_ASSERT(int(i->finished) + int(i->writing) == max_blocks); #if TORRENT_USE_INVARIANT_CHECKS - block_info const* info = blocks_for_piece(*i); - for (int k = 0; k < max_blocks; ++k) + for (auto const& info : blocks_for_piece(*i)) { - TORRENT_ASSERT(info[k].piece_index == index); - TORRENT_ASSERT(info[k].state == block_info::state_finished - || info[k].state == block_info::state_writing); + TORRENT_ASSERT(info.piece_index == index); + TORRENT_ASSERT(info.state == block_info::state_finished + || info.state == block_info::state_writing); } #endif @@ -2905,7 +2898,7 @@ get_out: TORRENT_ASSERT(i != m_downloads[state].end()); - block_info const* info = blocks_for_piece(*i); + auto const info = blocks_for_piece(*i); TORRENT_ASSERT(info[block.block_index].piece_index == block.piece_index); return info[block.block_index].state == block_info::state_requested; } @@ -2923,7 +2916,7 @@ get_out: , block.piece_index); TORRENT_ASSERT(i != m_downloads[state].end()); - block_info const* info = blocks_for_piece(*i); + auto const info = blocks_for_piece(*i); TORRENT_ASSERT(info[block.block_index].piece_index == block.piece_index); return info[block.block_index].state == block_info::state_finished || info[block.block_index].state == block_info::state_writing; @@ -2942,7 +2935,7 @@ get_out: , block.piece_index); TORRENT_ASSERT(i != m_downloads[p.download_queue()].end()); - block_info const* info = blocks_for_piece(*i); + auto const info = blocks_for_piece(*i); TORRENT_ASSERT(info[block.block_index].piece_index == block.piece_index); return info[block.block_index].state == block_info::state_finished; } @@ -2981,7 +2974,7 @@ get_out: if (prio >= 0 && !m_dirty) update(prio, p.index); auto const dp = add_download_piece(block.piece_index); - block_info* binfo = blocks_for_piece(*dp); + auto const binfo = mutable_blocks_for_piece(*dp); block_info& info = binfo[block.block_index]; TORRENT_ASSERT(info.piece_index == block.piece_index); info.state = block_info::state_requested; @@ -3005,7 +2998,7 @@ get_out: std::vector::iterator i = find_dl_piece(p.download_queue() , block.piece_index); TORRENT_ASSERT(i != m_downloads[p.download_queue()].end()); - block_info* binfo = blocks_for_piece(*i); + auto const binfo = mutable_blocks_for_piece(*i); block_info& info = binfo[block.block_index]; TORRENT_ASSERT(info.piece_index == block.piece_index); if (info.state == block_info::state_writing @@ -3068,7 +3061,7 @@ get_out: , block.piece_index); TORRENT_ASSERT(i != m_downloads[p.download_queue()].end()); - block_info const* binfo = blocks_for_piece(*i); + auto const binfo = blocks_for_piece(*i); block_info const& info = binfo[block.block_index]; TORRENT_ASSERT(&info >= &m_block_info[0]); TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size()); @@ -3126,7 +3119,7 @@ get_out: if (prio >= 0 && !m_dirty) update(prio, p.index); auto const dp = add_download_piece(block.piece_index); - block_info* binfo = blocks_for_piece(*dp); + auto const binfo = mutable_blocks_for_piece(*dp); block_info& info = binfo[block.block_index]; TORRENT_ASSERT(&info >= &m_block_info[0]); TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size()); @@ -3146,7 +3139,7 @@ get_out: std::vector::iterator i = find_dl_piece(p.download_queue() , block.piece_index); TORRENT_ASSERT(i != m_downloads[p.download_queue()].end()); - block_info* binfo = blocks_for_piece(*i); + auto const binfo = mutable_blocks_for_piece(*i); block_info& info = binfo[block.block_index]; TORRENT_ASSERT(&info >= &m_block_info[0]); @@ -3233,7 +3226,7 @@ get_out: std::vector::iterator i = find_dl_piece(state, block.piece_index); if (i == m_downloads[state].end()) return; - block_info* binfo = blocks_for_piece(*i); + auto const binfo = mutable_blocks_for_piece(*i); block_info& info = binfo[block.block_index]; TORRENT_ASSERT(&info >= &m_block_info[0]); TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size()); @@ -3300,7 +3293,7 @@ get_out: , block.piece_index); TORRENT_ASSERT(i != m_downloads[p.download_queue()].end()); - block_info* binfo = blocks_for_piece(*i); + auto const binfo = mutable_blocks_for_piece(*i); block_info& info = binfo[block.block_index]; if (info.state == block_info::state_finished) return; @@ -3370,7 +3363,7 @@ get_out: if (prio >= 0 && !m_dirty) update(prio, p.index); auto const dp = add_download_piece(block.piece_index); - block_info* binfo = blocks_for_piece(*dp); + auto const binfo = mutable_blocks_for_piece(*dp); block_info& info = binfo[block.block_index]; TORRENT_ASSERT(&info >= &m_block_info[0]); TORRENT_ASSERT(&info < &m_block_info[0] + m_block_info.size()); @@ -3392,7 +3385,7 @@ get_out: std::vector::iterator i = find_dl_piece(p.download_queue() , block.piece_index); TORRENT_ASSERT(i != m_downloads[p.download_queue()].end()); - block_info* binfo = blocks_for_piece(*i); + auto const binfo = mutable_blocks_for_piece(*i); block_info& info = binfo[block.block_index]; TORRENT_ASSERT(info.piece_index == block.piece_index); @@ -3451,7 +3444,7 @@ get_out: std::vector::const_iterator i = find_dl_piece(state, index); TORRENT_ASSERT(i != m_downloads[state].end()); - block_info const* binfo = blocks_for_piece(*i); + auto const binfo = blocks_for_piece(*i); for (int j = 0; j != num_blocks; ++j) { TORRENT_ASSERT(binfo[j].peer == nullptr @@ -3469,7 +3462,7 @@ get_out: , block.piece_index); TORRENT_ASSERT(block.block_index != piece_block::invalid.block_index); - block_info const* binfo = blocks_for_piece(*i); + auto const binfo = blocks_for_piece(*i); TORRENT_ASSERT(binfo[block.block_index].piece_index == block.piece_index); if (binfo[block.block_index].state == block_info::state_none) return nullptr; @@ -3502,7 +3495,7 @@ get_out: , block.piece_index); TORRENT_ASSERT(i != m_downloads[state].end()); - block_info* binfo = blocks_for_piece(*i); + auto const binfo = mutable_blocks_for_piece(*i); block_info& info = binfo[block.block_index]; TORRENT_ASSERT(info.peer == nullptr || info.peer->in_use); TORRENT_ASSERT(info.piece_index == block.piece_index); diff --git a/src/torrent.cpp b/src/torrent.cpp index 39bb3c80a..45bc3272c 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -1816,7 +1816,7 @@ namespace libtorrent for (auto const& p : dq) { - int num_blocks = m_picker->blocks_in_piece(p.index); + int const num_blocks = m_picker->blocks_in_piece(p.index); if (p.finished < num_blocks) continue; have_pieces.push_back(p.index); } @@ -1855,30 +1855,25 @@ namespace libtorrent { std::vector> ts = m_ses.find_collection(c); - for (std::vector>::iterator k = ts.begin() - , end2(ts.end()); k != end2; ++k) + for (auto const& t : ts) { // Only attempt to reuse files from torrents that are seeding. // TODO: this could be optimized by looking up which files are // complete and just look at those - if (!(*k)->is_seed()) continue; + if (!t->is_seed()) continue; - res.match((*k)->get_torrent_copy(), (*k)->save_path()); + res.match(t->get_torrent_copy(), t->save_path()); } } std::vector const& l = res.get_links(); if (!l.empty()) { - for (std::vector::const_iterator i = l.begin() - , end(l.end()); i != end; ++i) + for (auto const& i : l) { - if (!i->ti) continue; - - torrent_info const& ti = *i->ti; - std::string const& save_path = i->save_path; - links.push_back(combine_path(save_path - , ti.files().file_path(i->file_idx))); + if (!i.ti) continue; + links.push_back(combine_path(i.save_path + , i.ti->files().file_path(i.file_idx))); } } } @@ -3549,8 +3544,6 @@ namespace libtorrent std::vector dl_queue = m_picker->get_download_queue(); - const int blocks_per_piece = (piece_size + block_size() - 1) / block_size(); - // look at all unfinished pieces and add the completed // blocks to our 'done' counter for (auto i = dl_queue.begin(); i != dl_queue.end(); ++i) @@ -3566,20 +3559,21 @@ namespace libtorrent , [index](piece_picker::downloading_piece const& p) { return p.index == index; }) == 0); #endif - piece_picker::block_info* info = m_picker->blocks_for_piece(*i); - for (int j = 0; j < blocks_per_piece; ++j) + int idx = -1; + for (auto const& info : m_picker->blocks_for_piece(*i)) { + ++idx; #ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS - TORRENT_ASSERT(m_picker->is_finished(piece_block(index, j)) - == (info[j].state == piece_picker::block_info::state_finished)); + TORRENT_ASSERT(m_picker->is_finished(piece_block(index, idx)) + == (info.state == piece_picker::block_info::state_finished)); #endif - if (info[j].state == piece_picker::block_info::state_finished) + if (info.state == piece_picker::block_info::state_finished) { - corr += block_bytes_wanted(piece_block(index, j)); + corr += block_bytes_wanted(piece_block(index, idx)); } TORRENT_ASSERT(corr >= 0); - TORRENT_ASSERT(index != last_piece || j < m_picker->blocks_in_last_piece() - || info[j].state != piece_picker::block_info::state_finished); + TORRENT_ASSERT(index != last_piece || idx < m_picker->blocks_in_last_piece() + || info.state != piece_picker::block_info::state_finished); } st.total_done += corr; @@ -3642,10 +3636,9 @@ namespace libtorrent for (auto const& dp : dl_queue) { std::fprintf(stderr, " %d ", static_cast(dp.index)); - piece_picker::block_info* info = m_picker->blocks_for_piece(dp); - for (int j = 0; j < blocks_per_piece; ++j) + for (auto const& info : m_picker->blocks_for_piece(dp)) { - char const* state = info[j].state + char const* state = info.state == piece_picker::block_info::state_finished ? "1" : "0"; fputs(state, stderr); } @@ -6029,7 +6022,7 @@ namespace libtorrent int const num_bitmask_bytes = std::max(num_blocks_per_piece / 8, 1); - piece_picker::block_info const* info = m_picker->blocks_for_piece(dp); + auto const info = m_picker->blocks_for_piece(dp); for (int j = 0; j < num_bitmask_bytes; ++j) { char v = 0; @@ -6355,24 +6348,25 @@ namespace libtorrent TORRENT_ASSERT(counter * blocks_per_piece + pi.blocks_in_piece <= int(blk.size())); pi.blocks = &blk[std::size_t(counter * blocks_per_piece)]; int const piece_size = torrent_file().piece_size(i->index); - piece_picker::block_info const* info = m_picker->blocks_for_piece(*i); - for (int j = 0; j < pi.blocks_in_piece; ++j) + int idx = -1; + for (auto const& info : m_picker->blocks_for_piece(*i)) { - block_info& bi = pi.blocks[j]; - bi.state = info[j].state; - bi.block_size = j < pi.blocks_in_piece - 1 + ++idx; + block_info& bi = pi.blocks[idx]; + bi.state = info.state; + bi.block_size = idx < pi.blocks_in_piece - 1 ? aux::numeric_cast(block_size()) - : aux::numeric_cast(piece_size - (j * block_size())); + : aux::numeric_cast(piece_size - (idx * block_size())); bool complete = bi.state == block_info::writing || bi.state == block_info::finished; - if (info[j].peer == nullptr) + if (info.peer == nullptr) { bi.set_peer(tcp::endpoint()); bi.bytes_progress = complete ? bi.block_size : 0; } else { - torrent_peer* tp = info[j].peer; + torrent_peer* tp = info.peer; TORRENT_ASSERT(tp->in_use); if (tp->connection) { @@ -6382,7 +6376,7 @@ namespace libtorrent if (bi.state == block_info::requested) { auto pbp = peer->downloading_piece_progress(); - if (pbp.piece_index == i->index && pbp.block_index == j) + if (pbp.piece_index == i->index && pbp.block_index == idx) { bi.bytes_progress = aux::numeric_cast(pbp.bytes_downloaded); TORRENT_ASSERT(bi.bytes_progress <= bi.block_size); @@ -6404,7 +6398,7 @@ namespace libtorrent } } - pi.blocks[j].num_peers = info[j].num_peers; + pi.blocks[idx].num_peers = info.num_peers; } pi.piece_index = i->index; queue->push_back(pi); @@ -9405,29 +9399,29 @@ namespace libtorrent TORRENT_ALLOCA(busy_blocks, busy_block_t, blocks_in_piece); int busy_count = 0; - piece_picker::block_info const* info = picker->blocks_for_piece(pi); - // pick busy blocks from the piece - for (int k = 0; k < blocks_in_piece; ++k) + int idx = -1; + for (auto const& info : picker->blocks_for_piece(pi)) { + ++idx; // only consider blocks that have been requested // and we're still waiting for them - if (info[k].state != piece_picker::block_info::state_requested) + if (info.state != piece_picker::block_info::state_requested) continue; - piece_block b(piece, k); + piece_block b(piece, idx); // only allow a single additional request per block, in order // to spread it out evenly across all stalled blocks - if (int(info[k].num_peers) > timed_out) + if (int(info.num_peers) > timed_out) continue; - busy_blocks[busy_count].peers = info[k].num_peers; - busy_blocks[busy_count].index = k; + busy_blocks[busy_count].peers = info.num_peers; + busy_blocks[busy_count].index = idx; ++busy_count; #if TORRENT_DEBUG_STREAMING > 1 - std::printf(" [%d (%d)]", b.block_index, info[k].num_peers); + std::printf(" [%d (%d)]", b.block_index, info.num_peers); #endif } #if TORRENT_DEBUG_STREAMING > 1 @@ -10249,14 +10243,14 @@ namespace libtorrent std::int64_t offset = std::int64_t(static_cast(dp.index)) * m_torrent_file->piece_length(); file_index_t file = fs.file_index_at_offset(offset); - int num_blocks = m_picker->blocks_in_piece(dp.index); - piece_picker::block_info const* info = m_picker->blocks_for_piece(dp); - for (int k = 0; k < num_blocks; ++k) + int idx = -1; + for (auto const& info : m_picker->blocks_for_piece(dp)) { + ++idx; TORRENT_ASSERT(file < fs.end_file()); TORRENT_ASSERT(offset == std::int64_t(static_cast(dp.index)) * m_torrent_file->piece_length() - + k * block_size()); + + idx * block_size()); TORRENT_ASSERT(offset < m_torrent_file->total_size()); while (offset >= fs.file_offset(file) + fs.file_size(file)) { @@ -10266,21 +10260,21 @@ namespace libtorrent std::int64_t block = block_size(); - if (info[k].state == piece_picker::block_info::state_none) + if (info.state == piece_picker::block_info::state_none) { offset += block; continue; } - if (info[k].state == piece_picker::block_info::state_requested) + if (info.state == piece_picker::block_info::state_requested) { block = 0; - torrent_peer* p = info[k].peer; + torrent_peer* p = info.peer; if (p != nullptr && p->connection) { peer_connection* peer = static_cast(p->connection); auto pbp = peer->downloading_piece_progress(); - if (pbp.piece_index == dp.index && pbp.block_index == k) + if (pbp.piece_index == dp.index && pbp.block_index == idx) block = pbp.bytes_downloaded; TORRENT_ASSERT(block <= block_size()); } @@ -10318,7 +10312,7 @@ namespace libtorrent offset += left_over; TORRENT_ASSERT(offset == std::int64_t(static_cast(dp.index)) * m_torrent_file->piece_length() - + (k + 1) * block_size()); + + (idx + 1) * block_size()); } else {