← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 3070: Fix incorrect user lists when DC++ is under heavy load

 

------------------------------------------------------------
revno: 3070
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Thu 2012-10-04 21:31:21 +0200
message:
  Fix incorrect user lists when DC++ is under heavy load
modified:
  changelog.txt
  dcpp/TaskQueue.h
  win32/DirectoryListingFrame.cpp
  win32/HubFrame.cpp
  win32/HubFrame.h
  win32/TransferView.cpp
  win32/TransferView.h


--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk

Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'changelog.txt'
--- changelog.txt	2012-10-01 18:25:44 +0000
+++ changelog.txt	2012-10-04 19:31:21 +0000
@@ -1,6 +1,7 @@
 * Perf improvements using lock-free queues, requires P6 CPUs (poy)
 * Reduce freezes when displaying file list dirs that contain lots of files (poy)
 * Less CPU consumption in large hubs (poy)
+* Fix incorrect user lists when DC++ is under heavy load (poy)
 
 -- 0.800 2012-09-16 --
 * [L#270107] Revamp favorite hub settings (poy)

=== modified file 'dcpp/TaskQueue.h'
--- dcpp/TaskQueue.h	2012-01-13 20:55:20 +0000
+++ dcpp/TaskQueue.h	2012-10-04 19:31:21 +0000
@@ -20,16 +20,15 @@
 #define DCPLUSPLUS_DCPP_TASK_H
 
 #include <memory>
-#include <utility>
 #include <vector>
 
+#include <boost/noncopyable.hpp>
+
 #include "CriticalSection.h"
 
 namespace dcpp {
 
-using std::make_pair;
 using std::pair;
-using std::swap;
 using std::unique_ptr;
 using std::vector;
 
@@ -37,36 +36,40 @@
 	virtual ~Task() { };
 };
 
-struct StringTask : public Task {
-	StringTask(const string& str_) : str(str_) { }
+struct StringTask : Task {
+	StringTask(string str) : str(move(str)) { }
 	string str;
 };
 
-class TaskQueue {
+template<bool threadsafe>
+class TaskQueue : private boost::noncopyable {
+protected:
+	typedef vector<pair<int, unique_ptr<Task>>> List;
+
 public:
-	typedef pair<int, unique_ptr<Task>> Pair;
-	typedef vector<Pair> List;
-
-	TaskQueue() {
-	}
-
-	~TaskQueue() {
+	virtual ~TaskQueue() {
 		clear();
 	}
 
-	void add(int type, std::unique_ptr<Task> && data) { Lock l(cs); tasks.push_back(make_pair(type, move(data))); }
-	void get(List& list) { Lock l(cs); swap(tasks, list); }
-	void clear() {
-		List tmp;
-		get(tmp);
-	}
-private:
-
-	TaskQueue(const TaskQueue&);
-	TaskQueue& operator=(const TaskQueue&);
-
+	void add(int type, std::unique_ptr<Task> && data) { tasks.emplace_back(type, move(data)); }
+	List get() { return move(tasks); }
+	void clear() { tasks.clear(); }
+
+private:
+	List tasks;
+};
+
+template<>
+class TaskQueue<true> : public TaskQueue<false> {
+	typedef TaskQueue<false> BaseType;
+
+public:
+	void add(int type, std::unique_ptr<Task> && data) { Lock l(cs); BaseType::add(type, move(data)); }
+	List get() { Lock l(cs); return BaseType::get(); }
+	void clear() { Lock l(cs); BaseType::clear(); }
+
+private:
 	CriticalSection cs;
-	List tasks;
 };
 
 } // namespace dcpp

=== modified file 'win32/DirectoryListingFrame.cpp'
--- win32/DirectoryListingFrame.cpp	2012-10-03 16:54:06 +0000
+++ win32/DirectoryListingFrame.cpp	2012-10-04 19:31:21 +0000
@@ -593,6 +593,8 @@
 	} catch(const ThreadException& e) {
 		error = Text::toT(e.getError());
 		finishLoad();
+		delete loader;
+		loader = nullptr;
 	}
 
 	initStatusText();

=== modified file 'win32/HubFrame.cpp'
--- win32/HubFrame.cpp	2012-10-01 18:25:44 +0000
+++ win32/HubFrame.cpp	2012-10-04 19:31:21 +0000
@@ -289,7 +289,6 @@
 
 HubFrame::~HubFrame() {
 	ClientManager::getInstance()->putClient(client);
-	clearTaskList();
 }
 
 bool HubFrame::preClosing() {
@@ -603,15 +602,9 @@
 	}
 }
 
-void HubFrame::addTask(Tasks s, const OnlineUser& u) {
-	tasks.add(s, unique_ptr<Task>(new UserTask(u)));
-	updateUsers = true;
-}
-
 void HubFrame::execTasks() {
 	updateUsers = false;
-	TaskQueue::List t;
-	tasks.get(t);
+	auto t = tasks.get();
 
 	HoldRedraw hold(users);
 
@@ -790,13 +783,9 @@
 
 void HubFrame::removeUser(const UserPtr& aUser) {
 	auto i = userMap.find(aUser);
-	if(i == userMap.end()) {
-		// Should never happen?
-		dcassert(i != userMap.end());
-		return;
-	}
+	dcassert(i != userMap.end());
 
-	UserInfo* ui = i->second;
+	auto ui = i->second;
 	if(!ui->isHidden() && showUsers->getChecked())
 		users->erase(ui);
 
@@ -920,21 +909,33 @@
 		setText(Text::toT(hubUrl));
 	});
 }
