Torrent example: rewrite some very convoluted code
The old code iterated over the peer list, inserting active peers into a QSet, curiously not stopping to search for clients if it had already determined the peer to be active. It then iterated over the peers again, storing the indexes of the peers it had determined to be active in the first loop, in a QList. It _then_ iterated over the index list, in reverse, calling removeAt() on the peers list. <sean parent>That's a remove_if!</sean parent> The twist is, that only some maximum number of inactive peers should be removed, just enough to bring the number of peers below a predefined number. To solve, use a lambda that keeps track of the number of times it has returned true, returning false once the count drops to zero. We can't use a mutable lambda here, since the STL algorithms are allowed to copy the predicate as many times as they wish, and, indeed, remove_if is commonly implemented by calling find_if. But the standard guarantees exactly one application of the predicate per element, so we can assume that we're not called again on the same element, and therefore keep a reference to an external count. With this, what was a horrible mess becomes a single call to remove_if. Also change a while(--n) c.removeFirst() loop to a single call of range-erase. Change-Id: I6c6a54a1805e5b376800e1116e7aec643e95e4e1 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
parent
c85e6dc998
commit
54590c4f8a
|
|
@ -1484,30 +1484,26 @@ void TorrentClient::addToPeerList(const QList<TorrentPeer> &peerList)
|
|||
// of the peers that have no (or low) activity.
|
||||
int maxPeers = ConnectionManager::instance()->maxConnections() * 3;
|
||||
if (d->peers.size() > maxPeers) {
|
||||
auto tooMany = d->peers.size() - maxPeers;
|
||||
|
||||
// Find what peers are currently connected & active
|
||||
QSet<TorrentPeer *> activePeers;
|
||||
for (TorrentPeer *peer : qAsConst(d->peers)) {
|
||||
const auto firstNInactivePeers = [&tooMany, this] (TorrentPeer *peer) {
|
||||
if (!tooMany)
|
||||
return false;
|
||||
for (const PeerWireClient *client : qAsConst(d->connections)) {
|
||||
if (client->peer() == peer && (client->downloadSpeed() + client->uploadSpeed()) > 1024)
|
||||
activePeers << peer;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
--tooMany;
|
||||
return true;
|
||||
};
|
||||
// Remove inactive peers from the peer list until we're below
|
||||
// the max connections count.
|
||||
QList<int> toRemove;
|
||||
for (int i = 0; i < d->peers.size() && (d->peers.size() - toRemove.size()) > maxPeers; ++i) {
|
||||
if (!activePeers.contains(d->peers.at(i)))
|
||||
toRemove << i;
|
||||
}
|
||||
QListIterator<int> toRemoveIterator(toRemove);
|
||||
toRemoveIterator.toBack();
|
||||
while (toRemoveIterator.hasPrevious())
|
||||
d->peers.removeAt(toRemoveIterator.previous());
|
||||
|
||||
d->peers.erase(std::remove_if(d->peers.begin(), d->peers.end(),
|
||||
firstNInactivePeers),
|
||||
d->peers.end());
|
||||
// If we still have too many peers, remove the oldest ones.
|
||||
while (d->peers.size() > maxPeers)
|
||||
d->peers.takeFirst();
|
||||
d->peers.erase(d->peers.begin(), d->peers.begin() + tooMany);
|
||||
}
|
||||
|
||||
if (d->state != Paused && d->state != Stopping && d->state != Idle) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue