1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 7 #include "base/message_pump_android.h" 8 9 #include <fcntl.h> 10 #include <math.h> 11 12 #include "base/eintr_wrapper.h" 13 #include "base/logging.h" 14 #include "base/platform_thread.h" 15 16 namespace mozilla { 17 bool ProcessNextEvent(); 18 void NotifyEvent(); 19 } // namespace mozilla 20 21 namespace base { 22 MessagePumpForUI()23MessagePumpForUI::MessagePumpForUI() : state_(NULL) {} 24 ~MessagePumpForUI()25MessagePumpForUI::~MessagePumpForUI() {} 26 Run(Delegate * delegate)27void MessagePumpForUI::Run(Delegate* delegate) { 28 RunState state; 29 state.delegate = delegate; 30 state.should_quit = false; 31 state.run_depth = state_ ? state_->run_depth + 1 : 1; 32 // We really only do a single task for each iteration of the loop. If we 33 // have done something, assume there is likely something more to do. This 34 // will mean that we don't block on the message pump until there was nothing 35 // more to do. We also set this to true to make sure not to block on the 36 // first iteration of the loop, so RunAllPending() works correctly. 37 state.more_work_is_plausible = true; 38 39 RunState* previous_state = state_; 40 state_ = &state; 41 42 // We run our own loop instead of using g_main_loop_quit in one of the 43 // callbacks. This is so we only quit our own loops, and we don't quit 44 // nested loops run by others. TODO(deanm): Is this what we want? 45 46 while (!state_->should_quit) { 47 mozilla::ProcessNextEvent(); 48 if (work_scheduled) { 49 work_scheduled = false; 50 HandleDispatch(); 51 } 52 } 53 54 state_ = previous_state; 55 } 56 HandleDispatch()57void MessagePumpForUI::HandleDispatch() { 58 // We should only ever have a single message on the wakeup pipe, since we 59 // are only signaled when the queue went from empty to non-empty. The qApp 60 // poll will tell us whether there was data, so this read shouldn't block. 61 if (state_->should_quit) return; 62 63 state_->more_work_is_plausible = false; 64 65 if (state_->delegate->DoWork()) state_->more_work_is_plausible = true; 66 67 if (state_->should_quit) return; 68 69 if (state_->delegate->DoDelayedWork(&delayed_work_time_)) 70 state_->more_work_is_plausible = true; 71 if (state_->should_quit) return; 72 73 // Don't do idle work if we think there are more important things 74 // that we could be doing. 75 if (state_->more_work_is_plausible) return; 76 77 if (state_->delegate->DoIdleWork()) state_->more_work_is_plausible = true; 78 if (state_->should_quit) return; 79 } 80 Quit()81void MessagePumpForUI::Quit() { 82 if (state_) { 83 state_->should_quit = true; 84 } else { 85 NOTREACHED() << "Quit called outside Run!"; 86 } 87 } 88 ScheduleWork()89void MessagePumpForUI::ScheduleWork() { 90 // This can be called on any thread, so we don't want to touch any state 91 // variables as we would then need locks all over. This ensures that if 92 // we are sleeping in a poll that we will wake up. 93 work_scheduled = true; 94 mozilla::NotifyEvent(); 95 } 96 ScheduleDelayedWork(const TimeTicks & delayed_work_time)97void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { 98 // We need to wake up the loop in case the poll timeout needs to be 99 // adjusted. This will cause us to try to do work, but that's ok. 100 delayed_work_time_ = delayed_work_time; 101 ScheduleWork(); 102 } 103 104 } // namespace base 105