diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index 4b154d7b6..dbbe4ac30 100644 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -66,6 +66,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/peer_info.hpp" #include "libtorrent/aux_/vector.hpp" #include "libtorrent/disk_interface.hpp" +#include "libtorrent/piece_picker.hpp" // for picker_options_t #include #include @@ -88,8 +89,8 @@ namespace libtorrent { namespace aux { - struct session_interface; - } + struct session_interface; +} struct pending_block { @@ -322,8 +323,7 @@ namespace aux { void on_metadata_impl(); - void picker_options(int o) - { m_picker_options = o; } + void picker_options(picker_options_t o) { m_picker_options = o; } int prefer_contiguous_blocks() const { @@ -333,7 +333,7 @@ namespace aux { bool on_parole() const; - int picker_options() const; + picker_options_t picker_options() const; void prefer_contiguous_blocks(int num) { m_prefer_contiguous_blocks = num; } @@ -1023,7 +1023,7 @@ namespace aux { // be augmented with flags controlled by other settings // like sequential download etc. These are here to // let plugins control flags that should always be set - int m_picker_options = 0; + picker_options_t m_picker_options{}; // the number of invalid piece-requests // we have got from this peer. If the request diff --git a/include/libtorrent/piece_picker.hpp b/include/libtorrent/piece_picker.hpp index ba5375ec9..06686d355 100644 --- a/include/libtorrent/piece_picker.hpp +++ b/include/libtorrent/piece_picker.hpp @@ -59,6 +59,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/aux_/typed_span.hpp" #include "libtorrent/alert_types.hpp" // for picker_flags_t #include "libtorrent/download_priority.hpp" +#include "libtorrent/flags.hpp" namespace libtorrent { @@ -72,6 +73,9 @@ namespace libtorrent { struct prio_index_tag_t {}; using prio_index_t = aux::strong_typedef; + struct picker_options_tag; + using picker_options_t = flags::bitfield_flag; + class TORRENT_EXTRA_EXPORT piece_picker { public: @@ -103,27 +107,30 @@ namespace libtorrent { #endif }; - enum options_t - { - // pick rarest first - rarest_first = 1, - // pick the most common first, or the last pieces if sequential - reverse = 2, - // only pick pieces exclusively requested from this peer - on_parole = 4, - // always pick partial pieces before any other piece - prioritize_partials = 8, - // pick pieces in sequential order - sequential = 16, - // treat pieces with priority 6 and below as filtered - // to trigger end-game mode until all prio 7 pieces are - // completed - time_critical_mode = 32, - // only expands pieces (when prefer contiguous blocks is set) - // within properly aligned ranges, not the largest possible - // range of pieces. - align_expanded_pieces = 64 - }; + // pick rarest first + static constexpr picker_options_t rarest_first = 0_bit; + + // pick the most common first, or the last pieces if sequential + static constexpr picker_options_t reverse = 1_bit; + + // only pick pieces exclusively requested from this peer + static constexpr picker_options_t on_parole = 2_bit; + + // always pick partial pieces before any other piece + static constexpr picker_options_t prioritize_partials = 3_bit; + + // pick pieces in sequential order + static constexpr picker_options_t sequential = 4_bit; + + // treat pieces with priority 6 and below as filtered + // to trigger end-game mode until all prio 7 pieces are + // completed + static constexpr picker_options_t time_critical_mode = 5_bit; + + // only expands pieces (when prefer contiguous blocks is set) + // within properly aligned ranges, not the largest possible + // range of pieces. + static constexpr picker_options_t align_expanded_pieces = 6_bit; struct downloading_piece { @@ -261,7 +268,7 @@ namespace libtorrent { picker_flags_t pick_pieces(typed_bitfield const& pieces , std::vector& interesting_blocks, int num_blocks , int prefer_contiguous_blocks, torrent_peer* peer - , int options, std::vector const& suggested_pieces + , picker_options_t options, std::vector const& suggested_pieces , int num_peers , counters& pc ) const; @@ -278,7 +285,7 @@ namespace libtorrent { , std::vector& backup_blocks2 , int num_blocks, int prefer_contiguous_blocks , torrent_peer* peer, std::vector const& ignore - , int options) const; + , picker_options_t options) const; // picks blocks only from downloading pieces int add_blocks_downloading(downloading_piece const& dp @@ -288,7 +295,7 @@ namespace libtorrent { , std::vector& backup_blocks2 , int num_blocks, int prefer_contiguous_blocks , torrent_peer* peer - , int options) const; + , picker_options_t options) const; // clears the peer pointer in all downloading pieces with this // peer pointer @@ -311,7 +318,7 @@ namespace libtorrent { // marks this piece-block as queued for downloading // options are flags from options_t. bool mark_as_downloading(piece_block block, torrent_peer* peer - , int options = 0); + , picker_options_t options = {}); // returns true if the block was marked as writing, // and false if the block is already finished or writing @@ -446,7 +453,7 @@ namespace libtorrent { std::pair expand_piece(piece_index_t piece, int whole_pieces , typed_bitfield const& have - , int options) const; + , picker_options_t options) const; // only defined when TORRENT_PICKER_LOG is defined, used for debugging // unit tests diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index ddf191d7c..b473cf741 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -859,14 +859,14 @@ namespace libtorrent { bool peer_connection::on_parole() const { return peer_info_struct() && peer_info_struct()->on_parole; } - int peer_connection::picker_options() const + picker_options_t peer_connection::picker_options() const { TORRENT_ASSERT(is_single_thread()); - int ret = m_picker_options; + picker_options_t ret = m_picker_options; std::shared_ptr t = m_torrent.lock(); TORRENT_ASSERT(t); - if (!t) return 0; + if (!t) return {}; if (t->num_time_critical_pieces() > 0) { diff --git a/src/piece_picker.cpp b/src/piece_picker.cpp index ff5649262..d8f47dcaa 100644 --- a/src/piece_picker.cpp +++ b/src/piece_picker.cpp @@ -69,6 +69,14 @@ namespace libtorrent { constexpr prio_index_t piece_picker::piece_pos::we_have_index; + constexpr picker_options_t piece_picker::rarest_first; + constexpr picker_options_t piece_picker::reverse; + constexpr picker_options_t piece_picker::on_parole; + constexpr picker_options_t piece_picker::prioritize_partials; + constexpr picker_options_t piece_picker::sequential; + constexpr picker_options_t piece_picker::time_critical_mode; + constexpr picker_options_t piece_picker::align_expanded_pieces; + piece_picker::piece_picker(int const blocks_per_piece , int const blocks_in_last_piece, int const total_num_pieces) : m_priority_boundaries(1, m_pieces.end_index()) @@ -1838,7 +1846,7 @@ namespace { picker_flags_t piece_picker::pick_pieces(typed_bitfield const& pieces , std::vector& interesting_blocks, int num_blocks , int prefer_contiguous_blocks, torrent_peer* peer - , int options, std::vector const& suggested_pieces + , picker_options_t options, std::vector const& suggested_pieces , int num_peers , counters& pc ) const @@ -2007,7 +2015,7 @@ namespace { } // in time critical mode, only pick high priority pieces - if ((options & time_critical_mode) == 0) + if (!(options & time_critical_mode)) { if (options & reverse) { @@ -2056,7 +2064,7 @@ namespace { // pieces. This is why reverse mode is disabled when we're in // time-critical mode, because all high priority pieces are at the // front of the list - if ((options & reverse) && (options & time_critical_mode) == 0) + if ((options & reverse) && !(options & time_critical_mode)) { for (int i = int(m_priority_boundaries.size()) - 1; i >= 0; --i) { @@ -2517,7 +2525,7 @@ get_out: , std::vector& backup_blocks2 , int num_blocks, int prefer_contiguous_blocks , torrent_peer* peer, std::vector const& ignore - , int options) const + , picker_options_t const options) const { TORRENT_ASSERT(is_piece_free(piece, pieces)); @@ -2588,7 +2596,7 @@ get_out: , std::vector& backup_blocks , std::vector& backup_blocks2 , int num_blocks, int prefer_contiguous_blocks - , torrent_peer* peer, int options) const + , torrent_peer* peer, picker_options_t const options) const { if (!pieces[dp.index]) return num_blocks; TORRENT_ASSERT(!m_piece_map[dp.index].filtered()); @@ -2628,7 +2636,7 @@ get_out: // to primarily request from a piece all by ourselves. if (prefer_contiguous_blocks > contiguous_blocks && !exclusive_active - && (options & on_parole) == 0) + && !(options & on_parole)) { if (int(backup_blocks2.size()) >= num_blocks) return num_blocks; @@ -2680,7 +2688,7 @@ get_out: std::pair piece_picker::expand_piece(piece_index_t const piece, int const contiguous_blocks - , typed_bitfield const& have, int const options) const + , typed_bitfield const& have, picker_options_t const options) const { if (contiguous_blocks == 0) return std::make_pair(piece, next(piece)); @@ -2935,7 +2943,7 @@ get_out: // options may be 0 or piece_picker::reverse // returns false if the block could not be marked as downloading bool piece_picker::mark_as_downloading(piece_block const block - , torrent_peer* peer, int const options) + , torrent_peer* peer, picker_options_t const options) { #ifdef TORRENT_PICKER_LOG std::cerr << "[" << this << "] " << "mark_as_downloading( {" @@ -3022,7 +3030,7 @@ get_out: // if we make a non-reverse request from a reversed piece, // undo the reverse state - if ((options & reverse) == 0 && p.reverse()) + if (!(options & reverse) && p.reverse()) { int prio = p.priority(this); // make it non-reverse diff --git a/src/torrent.cpp b/src/torrent.cpp index b16f6d26d..0c089d389 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -9599,7 +9599,7 @@ namespace libtorrent { // the backup lists picker->add_blocks(i->piece, c.get_bitfield(), interesting_blocks , backup1, backup2, blocks_in_piece, 0, c.peer_info_struct() - , ignore, 0); + , ignore, {}); interesting_blocks.insert(interesting_blocks.end() , backup1.begin(), backup1.end()); diff --git a/test/test_piece_picker.cpp b/test/test_piece_picker.cpp index 321282ee5..6fa384992 100644 --- a/test/test_piece_picker.cpp +++ b/test/test_piece_picker.cpp @@ -270,7 +270,7 @@ std::vector pick_pieces(std::shared_ptr const& p , int num_blocks , int prefer_contiguous_blocks , torrent_peer* peer_struct - , int options = piece_picker::rarest_first + , picker_options_t const options = piece_picker::rarest_first , std::vector const& suggested_pieces = empty_vector) { std::vector picked; @@ -284,7 +284,7 @@ std::vector pick_pieces(std::shared_ptr const& p } piece_index_t test_pick(std::shared_ptr const& p - , int options = piece_picker::rarest_first) + , picker_options_t const options = piece_picker::rarest_first) { std::vector picked = pick_pieces(p, "*******", 1, 0, nullptr , options, empty_vector); @@ -292,7 +292,7 @@ piece_index_t test_pick(std::shared_ptr const& p return picked[0].piece_index; } -const int options = piece_picker::rarest_first; +picker_options_t const options = piece_picker::rarest_first; counters pc; } // anonymous namespace @@ -715,7 +715,7 @@ TORRENT_TEST(random_picking_downloading_piece) // make sure the random piece picker can still pick partial pieces auto p = setup_picker("1111111", " ", "", "013700f"); auto picked = pick_pieces(p, " *** *", 1, 0, nullptr - , 0, empty_vector); + , {}, empty_vector); TEST_CHECK(int(picked.size()) > 0); TEST_CHECK(picked.front() == piece_block(piece_index_t(1), 1) || picked.front() == piece_block(piece_index_t(2), 2) @@ -728,7 +728,7 @@ TORRENT_TEST(random_picking_downloading_piece_prefer_contiguous) // even when prefer_contiguous_blocks is set auto p = setup_picker("1111111", " ", "", "013700f"); auto picked = pick_pieces(p, " *** *", 1, 4, nullptr - , 0, empty_vector); + , {}, empty_vector); TEST_CHECK(int(picked.size()) > 0); TEST_CHECK(picked.front() == piece_block(piece_index_t(1), 1) || picked.front() == piece_block(piece_index_t(2), 2) @@ -1070,13 +1070,13 @@ TORRENT_TEST(random_pick) auto p = setup_picker("1234567", " ", "1111122", ""); std::set random_pieces; for (int i = 0; i < 100; ++i) - random_pieces.insert(test_pick(p, 0)); + random_pieces.insert(test_pick(p, {})); TEST_CHECK(random_pieces.size() == 7); random_pieces.clear(); for (int i = 0; i < 7; ++i) { - piece_index_t const piece = test_pick(p, 0); + piece_index_t const piece = test_pick(p, {}); p->we_have(piece); random_pieces.insert(piece); }