Add MessageLoop to avoid 100% CPU in foreground windows.

This commit is contained in:
David Capello 2012-07-09 18:31:06 -03:00
parent 5529c62c9f
commit 8e7b16c3b1
7 changed files with 83 additions and 31 deletions

View File

@ -27,6 +27,7 @@ add_library(ui-lib
manager.cpp
menu.cpp
message.cpp
message_loop.cpp
paint_event.cpp
popup_window.cpp
preferred_size_event.cpp

View File

@ -32,6 +32,7 @@
#include "ui/manager.h"
#include "ui/menu.h"
#include "ui/message.h"
#include "ui/message_loop.h"
#include "ui/paint_event.h"
#include "ui/popup_window.h"
#include "ui/preferred_size_event.h"

View File

@ -11,8 +11,6 @@
#include "ui/manager.h"
#include "base/chrono.h"
#include "base/thread.h"
#include "ui/gui.h"
#include "ui/intern.h"
@ -186,27 +184,10 @@ Manager::~Manager()
void Manager::run()
{
base::Chrono chrono;
MessageLoop loop(this);
while (!jlist_empty(this->children)) {
chrono.reset();
if (generateMessages()) {
dispatchMessages();
}
else if (!m_garbage.empty()) {
collectGarbage();
}
// If the dispatching of messages was faster than 10 milliseconds,
// it means that the process is not using a lot of CPU, so we can
// wait the difference to cover those 10 milliseconds
// sleeping. With this code we can avoid 100% CPU usage (a
// property of Allegro 4 polling nature).
double elapsedMSecs = chrono.elapsed() * 1000.0;
if (elapsedMSecs > 0.0 && elapsedMSecs < 10.0)
base::this_thread::sleep_for((10.0 - elapsedMSecs) / 1000.0);
}
while (!jlist_empty(this->children))
loop.pumpMessages();
}
bool Manager::generateMessages()
@ -1196,6 +1177,9 @@ void Manager::invalidateDisplayRegion(const JRegion region)
void Manager::collectGarbage()
{
if (m_garbage.empty())
return;
for (WidgetsList::iterator
it = m_garbage.begin(),
end = m_garbage.end(); it != end; ++it) {

View File

@ -28,12 +28,11 @@ namespace ui {
// Returns true if there are messages in the queue to be
// distpatched through jmanager_dispatch_messages().
bool generateMessages();
void dispatchMessages();
void enqueueMessage(Message* msg);
void addToGarbage(Widget* widget);
void enqueueMessage(Message* msg);
void collectGarbage();
Window* getTopWindow();
Window* getForegroundWindow();
@ -72,7 +71,6 @@ namespace ui {
private:
void layoutManager(JRect rect);
void pumpQueue();
void collectGarbage();
void generateSetCursorMessage();
static void removeWidgetFromDests(Widget* widget, Message* msg);
static bool someParentIsFocusStop(Widget* widget);

43
src/ui/message_loop.cpp Normal file
View File

@ -0,0 +1,43 @@
// ASEPRITE gui library
// Copyright (C) 2001-2012 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#include "config.h"
#include "ui/message_loop.h"
#include "base/chrono.h"
#include "base/thread.h"
#include "ui/manager.h"
namespace ui {
MessageLoop::MessageLoop(Manager* manager)
: m_manager(manager)
{
}
void MessageLoop::pumpMessages()
{
base::Chrono chrono;
if (m_manager->generateMessages()) {
m_manager->dispatchMessages();
}
else {
m_manager->collectGarbage();
}
// If the dispatching of messages was faster than 10 milliseconds,
// it means that the process is not using a lot of CPU, so we can
// wait the difference to cover those 10 milliseconds
// sleeping. With this code we can avoid 100% CPU usage (a
// property of Allegro 4 polling nature).
double elapsedMSecs = chrono.elapsed() * 1000.0;
if (elapsedMSecs > 0.0 && elapsedMSecs < 10.0)
base::this_thread::sleep_for((10.0 - elapsedMSecs) / 1000.0);
}
} // namespace ui

27
src/ui/message_loop.h Normal file
View File

@ -0,0 +1,27 @@
// ASEPRITE gui library
// Copyright (C) 2001-2012 David Capello
//
// This source file is ditributed under a BSD-like license, please
// read LICENSE.txt for more information.
#ifndef UI_MESSAGE_LOOP_H_INCLUDED
#define UI_MESSAGE_LOOP_H_INCLUDED
namespace ui {
class Manager;
class MessageLoop
{
public:
MessageLoop(Manager* manager);
void pumpMessages();
private:
Manager* m_manager;
};
} // namespace ui
#endif

View File

@ -233,14 +233,12 @@ void Window::openWindowInForeground()
{
openWindow();
Manager* manager = getManager();
MessageLoop loop(getManager());
m_is_foreground = true;
while (!(this->flags & JI_HIDDEN)) {
if (manager->generateMessages())
manager->dispatchMessages();
}
while (!(this->flags & JI_HIDDEN))
loop.pumpMessages();
m_is_foreground = false;
}