linuxdcpp-team team mailing list archive
-
linuxdcpp-team team
-
Mailing list archive
-
Message #06125
[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 3073: destroy tooltips, reduce CPU use due to status updates
------------------------------------------------------------
revno: 3073
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Thu 2012-10-11 18:17:05 +0200
message:
destroy tooltips, reduce CPU use due to status updates
modified:
changelog.txt
dcpp/TaskQueue.h
dwt/include/dwt/resources/Handle.h
dwt/include/dwt/widgets/Button.h
dwt/include/dwt/widgets/ToolTip.h
dwt/src/widgets/Button.cpp
dwt/src/widgets/Splitter.cpp
dwt/src/widgets/StatusBar.cpp
win32/DirectoryListingFrame.cpp
win32/DirectoryListingFrame.h
win32/QueueFrame.cpp
win32/QueueFrame.h
win32/RichTextBox.cpp
win32/UsersFrame.cpp
win32/UsersFrame.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-04 19:57:25 +0000
+++ changelog.txt 2012-10-11 16:17:05 +0000
@@ -1,7 +1,8 @@
* 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)
+* Less CPU consumption with large hubs/queues/lists (poy)
* Fix incorrect user lists when DC++ is under heavy load (poy)
+* Plug resource leaks (poy)
-- 0.801 2012-09-29 --
* [L#1029629] Prevent crashes on heavy use by updating Boost.Atomic
=== modified file 'dcpp/TaskQueue.h'
--- dcpp/TaskQueue.h 2012-10-04 19:31:21 +0000
+++ dcpp/TaskQueue.h 2012-10-11 16:17:05 +0000
@@ -47,10 +47,6 @@
typedef vector<pair<int, unique_ptr<Task>>> List;
public:
- virtual ~TaskQueue() {
- clear();
- }
-
void add(int type, std::unique_ptr<Task> && data) { tasks.emplace_back(type, move(data)); }
List get() { return move(tasks); }
void clear() { tasks.clear(); }
=== modified file 'dwt/include/dwt/resources/Handle.h'
--- dwt/include/dwt/resources/Handle.h 2012-05-13 11:48:45 +0000
+++ dwt/include/dwt/resources/Handle.h 2012-10-11 16:17:05 +0000
@@ -56,17 +56,11 @@
template<typename Policy>
class Handle;
-template<typename Policy>
-void intrusive_ptr_add_ref(Handle<Policy>* resource);
-
-template<typename Policy>
-void intrusive_ptr_release(Handle<Policy>* resource);
-
/**
* Ref-counted base class for resources - nothing stops you from using this one the stack as well
*/
template<typename Policy>
-class Handle : protected Policy, public boost::noncopyable {
+class Handle : protected Policy, boost::noncopyable {
public:
typedef typename Policy::HandleType HandleType;
@@ -88,8 +82,8 @@
}
private:
- friend void intrusive_ptr_add_ref<Policy>(Handle<Policy>*);
- friend void intrusive_ptr_release<Policy>(Handle<Policy>*);
+ friend void intrusive_ptr_add_ref(Handle<Policy>* p) { ++p->ref; }
+ friend void intrusive_ptr_release(Handle<Policy>* p) { if(--p->ref == 0) { delete p; } }
HandleType h;
bool owned;
@@ -97,17 +91,6 @@
long ref;
};
-template<typename Policy>
-void intrusive_ptr_add_ref(Handle<Policy>* resource) {
- ::InterlockedIncrement(&resource->ref);
-}
-
-template<typename Policy>
-void intrusive_ptr_release(Handle<Policy>* resource) {
- if(::InterlockedDecrement(&resource->ref) == 0) {
- delete resource;
- }
-}
-
-}
+}
+
#endif /*RESOURCE_H_*/
=== modified file 'dwt/include/dwt/widgets/Button.h'
--- dwt/include/dwt/widgets/Button.h 2012-01-13 20:55:20 +0000
+++ dwt/include/dwt/widgets/Button.h 2012-10-11 16:17:05 +0000
@@ -108,11 +108,6 @@
return Message(WM_COMMAND, MAKEWPARAM(0, BN_DBLCLK));
}
-inline Button::Button(Widget* parent) :
- BaseType(parent, ChainingDispatcher::superClass<ThisType>())
-{
-}
-
}
#endif /*ASPECTBUTTON_H_*/
=== modified file 'dwt/include/dwt/widgets/ToolTip.h'
--- dwt/include/dwt/widgets/ToolTip.h 2012-06-02 12:48:00 +0000
+++ dwt/include/dwt/widgets/ToolTip.h 2012-10-11 16:17:05 +0000
@@ -33,6 +33,7 @@
#define DWT_ToolTip_H_
#include "../Widget.h"
+#include "../aspects/Closeable.h"
#include "../aspects/CustomDraw.h"
#include "../aspects/Enabled.h"
#include "../aspects/Fonts.h"
@@ -44,6 +45,7 @@
class ToolTip :
public Widget,
+ public aspects::Closeable<ToolTip>,
public aspects::CustomDraw<ToolTip, NMTTCUSTOMDRAW>,
public aspects::Enabled<ToolTip>,
public aspects::Fonts<ToolTip>,
@@ -87,12 +89,12 @@
void onGetTip(F f);
- /// Actually creates the Toolbar
- /** You should call WidgetFactory::createToolbar if you instantiate class
- * directly. <br>
- * Only if you DERIVE from class you should call this function directly.
- */
- void create( const Seed & cs = Seed() );
+ /** Create the ToolTip control.
+ @note Be careful about tooltip destruction! Unlike other widgets, tooltips aren't regular
+ children; they are instead "owned" by their parent (Windows terminology). Therefore, unless the
+ owner doesn't have any non-owner parent, Windows won't destroy the tooltip control when the
+ owner is destroyed; so make sure you explicitly destroy it by calling the "close" method. */
+ void create(const Seed& cs = Seed());
protected:
// Constructor Taking pointer to parent
=== modified file 'dwt/src/widgets/Button.cpp'
--- dwt/src/widgets/Button.cpp 2012-01-13 20:55:20 +0000
+++ dwt/src/widgets/Button.cpp 2012-10-11 16:17:05 +0000
@@ -44,6 +44,11 @@
{
}
+Button::Button(Widget* parent) :
+ BaseType(parent, ChainingDispatcher::superClass<ThisType>())
+{
+}
+
void Button::create(const Seed& cs) {
BaseType::create(cs);
setFont(cs.font);
@@ -62,14 +67,8 @@
Point Button::getPreferredSize() {
SIZE size = { 0 };
- if(sendMessage(BCM_GETIDEALSIZE, 0, reinterpret_cast<LPARAM>(&size))) {
- return Point(size.cx, size.cy);
- }
-
- // BCM_GETIDEALSIZE fails on comctrl < 6, so resort to the standard method
- UpdateCanvas c(this);
- auto select(c.select(*getFont()));
- return c.getTextExtent(getText()) + Point(3, 2) + Point(::GetSystemMetrics(SM_CYFIXEDFRAME) * 2, ::GetSystemMetrics(SM_CXFIXEDFRAME) * 2);
+ sendMessage(BCM_GETIDEALSIZE, 0, reinterpret_cast<LPARAM>(&size));
+ return Point(size.cx, size.cy);
}
}
=== modified file 'dwt/src/widgets/Splitter.cpp'
--- dwt/src/widgets/Splitter.cpp 2012-06-29 19:22:25 +0000
+++ dwt/src/widgets/Splitter.cpp 2012-10-11 16:17:05 +0000
@@ -53,7 +53,9 @@
onMouseMove([this](const MouseEvent& mouseEvent) { return handleMouseMove(mouseEvent); });
onLeftMouseUp([this](const MouseEvent&) { return handleLButtonUp(); });
- WidgetCreator<ToolTip>::create(this, ToolTip::Seed())->setText(Texts::get(Texts::resize));
+ auto tip = WidgetCreator<ToolTip>::create(this, ToolTip::Seed());
+ tip->setText(Texts::get(Texts::resize));
+ onDestroy([tip] { tip->close(); });
}
SplitterContainerPtr Splitter::getParent() const {
=== modified file 'dwt/src/widgets/StatusBar.cpp'
--- dwt/src/widgets/StatusBar.cpp 2012-03-03 19:33:45 +0000
+++ dwt/src/widgets/StatusBar.cpp 2012-10-11 16:17:05 +0000
@@ -70,6 +70,7 @@
tip = WidgetCreator<ToolTip>::create(this, ToolTip::Seed());
tip->setTool(this, [this](tstring& text) { handleToolTip(text); });
+ onDestroy([this] { tip->close(); tip = nullptr; });
}
void StatusBar::setSize(unsigned part, unsigned size) {
=== modified file 'win32/DirectoryListingFrame.cpp'
--- win32/DirectoryListingFrame.cpp 2012-10-04 19:31:21 +0000
+++ win32/DirectoryListingFrame.cpp 2012-10-11 16:17:05 +0000
@@ -224,6 +224,7 @@
BaseType(parent, _T(""), IDH_FILE_LIST, IDI_DIRECTORY, false),
loader(nullptr),
loading(0),
+ useCache(true),
rebar(0),
pathBox(0),
grid(0),
@@ -425,7 +426,7 @@
}
#ifdef _DEBUG
-#define step(x) dcdebug("Loading file list <%s>: " x "\n", parent.path.c_str());
+#define step(x) dcdebug("Loading file list <%s>: " x "\n", parent.path.c_str())
#else
#define step(x)
#endif
@@ -452,16 +453,16 @@
successF();
} catch(const Exception& e) {
- step("error")
+ step("error");
errorF(Text::toT(e.getError()));
}
/* now that the file list is being displayed, prepare individual file items, hoping that
they will have been processed by the time the user wants them to be displayed. */
- try {
+ if(parent.useCache) { try {
step("caching files");
cacheFiles(parent.dl->getRoot());
- } catch(const Exception&) { }
+ } catch(const Exception&) { } }
step("file cache done; destroying thread");
endF();
@@ -1257,27 +1258,34 @@
void DirectoryListingFrame::changeDir(DirectoryListing::Directory* d) {
updating = true;
+ if(!useCache) { files->forEachT([](ItemInfo* i) { if(i->type == ItemInfo::FILE) { delete i; } }); } /// @todo also delete when closing the window
files->clear();
- auto cache = fileCache.find(d);
- if(cache == fileCache.end()) {
- if(!loader || !loader->updateCache(d)) {
- /* dang, the file cache isn't ready for this directory. fill it on-the-fly; might
- freeze the interface (this is the operation the file cache is meant to prevent). */
- list<ItemInfo> list;
- for(auto& i: d->files) {
- list.emplace_back(i);
- }
- fileCache.emplace(d, move(list));
- }
- cache = fileCache.find(d);
- }
-
for(auto& i: d->directories) {
files->insert(files->size(), getCachedDir(i));
}
- for(auto& i: cache->second) {
- files->insert(files->size(), &i);
+
+ if(useCache) {
+ auto cache = fileCache.find(d);
+ if(cache == fileCache.end()) {
+ if(!loader || !loader->updateCache(d)) {
+ /* dang, the file cache isn't ready for this directory. fill it on-the-fly; might
+ freeze the interface (this is the operation the file cache is meant to prevent). */
+ list<ItemInfo> list;
+ for(auto& i: d->files) {
+ list.emplace_back(i);
+ }
+ fileCache.emplace(d, move(list));
+ }
+ cache = fileCache.find(d);
+ }
+ for(auto& i: cache->second) {
+ files->insert(files->size(), &i);
+ }
+ } else {
+ for(auto& i: d->files) {
+ files->insert(files->size(), new ItemInfo(i));
+ }
}
files->resort();
=== modified file 'win32/DirectoryListingFrame.h'
--- win32/DirectoryListingFrame.h 2012-09-29 12:29:21 +0000
+++ win32/DirectoryListingFrame.h 2012-10-11 16:17:05 +0000
@@ -27,7 +27,6 @@
#include <dcpp/forward.h>
#include <dcpp/ClientManagerListener.h>
#include <dcpp/DirectoryListing.h>
-#include <dcpp/FastAlloc.h>
#include <dcpp/StringMatch.h>
#include <dcpp/User.h>
@@ -103,7 +102,7 @@
COLUMN_LAST
};
- class ItemInfo : public FastAlloc<ItemInfo> {
+ class ItemInfo {
public:
enum ItemType {
FILE,
@@ -167,6 +166,7 @@
LabelPtr loading;
unordered_map<DirectoryListing::Directory*, ItemInfo> dirCache;
unordered_map<DirectoryListing::Directory*, list<ItemInfo>> fileCache;
+ bool useCache;
RebarPtr rebar;
ComboBoxPtr pathBox;
=== modified file 'win32/QueueFrame.cpp'
--- win32/QueueFrame.cpp 2012-09-15 20:36:00 +0000
+++ win32/QueueFrame.cpp 2012-10-11 16:17:05 +0000
@@ -65,6 +65,7 @@
dirs(0),
files(0),
dirty(true),
+filesDirty(true),
usingDirMenu(false),
queueSize(0),
queueItems(0),
@@ -94,6 +95,7 @@
files->onKeyDown([this](int c) { return handleKeyDownFiles(c); });
files->onContextMenu([this](const dwt::ScreenCoordinate &sc) { return handleFilesContextMenu(sc); });
+ files->onSelectionChanged([this] { filesDirty = true; });
if(!SETTING(QUEUEFRAME_SHOW_TREE)) {
paned->maximize(files);
@@ -193,33 +195,38 @@
}
void QueueFrame::updateStatus() {
- int64_t total = 0;
- int cnt = files->countSelected();
- if(cnt < 2) {
- cnt = files->size();
- if(SETTING(QUEUEFRAME_SHOW_TREE)) {
- for(auto i = 0; i < cnt; ++i) {
+ if(filesDirty || dirty) {
+ filesDirty = false;
+
+ auto cnt = files->countSelected();
+ int64_t total = 0;
+ if(cnt < 2) {
+ cnt = files->size();
+ if(SETTING(QUEUEFRAME_SHOW_TREE)) {
+ for(decltype(cnt) i = 0; i < cnt; ++i) {
+ QueueItemInfo* ii = files->getData(i);
+ total += (ii->getSize() > 0) ? ii->getSize() : 0;
+ }
+ } else {
+ total = queueSize;
+ }
+ } else {
+ int i = -1;
+ while( (i = files->getNext(i, LVNI_SELECTED)) != -1) {
QueueItemInfo* ii = files->getData(i);
total += (ii->getSize() > 0) ? ii->getSize() : 0;
}
- } else {
- total = queueSize;
- }
- } else {
- int i = -1;
- while( (i = files->getNext(i, LVNI_SELECTED)) != -1) {
- QueueItemInfo* ii = files->getData(i);
- total += (ii->getSize() > 0) ? ii->getSize() : 0;
- }
+ }
+
+ status->setText(STATUS_PARTIAL_COUNT, str(TF_("Items: %1%") % cnt));
+ status->setText(STATUS_PARTIAL_BYTES, str(TF_("Size: %1%") % Text::toT(Util::formatBytes(total))));
}
- status->setText(STATUS_PARTIAL_COUNT, str(TF_("Items: %1%") % cnt));
- status->setText(STATUS_PARTIAL_BYTES, str(TF_("Size: %1%") % Text::toT(Util::formatBytes(total))));
-
if(dirty) {
+ dirty = false;
+
status->setText(STATUS_TOTAL_COUNT, str(TF_("Files: %1%") % queueItems));
status->setText(STATUS_TOTAL_BYTES, str(TF_("Size: %1%") % Text::toT(Util::formatBytes(queueSize))));
- dirty = false;
}
}
@@ -288,6 +295,8 @@
files->resort();
curDir = getSelectedDir();
+
+ filesDirty = true;
updateStatus();
}
=== modified file 'win32/QueueFrame.h'
--- win32/QueueFrame.h 2012-07-11 17:13:42 +0000
+++ win32/QueueFrame.h 2012-10-11 16:17:05 +0000
@@ -205,6 +205,8 @@
std::string curDir;
bool dirty;
+ bool filesDirty;
+
bool usingDirMenu;
int64_t queueSize;
=== modified file 'win32/RichTextBox.cpp'
--- win32/RichTextBox.cpp 2012-09-09 13:55:46 +0000
+++ win32/RichTextBox.cpp 2012-10-11 16:17:05 +0000
@@ -49,6 +49,7 @@
if((seed.events & ENM_LINK) == ENM_LINK) {
linkTip = dwt::WidgetCreator<dwt::ToolTip>::create(this, dwt::ToolTip::Seed());
linkTip->setTool(this, [this](tstring& text) { handleLinkTip(text); });
+ onDestroy([this] { linkTip->close(); linkTip = nullptr; });
onRaw([this](WPARAM, LPARAM lParam) { return handleLink(*reinterpret_cast<ENLINK*>(lParam)); },
dwt::Message(WM_NOTIFY, EN_LINK));
=== modified file 'win32/UsersFrame.cpp'
--- win32/UsersFrame.cpp 2012-09-10 22:14:27 +0000
+++ win32/UsersFrame.cpp 2012-10-11 16:17:05 +0000
@@ -111,7 +111,8 @@
users(0),
scroll(0),
userInfo(0),
-filter(usersColumns, COLUMN_LAST, [this] { updateList(); })
+filter(usersColumns, COLUMN_LAST, [this] { updateList(); }),
+selected(-1)
{
grid = addChild(Grid::Seed(2, 1));
grid->column(0).mode = GridInfo::FILL;
@@ -331,6 +332,11 @@
}
void UsersFrame::updateUserInfo() {
+ auto prevSelected = selected;
+ selected = users->countSelected() == 1 ? users->getSelected() : -1;
+ if(selected == prevSelected)
+ return;
+
ScopedFunctor([&] { scroll->layout(); userInfo->layout(); userInfo->redraw(); });
HoldRedraw hold(userInfo);
@@ -344,20 +350,17 @@
userInfo->clearRows();
if(users->countSelected() != 1) {
- userInfo->redraw();
return;
}
auto sel = users->getSelectedData();
if(!sel) {
- userInfo->redraw();
return;
}
auto user = sel->getUser();
auto idents = ClientManager::getInstance()->getIdentities(user);
if(idents.empty()) {
- userInfo->redraw();
return;
}
@@ -427,7 +430,6 @@
if(dlg.run() == IDOK) {
FavoriteManager::getInstance()->setUserDescription(ui->getUser(), Text::fromT(dlg.getValue()));
ui->columns[COLUMN_DESCRIPTION] = dlg.getValue();
- users->update(i);
}
}
}
=== modified file 'win32/UsersFrame.h'
--- win32/UsersFrame.h 2012-09-10 22:14:27 +0000
+++ win32/UsersFrame.h 2012-10-11 16:17:05 +0000
@@ -127,6 +127,8 @@
ListFilter filter;
+ int selected;
+
static dwt::ImageListPtr userIcons;
std::unordered_map<UserPtr, UserInfo, User::Hash> userInfos;