linuxdcpp-team team mailing list archive
-
linuxdcpp-team team
-
Mailing list archive
-
Message #05077
[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;
}
}