+
 void HubFrame::on(Connected, Client*) noexcept {
 	callAsync([this] { onConnected(); });
 }
+
 void HubFrame::on(ClientListener::UserUpdated, Client*, const OnlineUser& user) noexcept {
-	addTask(UPDATE_USER_JOIN, user);
+	auto task = new UserTask(user);
+	callAsync([this, task] {
+		tasks.add(UPDATE_USER_JOIN, unique_ptr<Task>(task));
+		updateUsers = true;
+	});
 }
+
 void HubFrame::on(UsersUpdated, Client*, const OnlineUserList& aList) noexcept {
 	for(auto& i: aList) {
-		tasks.add(UPDATE_USER, unique_ptr<Task>(new UserTask(*i)));
+		auto task = new UserTask(*i);
+		callAsync([this, task] { tasks.add(UPDATE_USER, unique_ptr<Task>(task)); });
 	}
-	updateUsers = true;
+	callAsync([this] { updateUsers = true; });
 }
 
 void HubFrame::on(ClientListener::UserRemoved, Client*, const OnlineUser& user) noexcept {
-	addTask(REMOVE_USER, user);
+	auto task = new UserTask(user);
+	callAsync([this, task] {
+		tasks.add(REMOVE_USER, unique_ptr<Task>(task));
+		updateUsers = true;
+	});
 }
 
 void HubFrame::on(Redirect, Client*, const string& line) noexcept {

=== modified file 'win32/HubFrame.h'
--- win32/HubFrame.h	2012-10-01 18:25:44 +0000
+++ win32/HubFrame.h	2012-10-04 19:31:21 +0000
@@ -105,7 +105,7 @@
 		UPDATE_USER_JOIN, UPDATE_USER, REMOVE_USER
 	};
 
-	struct UserTask : public Task {
+	struct UserTask : Task {
 		UserTask(const OnlineUser& ou);
 
 		HintedUser user;
@@ -174,7 +174,7 @@
 	bool resort;
 	bool confirmClose;
 
-	TaskQueue tasks; // todo get rid of TaskQueue
+	TaskQueue<false> tasks;
 
 	UserInfo* currentUser; /// only for situations when the user list is hidden
 
@@ -209,6 +209,8 @@
 	void initTimer();
 	bool runTimer();
 
+	void execTasks();
+
 	UserInfo* findUser(const tstring& nick);
 	bool updateUser(const UserTask& u);
 	void removeUser(const UserPtr& aUser);
@@ -259,9 +261,6 @@
 	// AspectUserInfo
 	UserInfoList selectedUsersImpl() const;
 
-	void addTask(Tasks s, const OnlineUser& u);
-	void execTasks();
-
 	void onConnected();
 	void onDisconnected();
 	void onGetPassword();

=== modified file 'win32/TransferView.cpp'
--- win32/TransferView.cpp	2012-09-10 22:14:27 +0000
+++ win32/TransferView.cpp	2012-10-04 19:31:21 +0000
@@ -476,8 +476,7 @@
 }
 
 void TransferView::execTasks() {
-	TaskQueue::List t;
-	tasks.get(t);
+	auto t = tasks.get();
 
 	bool sortConn = false;
 	bool sortDown = false;

=== modified file 'win32/TransferView.h'
--- win32/TransferView.h	2012-07-11 17:13:42 +0000
+++ win32/TransferView.h	2012-10-04 19:31:21 +0000
@@ -251,7 +251,7 @@
 
 	bool startup;
 
-	TaskQueue tasks; // todo get rid of TaskQueue
+	TaskQueue<true> tasks; // todo get rid of TaskQueue
 
 	ParamMap ucLineParams;