← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2764: Load file lists in a separate thread

 

------------------------------------------------------------
revno: 2764
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Tue 2011-12-27 23:02:43 +0100
message:
  Load file lists in a separate thread
modified:
  changelog.txt
  dcpp/DirectoryListing.cpp
  dcpp/DirectoryListing.h
  win32/DirectoryListingFrame.cpp
  win32/DirectoryListingFrame.h
  win32/MainWindow.cpp


--
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	2011-12-27 15:21:02 +0000
+++ changelog.txt	2011-12-27 22:02:43 +0000
@@ -58,6 +58,7 @@
 * Plug memory leaks in list and tree controls (poy)
 * [L#735512] Switch to Boost.Atomic to solve freezes (poy)
 * [L#871975] Safer updating of the finished transfer window (poy)
+* Load file lists in a separate thread (bigmuscle, poy)
 
 -- 0.782 2011-03-05 --
 * Prevent a remote crash triggered via malformed user commands (poy)

=== modified file 'dcpp/DirectoryListing.cpp'
--- dcpp/DirectoryListing.cpp	2011-12-22 22:14:45 +0000
+++ dcpp/DirectoryListing.cpp	2011-12-27 22:02:43 +0000
@@ -39,6 +39,7 @@
 
 DirectoryListing::DirectoryListing(const HintedUser& aUser) :
 user(aUser),
+abort(false),
 root(new Directory(NULL, Util::emptyString, false, false))
 {
 }
@@ -96,16 +97,24 @@
 
 class ListLoader : public SimpleXMLReader::CallBack {
 public:
-	ListLoader(DirectoryListing::Directory* root, bool aUpdating) : cur(root), base("/"), inListing(false), updating(aUpdating) {
+	ListLoader(DirectoryListing* list, DirectoryListing::Directory* root, bool aUpdating) :
+	list(list),
+	cur(root),
+	base("/"),
+	inListing(false),
+	updating(aUpdating)
+	{
 	}
 
 	virtual ~ListLoader() { }
 
-	virtual void startTag(const string& name, StringPairList& attribs, bool simple);
-	virtual void endTag(const string& name, const string& data);
+	void startTag(const string& name, StringPairList& attribs, bool simple);
+	void endTag(const string& name, const string& data);
 
 	const string& getBase() const { return base; }
+
 private:
+	DirectoryListing* list;
 	DirectoryListing::Directory* cur;
 
 	StringMap params;
@@ -120,7 +129,7 @@
 }
 
 string DirectoryListing::loadXML(InputStream& is, bool updating) {
-	ListLoader ll(getRoot(), updating);
+	ListLoader ll(this, getRoot(), updating);
 
 	SimpleXMLReader(&ll).parse(is, SETTING(MAX_FILELIST_SIZE) ? (size_t)SETTING(MAX_FILELIST_SIZE)*1024*1024 : 0);
 
@@ -137,6 +146,10 @@
 static const string sTTH = "TTH";
 
 void ListLoader::startTag(const string& name, StringPairList& attribs, bool simple) {
+	if(list->getAbort()) {
+		throw Exception();
+	}
+
 	if(inListing) {
 		if(name == sFile) {
 			const string& n = getAttrib(attribs, sName, 0);

=== modified file 'dcpp/DirectoryListing.h'
--- dcpp/DirectoryListing.h	2011-12-23 21:15:27 +0000
+++ dcpp/DirectoryListing.h	2011-12-27 22:02:43 +0000
@@ -150,6 +150,7 @@
 	static UserPtr getUserFromFilename(const string& fileName);
 
 	GETSET(HintedUser, user, User);
+	GETSET(bool, abort, Abort);
 
 private:
 	friend class ListLoader;

=== modified file 'win32/DirectoryListingFrame.cpp'
--- win32/DirectoryListingFrame.cpp	2011-12-26 16:12:50 +0000
+++ win32/DirectoryListingFrame.cpp	2011-12-27 22:02:43 +0000
@@ -26,6 +26,7 @@
 #include <dcpp/QueueManager.h>
 #include <dcpp/ShareManager.h>
 #include <dcpp/ScopedFunctor.h>
+#include <dcpp/Thread.h>
 #include <dcpp/WindowInfo.h>
 
 #include <dwt/widgets/FolderDialog.h>
@@ -123,7 +124,7 @@
 	} else {
 		frame->setDirty(SettingsManager::BOLD_FL);
 		frame->onVisibilityChanged([frame, aDir](bool b) {
-			if(b && !frame->loaded && !WinUtil::mainWindow->closing())
+			if(b && !frame->loaded && !frame->loader && !WinUtil::mainWindow->closing())
 				frame->loadFile(aDir);
 		});
 	}
@@ -209,6 +210,8 @@
 
 DirectoryListingFrame::DirectoryListingFrame(TabViewPtr parent, const HintedUser& aUser, int64_t aSpeed) :
 	BaseType(parent, _T(""), IDH_FILE_LIST, IDI_DIRECTORY, false),
+	loader(0),
+	loading(0),
 	rebar(0),
 	pathBox(0),
 	grid(0),
@@ -391,17 +394,90 @@
 	lists.erase(dl->getUser());
 }
 
+class FileListLoader : public Thread {
+	typedef std::function<void ()> SuccessF;
+	typedef std::function<void (tstring)> ErrorF;
+
+public:
+	FileListLoader(DirectoryListing* dl, const string& path, SuccessF successF, ErrorF errorF) :
+	dl(dl),
+	path(path),
+	successF(successF),
+	errorF(errorF)
+	{
+	}
+
+	int run() {
+		try {
+			dl->loadFile(path);
+			ADLSearchManager::getInstance()->matchListing(*dl);
+			successF();
+		} catch(const Exception& e) {
+			errorF(Text::toT(e.getError()));
+		}
+		return 0;
+	}
+
+private:
+	DirectoryListing* dl;
+	const string& path;
+	SuccessF successF;
+	ErrorF errorF;
+};
+
 void DirectoryListingFrame::loadFile(const tstring& dir) {
-	loaded = true;
-
-	try {
-		dl->loadFile(path);
+	setEnabled(false);
+
+	{
+		// this control will cover the whole window.
+		Label::Seed seed(WinUtil::createIcon(IDI_OPEN_FILE_LIST, 32));
+		seed.style |= SS_CENTERIMAGE;
+		loading = addChild(seed);
+		WinUtil::setColor(loading);
+		layout();
+	}
+
+	loader = new FileListLoader(dl.get(), path, [this, dir] { callAsync([=] {
+		// success callback
+		delete loader;
+		loader = 0;
+		setEnabled(true);
+		loading->close(true);
+		loaded = true;
 		addRecent();
-		ADLSearchManager::getInstance()->matchListing(*dl);
 		refreshTree(dir);
-	} catch(const Exception& e) {
-		error = Text::toT(": " + e.getError());
-		updateTitle();
+		layout();
+		setDirty(SettingsManager::BOLD_FL);
+	}); }, [this](tstring s) { callAsync([=] {
+		// error callback
+		delete loader;
+		loader = 0;
+		setEnabled(true);
+		loading->close(true);
+		error = std::move(s);
+		updateTitle();
+		layout();
+		setDirty(SettingsManager::BOLD_FL);
+	}); });
+
+	onDestroy([this] {
+		if(loader) {
+			dl->setAbort(true);
+			loader->join();
+		}
+	});
+
+	try {
+		loader->start();
+
+	} catch(const ThreadException& e) {
+		delete loader;
+		loader = 0;
+		setEnabled(true);
+		loading->close(true);
+		error = Text::toT(e.getError());
+		updateTitle();
+		layout();
 	}
 
 	initStatusText();
@@ -413,7 +489,8 @@
 	try {
 		refreshTree(Text::toT(Util::toNmdcFile(dl->updateXML(txt))));
 	} catch(const Exception& e) {
-		error = Text::toT(": " + e.getError());
+		error = Text::toT(e.getError());
+		updateTitle();
 	}
 
 	initStatusText();
@@ -422,6 +499,12 @@
 void DirectoryListingFrame::layout() {
 	dwt::Rectangle r(getClientSize());
 
+	if(loading) {
+		loading->bringToFront();
+		loading->resize(r);
+		return;
+	}
+
 	auto y = rebar->refresh();
 	r.pos.y += y;
 	r.size.y -= y;
@@ -522,10 +605,11 @@
 
 void DirectoryListingFrame::updateTitle() {
 	tstring text = WinUtil::getNicks(dl->getUser());
-	if(error.empty())
+	if(error.empty()) {
 		text += _T(" - ") + WinUtil::getHubNames(dl->getUser()).first;
-	else
-		text += _T(": ") + error;
+	} else {
+		text = str(TF_("%1%: %2%") % text % error);
+	}
 
 	// bypass the recent item updater if the file list hasn't been loaded yet.
 	if(loaded) setText(text); else BaseType::setText(text);

=== modified file 'win32/DirectoryListingFrame.h'
--- win32/DirectoryListingFrame.h	2011-12-26 16:12:50 +0000
+++ win32/DirectoryListingFrame.h	2011-12-27 22:02:43 +0000
@@ -33,6 +33,8 @@
 
 using std::deque;
 
+class FileListLoader;
+
 class DirectoryListingFrame :
 	public MDIChildFrame<DirectoryListingFrame>,
 	public IRecent<DirectoryListingFrame>,
@@ -150,7 +152,10 @@
 	private:
 		tstring columns[COLUMN_LAST];
 	};
-	
+
+	FileListLoader* loader;
+	LabelPtr loading;
+
 	RebarPtr rebar;
 	ComboBoxPtr pathBox;
 

=== modified file 'win32/MainWindow.cpp'
--- win32/MainWindow.cpp	2011-12-26 14:09:44 +0000
+++ win32/MainWindow.cpp	2011-12-27 22:02:43 +0000
@@ -1208,12 +1208,10 @@
 
 class ListMatcher : public Thread {
 public:
-	ListMatcher(StringList files_) :
-		files(files_) {
+	ListMatcher(StringList&& files) : files(std::forward<StringList>(files)) { }
 
-	}
-	virtual int run() {
-		for (auto i = files.begin(); i != files.end(); ++i) {
+	int run() {
+		for(auto i = files.cbegin(), iend = files.cend(); i != iend; ++i) {
 			UserPtr u = DirectoryListing::getUserFromFilename(*i);
 			if (!u)
 				continue;
@@ -1226,21 +1224,22 @@
 				% Util::toString(ClientManager::getInstance()->getNicks(user))
 				% matched));
 			} catch(const Exception&) {
-
 			}
 		}
 		delete this;
 		return 0;
 	}
+
+private:
 	StringList files;
 };
 
 void MainWindow::handleMatchAll() {
-	ListMatcher* matcher = new ListMatcher(File::findFiles(Util::getListPath(), "*.xml*"));
+	auto matcher = new ListMatcher(File::findFiles(Util::getListPath(), "*.xml*"));
 	try {
 		matcher->start();
-	} catch(const ThreadException&) {
-		///@todo add error message
+	} catch(const ThreadException& e) {
+		LogManager::getInstance()->message(e.getError());
 		delete matcher;
 	}
 }