diff --git a/src/qtlibtorrent/torrentspeedmonitor.cpp b/src/qtlibtorrent/torrentspeedmonitor.cpp index f898e4acc..5cdb62d30 100644 --- a/src/qtlibtorrent/torrentspeedmonitor.cpp +++ b/src/qtlibtorrent/torrentspeedmonitor.cpp @@ -36,25 +36,82 @@ using namespace libtorrent; -template struct Sample { - Sample(const T down = 0, const T up = 0) : download(down), upload(up) {} - T download; - T upload; -}; +namespace { + + template struct Sample { + Sample() + : download() + , upload() + {} + + Sample(T download, T upload) + : download(download) + , upload(upload) + {} + + template + explicit Sample(Sample other) + : download(static_cast(other.download)) + , upload(static_cast(other.upload)) + {} + + T download; + T upload; + }; + + template + Sample& operator+=(Sample& lhs, Sample const& rhs) { + lhs.download += rhs.download; + lhs.upload += rhs.upload; + return lhs; + } + + template + Sample& operator-=(Sample& lhs, Sample const& rhs) { + lhs.download -= rhs.download; + lhs.upload -= rhs.upload; + return lhs; + } + + template + Sample operator+(Sample const& lhs, Sample const& rhs) { + return Sample(lhs.download + rhs.download, lhs.upload + rhs.upload); + } + + template + Sample operator-(Sample const& lhs, Sample const& rhs) { + return Sample(lhs.download - rhs.download, lhs.upload - rhs.upload); + } + + template + Sample operator*(Sample const& lhs, T rhs) { + return Sample(lhs.download * rhs, lhs.upload * rhs); + } + + template + Sample operator*(T lhs,Sample const& rhs) { + return Sample(lhs * rhs.download, lhs * rhs.upload); + } + + template + Sample operator/(Sample const& lhs, T rhs) { + return Sample(lhs.download / rhs, lhs.upload / rhs); + } +} class SpeedSample { public: SpeedSample() {} - void addSample(int speedDL, int speedUL); + void addSample(Sample const& item); Sample average() const; - void clear(); private: static const int max_samples = 30; private: QList > m_speedSamples; + Sample m_sum; }; TorrentSpeedMonitor::TorrentSpeedMonitor(QBtSession* session) @@ -68,11 +125,14 @@ TorrentSpeedMonitor::TorrentSpeedMonitor(QBtSession* session) TorrentSpeedMonitor::~TorrentSpeedMonitor() {} -void SpeedSample::addSample(int speedDL, int speedUL) +void SpeedSample::addSample(Sample const& item) { - m_speedSamples << Sample(speedDL, speedUL); - if (m_speedSamples.size() > max_samples) - m_speedSamples.removeFirst(); + m_speedSamples.push_back(item); + m_sum += Sample(item); + if (m_speedSamples.size() > max_samples) { + m_sum -= Sample(m_speedSamples.front()); + m_speedSamples.pop_front(); + } } Sample SpeedSample::average() const @@ -80,21 +140,7 @@ Sample SpeedSample::average() const if (m_speedSamples.empty()) return Sample(); - qlonglong sumDL = 0; - qlonglong sumUL = 0; - - foreach (const Sample& s, m_speedSamples) { - sumDL += s.download; - sumUL += s.upload; - } - - const qreal numSamples = m_speedSamples.size(); - return Sample(sumDL/numSamples, sumUL/numSamples); -} - -void SpeedSample::clear() -{ - m_speedSamples.clear(); + return Sample(m_sum) * (1. / m_speedSamples.size()); } void TorrentSpeedMonitor::removeSamples(const QString &hash) @@ -110,10 +156,14 @@ void TorrentSpeedMonitor::removeSamples(const QTorrentHandle& h) { qlonglong TorrentSpeedMonitor::getETA(const QString &hash, const libtorrent::torrent_status &status) const { - if (QTorrentHandle::is_paused(status) || !m_samples.contains(hash)) + if (QTorrentHandle::is_paused(status)) return MAX_ETA; - const Sample speed_average = m_samples[hash].average(); + QHash::const_iterator i = m_samples.find(hash); + if (i == m_samples.end()) + return MAX_ETA; + + const Sample speed_average = i->average(); if (QTorrentHandle::is_seed(status)) { if (!speed_average.upload) @@ -141,8 +191,10 @@ void TorrentSpeedMonitor::statsReceived(const stats_alert &stats) { Q_ASSERT(stats.interval >= 1000); - int speedDL = static_cast(static_cast(stats.transferred[stats_alert::download_payload]) * 1000 / stats.interval); - int speedUL = static_cast(static_cast(stats.transferred[stats_alert::upload_payload]) * 1000 / stats.interval); + Sample transferred(stats.transferred[stats_alert::download_payload], + stats.transferred[stats_alert::upload_payload]); - m_samples[misc::toQString(stats.handle.info_hash())].addSample(speedDL, speedUL); + Sample normalized = Sample(Sample(transferred) * 1000LL / static_cast(stats.interval)); + + m_samples[misc::toQString(stats.handle.info_hash())].addSample(normalized); }