summaryrefslogtreecommitdiffstats
path: root/base/message_loop.cc
diff options
context:
space:
mode:
Diffstat (limited to 'base/message_loop.cc')
-rw-r--r--base/message_loop.cc72
1 files changed, 36 insertions, 36 deletions
diff --git a/base/message_loop.cc b/base/message_loop.cc
index ccaf700..623ec99 100644
--- a/base/message_loop.cc
+++ b/base/message_loop.cc
@@ -169,15 +169,7 @@ void MessageLoop::RemoveObserver(Observer *obs) {
}
void MessageLoop::Run() {
- RunHandler(NULL, false);
-}
-
-void MessageLoop::Run(Dispatcher* dispatcher) {
- RunHandler(dispatcher, false);
-}
-
-void MessageLoop::RunOnce() {
- RunHandler(NULL, true);
+ Run(NULL);
}
// Runs the loop in two different SEH modes:
@@ -185,19 +177,20 @@ void MessageLoop::RunOnce() {
// one that calls SetUnhandledExceptionFilter().
// enable_SEH_restoration_ = true : any unhandled exception goes to the filter
// that was existed before the loop was run.
-void MessageLoop::RunHandler(Dispatcher* dispatcher, bool run_loop_once) {
+void MessageLoop::Run(Dispatcher* dispatcher) {
if (exception_restoration_) {
LPTOP_LEVEL_EXCEPTION_FILTER current_filter = GetTopSEHFilter();
__try {
- RunInternal(dispatcher, run_loop_once);
+ RunInternal(dispatcher);
} __except(SEHFilter(current_filter)) {
}
} else {
- RunInternal(dispatcher, run_loop_once);
+ RunInternal(dispatcher);
}
}
//------------------------------------------------------------------------------
+// Methods supporting various strategies for servicing the numerous queues.
// IF this was just a simple PeekMessage() loop (servicing all passible work
// queues), then Windows would try to achieve the following order according to
// MSDN documentation about PeekMessage with no filter):
@@ -210,7 +203,7 @@ void MessageLoop::RunHandler(Dispatcher* dispatcher, bool run_loop_once) {
// Summary: none of the above classes is starved, and sent messages has twice
// the chance of being processed (i.e., reduced service time).
-void MessageLoop::RunInternal(Dispatcher* dispatcher, bool run_loop_once) {
+void MessageLoop::RunInternal(Dispatcher* dispatcher) {
// Preserve ability to be called recursively.
ScopedStateSave save(this); // State is restored on exit.
dispatcher_ = dispatcher;
@@ -218,30 +211,38 @@ void MessageLoop::RunInternal(Dispatcher* dispatcher, bool run_loop_once) {
DCHECK(this == current());
//
- // Process pending messages and signaled objects.
+ // Process all pending messages and signaled objects.
//
// Flush these queues before exiting due to a kMsgQuit or else we risk not
// shutting down properly as some operations may depend on further event
// processing. (Note: some tests may use quit_now_ to exit more swiftly,
// and leave messages pending, so don't assert the above fact).
- RunTraditional(run_loop_once);
- DCHECK(run_loop_once || quit_received_ || quit_now_);
+ //
+
+ RunTraditional();
+ DCHECK(quit_received_ || quit_now_);
}
-void MessageLoop::RunTraditional(bool run_loop_once) {
- do {
+typedef bool (MessageLoop::*ProcessingMethod)();
+typedef ProcessingMethod ProcessingMethods[];
+
+void MessageLoop::RunTraditional() {
+ run_depth_++;
+ for (;;) {
// If we do any work, we may create more messages etc., and more work
- // may possibly be waiting in another task group. When we (for example)
- // ProcessNextWindowsMessage(), there is a good chance there are still more
- // messages waiting (same thing for ProcessNextObject(), which responds to
- // only one signaled object; etc.). On the other hand, when any of these
- // methods return having done no work, then it is pretty unlikely that
- // calling them again quickly will find any work to do.
+ // may possibly be waiting in another task group. In addition, each method
+ // call here typically limits work to 1 (worst case 2) items. As a result,
+ // when we (for example) ProcessNextWindowsMessage() there is a good chance
+ // there are still more waiting (same thing for ProcessNextDeferredTask(),
+ // which responds to only one signaled object.). On the other hand, when
+ // any of these methods return having done no work, then it is pretty
+ // unlikely that calling them again quickly will find any work to do.
// Finally, if they all say they had no work, then it is a good time to
// consider sleeping (waiting) for more work.
- bool more_work_is_plausible = ProcessNextWindowsMessage();
+ bool more_work_is_plausible = false;
+ more_work_is_plausible |= ProcessNextWindowsMessage();
if (quit_now_)
- return;
+ break;
more_work_is_plausible |= ProcessNextDeferredTask();
more_work_is_plausible |= ProcessNextObject();
@@ -249,7 +250,7 @@ void MessageLoop::RunTraditional(bool run_loop_once) {
continue;
if (quit_received_)
- return;
+ break;
// Run any timer that is ready to run. It may create messages etc.
if (ProcessSomeTimers())
@@ -257,19 +258,16 @@ void MessageLoop::RunTraditional(bool run_loop_once) {
// We run delayed non nestable tasks only after all nestable tasks have
// run, to preserve FIFO ordering.
- if (ProcessNextDelayedNonNestableTask())
+ more_work_is_plausible = ProcessNextDelayedNonNestableTask();
+ if (more_work_is_plausible)
continue;
- if (run_loop_once)
- return;
-
// We service APCs in WaitForWork, without returning.
WaitForWork(); // Wait (sleep) until we have work to do again.
- } while (!run_loop_once);
-}
+ }
-//------------------------------------------------------------------------------
-// Wrapper functions for use in above message loop framework.
+ run_depth_--;
+}
bool MessageLoop::ProcessNextDelayedNonNestableTask() {
if (run_depth_ != 1)
@@ -282,6 +280,9 @@ bool MessageLoop::ProcessNextDelayedNonNestableTask() {
return true;
}
+//------------------------------------------------------------------------------
+// Wrapper functions for use in above message loop frameworks.
+
bool MessageLoop::ProcessNextDeferredTask() {
ReloadWorkQueue();
return QueueOrRunTask(NULL);
@@ -398,7 +399,6 @@ LRESULT MessageLoop::MessageWndProc(HWND hwnd, UINT message,
}
case kMsgQuit: {
- CHECK(!quit_received_); // Discarding a second quit will cause a hang.
quit_received_ = true;
return 0;
}