summaryrefslogtreecommitdiffstats
path: root/libktorrent/net/networkthread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libktorrent/net/networkthread.cpp')
-rw-r--r--libktorrent/net/networkthread.cpp165
1 files changed, 165 insertions, 0 deletions
diff --git a/libktorrent/net/networkthread.cpp b/libktorrent/net/networkthread.cpp
new file mode 100644
index 0000000..40791c9
--- /dev/null
+++ b/libktorrent/net/networkthread.cpp
@@ -0,0 +1,165 @@
+/***************************************************************************
+ * Copyright (C) 2005 by Joris Guisson *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+#include <math.h>
+#include <util/functions.h>
+#include <util/log.h>
+#include "socketgroup.h"
+#include "socketmonitor.h"
+#include "networkthread.h"
+
+using namespace bt;
+
+namespace net
+{
+
+ NetworkThread::NetworkThread(SocketMonitor* sm)
+ : sm(sm),running(false)
+ {
+ groups.setAutoDelete(true);
+ groups.insert(0,new SocketGroup(0));
+ }
+
+
+ NetworkThread::~NetworkThread()
+ {}
+
+ void NetworkThread::run()
+ {
+ running = true;
+ prev_run_time = bt::Now();
+ while (running)
+ update();
+ }
+
+ void NetworkThread::addGroup(Uint32 gid,Uint32 limit)
+ {
+ // if group already exists, just change the limit
+ SocketGroup* g = groups.find(gid);
+ if (g)
+ {
+ g->setLimit(limit);
+ }
+ else
+ {
+ g = new SocketGroup(limit);
+ groups.insert(gid,g);
+ }
+ }
+
+ void NetworkThread::removeGroup(Uint32 gid)
+ {
+ // make sure the 0 group is never erased
+ if (gid != 0)
+ groups.erase(gid);
+ }
+
+ void NetworkThread::setGroupLimit(Uint32 gid,Uint32 limit)
+ {
+ SocketGroup* g = groups.find(gid);
+ if (g)
+ {
+ g->setLimit(limit);
+ }
+ }
+
+ Uint32 NetworkThread::doGroupsLimited(Uint32 num_ready,bt::TimeStamp now,Uint32 & allowance)
+ {
+ Uint32 num_still_ready = 0;
+
+ // this is one pass over all the groups
+ bt::PtrMap<Uint32,SocketGroup>::iterator itr = groups.begin();
+ while (itr != groups.end() && allowance > 0)
+ {
+ SocketGroup* g = itr->second;
+ if (g->numSockets() > 0)
+ {
+ Uint32 group_allowance = (Uint32)ceil(((double)g->numSockets() / num_ready) * allowance);
+
+ // lets not do to much and make sure we don't pass 0 to the socket group (0 is unlimited)
+ if (group_allowance > allowance || group_allowance == 0)
+ group_allowance = allowance;
+
+ Uint32 ga = group_allowance;
+
+ if (!doGroup(g,ga,now))
+ g->clear(); // group is done, so clear it
+ else
+ num_still_ready += g->numSockets(); // keep track of the number of sockets which are still ready
+
+ Uint32 done = group_allowance - ga;
+ if (allowance >= done)
+ allowance -= done;
+ else
+ allowance = 0;
+ }
+ itr++;
+ }
+
+ return num_still_ready > 0;
+ }
+
+ void NetworkThread::doGroups(Uint32 num_ready,bt::TimeStamp now,bt::Uint32 limit)
+ {
+ if (limit == 0)
+ {
+ Uint32 allowance = 0;
+ bt::PtrMap<Uint32,SocketGroup>::iterator itr = groups.begin();
+ while (itr != groups.end())
+ {
+ SocketGroup* g = itr->second;
+ if (g->numSockets() > 0)
+ {
+ g->calcAllowance(now);
+ doGroup(g,allowance,now);
+ g->clear();
+ }
+ itr++;
+ }
+ }
+ else
+ {
+ // calculate group allowance for each group
+ bt::PtrMap<Uint32,SocketGroup>::iterator itr = groups.begin();
+ while (itr != groups.end())
+ {
+ SocketGroup* g = itr->second;
+ g->calcAllowance(now);
+ itr++;
+ }
+
+ Uint32 allowance = (Uint32)ceil(1.02 * limit * (now - prev_run_time) * 0.001);
+
+ while (allowance > 0 && num_ready > 0)
+ {
+ // loop until nobody is ready anymore or the allowance is up
+ num_ready = doGroupsLimited(num_ready,now,allowance);
+ }
+
+ // make sure all groups are cleared
+ itr = groups.begin();
+ while (itr != groups.end())
+ {
+ SocketGroup* g = itr->second;
+ g->clear();
+ itr++;
+ }
+ }
+ }
+}