15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/run_loop.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/tracked_objects.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#if defined(OS_WIN)
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/message_loop/message_pump_dispatcher.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RunLoop::RunLoop()
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : loop_(MessageLoop::current()),
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      previous_run_loop_(NULL),
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      run_depth_(0),
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      run_called_(false),
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      quit_called_(false),
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      running_(false),
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      quit_when_idle_received_(false),
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      weak_factory_(this) {
25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if defined(OS_WIN)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   dispatcher_ = NULL;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if defined(OS_WIN)
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RunLoop::RunLoop(MessagePumpDispatcher* dispatcher)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : loop_(MessageLoop::current()),
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      previous_run_loop_(NULL),
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dispatcher_(dispatcher),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      run_depth_(0),
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      run_called_(false),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      quit_called_(false),
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      running_(false),
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      quit_when_idle_received_(false),
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      weak_factory_(this) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RunLoop::~RunLoop() {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RunLoop::Run() {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!BeforeRun())
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Use task stopwatch to exclude the loop run time from the current task, if
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // any.
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  tracked_objects::TaskStopwatch stopwatch;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop_->RunHandler();
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  stopwatch.Stop();
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AfterRun();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RunLoop::RunUntilIdle() {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  quit_when_idle_received_ = true;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Run();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RunLoop::Quit() {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  quit_called_ = true;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (running_ && loop_->run_loop_ == this) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is the inner-most RunLoop, so quit now.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loop_->QuitNow();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::Closure RunLoop::QuitClosure() {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::Bind(&RunLoop::Quit, weak_factory_.GetWeakPtr());
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RunLoop::BeforeRun() {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!run_called_);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  run_called_ = true;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allow Quit to be called before Run.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (quit_called_)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Push RunLoop stack:
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  previous_run_loop_ = loop_->run_loop_;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  run_depth_ = previous_run_loop_? previous_run_loop_->run_depth_ + 1 : 1;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop_->run_loop_ = this;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  running_ = true;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RunLoop::AfterRun() {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  running_ = false;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pop RunLoop stack:
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop_->run_loop_ = previous_run_loop_;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Execute deferred QuitNow, if any:
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (previous_run_loop_ && previous_run_loop_->quit_called_)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loop_->QuitNow();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
106