ipc/chromium/src/base/message_pump_qt.cc

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

     1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
     2 // Use of this source code is governed by a BSD-style license that can be
     3 // found in the LICENSE file.
     5 #include <qabstracteventdispatcher.h>
     6 #include <qevent.h>
     7 #include <QCoreApplication>
     8 #include <QThread>
     9 #include <qtimer.h>
    11 #include "base/message_pump_qt.h"
    13 #include <fcntl.h>
    14 #include <limits>
    15 #include <math.h>
    17 #include "base/eintr_wrapper.h"
    18 #include "base/lazy_instance.h"
    19 #include "base/logging.h"
    20 #include "base/platform_thread.h"
    22 namespace {
    23 // Cached QEvent user type, registered for our event system
    24 static int sPokeEvent;
    25 }  // namespace
    27 namespace base {
    29 MessagePumpForUI::MessagePumpForUI()
    30   : state_(NULL),
    31     qt_pump(*this)
    32 {
    33 }
    35 MessagePumpForUI::~MessagePumpForUI() {
    36 }
    38 MessagePumpQt::MessagePumpQt(MessagePumpForUI &aPump)
    39   : pump(aPump), mTimer(new QTimer(this))
    40 {
    41   // Register our custom event type, to use in qApp event loop
    42   sPokeEvent = QEvent::registerEventType();
    43   connect(mTimer, SIGNAL(timeout()), this, SLOT(dispatchDelayed()));
    44   mTimer->setSingleShot(true);
    45 }
    47 MessagePumpQt::~MessagePumpQt()
    48 {
    49   mTimer->stop();
    50   delete mTimer;
    51 }
    53 bool
    54 MessagePumpQt::event(QEvent *e)
    55 {
    56   if (e->type() == sPokeEvent) {
    57     pump.HandleDispatch();
    58     return true;
    59   }
    60   return false;
    61 }
    63 void
    64 MessagePumpQt::scheduleDelayedIfNeeded(const TimeTicks& delayed_work_time)
    65 {
    66   if (delayed_work_time.is_null()) {
    67     return;
    68   }
    70   if (mTimer->isActive()) {
    71     mTimer->stop();
    72   }
    74   TimeDelta later = delayed_work_time - TimeTicks::Now();
    75   // later.InMilliseconds() returns an int64_t, QTimer only accepts int's for start(),
    76   // std::min only works on exact same types.
    77   int laterMsecs = later.InMilliseconds() > std::numeric_limits<int>::max() ?
    78     std::numeric_limits<int>::max() : later.InMilliseconds();
    79   mTimer->start(laterMsecs > 0 ? laterMsecs : 0);
    80 }
    82 void
    83 MessagePumpQt::dispatchDelayed()
    84 {
    85   pump.HandleDispatch();
    86 }
    88 void MessagePumpForUI::Run(Delegate* delegate) {
    89   RunState state;
    90   state.delegate = delegate;
    91   state.should_quit = false;
    92   state.run_depth = state_ ? state_->run_depth + 1 : 1;
    93   // We really only do a single task for each iteration of the loop.  If we
    94   // have done something, assume there is likely something more to do.  This
    95   // will mean that we don't block on the message pump until there was nothing
    96   // more to do.  We also set this to true to make sure not to block on the
    97   // first iteration of the loop, so RunAllPending() works correctly.
    98   bool more_work_is_plausible = true;
   100   RunState* previous_state = state_;
   101   state_ = &state;
   103   for(;;) {
   104     QEventLoop::ProcessEventsFlags block = QEventLoop::AllEvents;
   105     if (!more_work_is_plausible) {
   106       block |= QEventLoop::WaitForMoreEvents;
   107     }
   109     QAbstractEventDispatcher* dispatcher =
   110       QAbstractEventDispatcher::instance(QThread::currentThread());
   111     // An assertion seems too much here, as during startup,
   112     // the dispatcher might not be ready yet.
   113     if (!dispatcher) {
   114       return;
   115     }
   117     // processEvent's returns true if an event has been processed.
   118     more_work_is_plausible = dispatcher->processEvents(block);
   120     if (state_->should_quit) {
   121       break;
   122     }
   124     more_work_is_plausible |= state_->delegate->DoWork();
   125     if (state_->should_quit) {
   126       break;
   127     }
   129     more_work_is_plausible |=
   130       state_->delegate->DoDelayedWork(&delayed_work_time_);
   131     if (state_->should_quit) {
   132       break;
   133     }
   135     qt_pump.scheduleDelayedIfNeeded(delayed_work_time_);
   137     if (more_work_is_plausible) {
   138       continue;
   139     }
   141     more_work_is_plausible = state_->delegate->DoIdleWork();
   142     if (state_->should_quit) {
   143       break;
   144     }
   145   }
   147   state_ = previous_state;
   148 }
   150 void MessagePumpForUI::HandleDispatch() {
   151   if (state_->should_quit) {
   152     return;
   153   }
   155   if (state_->delegate->DoWork()) {
   156     // there might be more, see more_work_is_plausible 
   157     // variable above, that's why we ScheduleWork() to keep going.
   158     ScheduleWork();
   159   }
   161   if (state_->should_quit) {
   162     return;
   163   }
   165   state_->delegate->DoDelayedWork(&delayed_work_time_);
   166   qt_pump.scheduleDelayedIfNeeded(delayed_work_time_);
   167 }
   169 void MessagePumpForUI::Quit() {
   170   if (state_) {
   171     state_->should_quit = true;
   172   } else {
   173     NOTREACHED() << "Quit called outside Run!";
   174   }
   175 }
   177 void MessagePumpForUI::ScheduleWork() {
   178   QCoreApplication::postEvent(&qt_pump,
   179                               new QEvent((QEvent::Type) sPokeEvent));
   180 }
   182 void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
   183   // On GLib implementation, a work source is defined which explicitly checks the
   184   // time that has passed. Here, on Qt we can use a QTimer that enqueues our
   185   // event signal in an event queue.
   186   delayed_work_time_ = delayed_work_time;
   187   qt_pump.scheduleDelayedIfNeeded(delayed_work_time_);
   188 }
   190 }  // namespace base

mercurial