1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Copyright 2013 The Chromium Authors. All rights reserved. 2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use of this source code is governed by a BSD-style license that can be 3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// found in the LICENSE file. 4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/message_pump/message_pump_mojo.h" 6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <stdint.h> 8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <algorithm> 10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <map> 11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <vector> 12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/containers/small_map.h" 14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/debug/alias.h" 15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/lazy_instance.h" 16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/logging.h" 17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/threading/thread_local.h" 18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/threading/thread_restrictions.h" 19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/time/time.h" 20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/message_pump/message_pump_mojo_handler.h" 21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/message_pump/time_helper.h" 22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/c/system/wait_set.h" 23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace mojo { 25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace common { 26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace { 27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbase::LazyInstance<base::ThreadLocalPointer<MessagePumpMojo> >::Leaky 29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez g_tls_current_pump = LAZY_INSTANCE_INITIALIZER; 30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezMojoDeadline TimeTicksToMojoDeadline(base::TimeTicks time_ticks, 32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::TimeTicks now) { 33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The is_null() check matches that of HandleWatcher as well as how 34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // |delayed_work_time| is used. 35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (time_ticks.is_null()) 36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return MOJO_DEADLINE_INDEFINITE; 37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const int64_t delta = (time_ticks - now).InMicroseconds(); 38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return delta < 0 ? static_cast<MojoDeadline>(0) : 39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez static_cast<MojoDeadline>(delta); 40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace 43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstruct MessagePumpMojo::RunState { 45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez RunState() : should_quit(false) {} 46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::TimeTicks delayed_work_time; 48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool should_quit; 50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}; 51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezMessagePumpMojo::MessagePumpMojo() 53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : run_state_(NULL), 54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez next_handler_id_(0), 55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, 56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::WaitableEvent::InitialState::NOT_SIGNALED) { 57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(!current()) 58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez << "There is already a MessagePumpMojo instance on this thread."; 59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez g_tls_current_pump.Pointer()->Set(this); 60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MojoResult result = CreateMessagePipe(nullptr, &read_handle_, &write_handle_); 62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK_EQ(result, MOJO_RESULT_OK); 63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK(read_handle_.is_valid()); 64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK(write_handle_.is_valid()); 65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MojoHandle handle; 67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez result = MojoCreateWaitSet(&handle); 68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK_EQ(result, MOJO_RESULT_OK); 69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez wait_set_handle_.reset(Handle(handle)); 70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK(wait_set_handle_.is_valid()); 71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez result = 73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MojoAddHandle(wait_set_handle_.get().value(), read_handle_.get().value(), 74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MOJO_HANDLE_SIGNAL_READABLE); 75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK_EQ(result, MOJO_RESULT_OK); 76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezMessagePumpMojo::~MessagePumpMojo() { 79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK_EQ(this, current()); 80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez g_tls_current_pump.Pointer()->Set(NULL); 81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// static 84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstd::unique_ptr<base::MessagePump> MessagePumpMojo::Create() { 85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return std::unique_ptr<MessagePump>(new MessagePumpMojo()); 86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// static 89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezMessagePumpMojo* MessagePumpMojo::current() { 90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return g_tls_current_pump.Pointer()->Get(); 91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MessagePumpMojo::AddHandler(MessagePumpMojoHandler* handler, 94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const Handle& handle, 95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MojoHandleSignals wait_signals, 96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::TimeTicks deadline) { 97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK(handler); 98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(handle.is_valid()); 99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Assume it's an error if someone tries to reregister an existing handle. 100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK_EQ(0u, handlers_.count(handle)); 101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Handler handler_data; 102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez handler_data.handler = handler; 103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez handler_data.wait_signals = wait_signals; 104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez handler_data.deadline = deadline; 105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez handler_data.id = next_handler_id_++; 106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez handlers_[handle] = handler_data; 107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!deadline.is_null()) { 108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool inserted = deadline_handles_.insert(handle).second; 109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(inserted); 110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MojoResult result = MojoAddHandle(wait_set_handle_.get().value(), 113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez handle.value(), wait_signals); 114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Because stopping a HandleWatcher is now asynchronous, it's possible for the 115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // handle to no longer be open at this point. 116645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK(result == MOJO_RESULT_OK || result == MOJO_RESULT_INVALID_ARGUMENT); 117645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MessagePumpMojo::RemoveHandler(const Handle& handle) { 120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MojoResult result = 121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MojoRemoveHandle(wait_set_handle_.get().value(), handle.value()); 122645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // At this point, it's possible that the handle has been closed, which would 123645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // cause MojoRemoveHandle() to return MOJO_RESULT_INVALID_ARGUMENT. It's also 124645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // possible for the handle to have already been removed, so all of the 125645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // possible error codes are valid here. 126645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK(result == MOJO_RESULT_OK || result == MOJO_RESULT_NOT_FOUND || 127645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez result == MOJO_RESULT_INVALID_ARGUMENT); 128645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 129645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez handlers_.erase(handle); 130645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez deadline_handles_.erase(handle); 131645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 132645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 133645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MessagePumpMojo::AddObserver(Observer* observer) { 134645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez observers_.AddObserver(observer); 135645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 136645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 137645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MessagePumpMojo::RemoveObserver(Observer* observer) { 138645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez observers_.RemoveObserver(observer); 139645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 140645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 141645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MessagePumpMojo::Run(Delegate* delegate) { 142645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez RunState run_state; 143645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez RunState* old_state = NULL; 144645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez { 145645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoLock auto_lock(run_state_lock_); 146645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez old_state = run_state_; 147645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez run_state_ = &run_state; 148645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 149645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DoRunLoop(&run_state, delegate); 150645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez { 151645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoLock auto_lock(run_state_lock_); 152645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez run_state_ = old_state; 153645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 154645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 155645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 156645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MessagePumpMojo::Quit() { 157645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoLock auto_lock(run_state_lock_); 158645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (run_state_) 159645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez run_state_->should_quit = true; 160645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 161645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 162645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MessagePumpMojo::ScheduleWork() { 163645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez SignalControlPipe(); 164645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 165645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 166645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MessagePumpMojo::ScheduleDelayedWork( 167645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const base::TimeTicks& delayed_work_time) { 168645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AutoLock auto_lock(run_state_lock_); 169645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!run_state_) 170645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 171645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez run_state_->delayed_work_time = delayed_work_time; 172645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 173645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 174645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MessagePumpMojo::DoRunLoop(RunState* run_state, Delegate* delegate) { 175645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool more_work_is_plausible = true; 176645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (;;) { 177645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const bool block = !more_work_is_plausible; 178645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (read_handle_.is_valid()) { 179645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez more_work_is_plausible = DoInternalWork(*run_state, block); 180645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 181645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez more_work_is_plausible = DoNonMojoWork(*run_state, block); 182645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 183645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 184645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (run_state->should_quit) 185645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez break; 186645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 187645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez more_work_is_plausible |= delegate->DoWork(); 188645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (run_state->should_quit) 189645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez break; 190645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 191645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez more_work_is_plausible |= delegate->DoDelayedWork( 192645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez &run_state->delayed_work_time); 193645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (run_state->should_quit) 194645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez break; 195645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 196645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (more_work_is_plausible) 197645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez continue; 198645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 199645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez more_work_is_plausible = delegate->DoIdleWork(); 200645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (run_state->should_quit) 201645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez break; 202645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 203645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 204645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 205645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool MessagePumpMojo::DoInternalWork(const RunState& run_state, bool block) { 206645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool did_work = block; 207645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (block) { 208645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // If the wait isn't blocking (deadline == 0), there's no point in waiting. 209645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Wait sets do not require a wait operation to be performed in order to 210645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // retreive any ready handles. Performing a wait with deadline == 0 is 211645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // unnecessary work. 212645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez did_work = WaitForReadyHandles(run_state); 213645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 214645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 215645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez did_work |= ProcessReadyHandles(); 216645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez did_work |= RemoveExpiredHandles(); 217645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 218645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return did_work; 219645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 220645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 221645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool MessagePumpMojo::DoNonMojoWork(const RunState& run_state, bool block) { 222645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool did_work = block; 223645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (block) { 224645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const MojoDeadline deadline = GetDeadlineForWait(run_state); 225645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Stolen from base/message_loop/message_pump_default.cc 226645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::ThreadRestrictions::ScopedAllowWait allow_wait; 227645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (deadline == MOJO_DEADLINE_INDEFINITE) { 228645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez event_.Wait(); 229645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 230645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (deadline > 0) { 231645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez event_.TimedWait(base::TimeDelta::FromMicroseconds(deadline)); 232645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 233645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez did_work = false; 234645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 235645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 236645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Since event_ is auto-reset, we don't need to do anything special here 237645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // other than service each delegate method. 238645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 239645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 240645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez did_work |= RemoveExpiredHandles(); 241645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 242645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return did_work; 243645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 244645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 245645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool MessagePumpMojo::WaitForReadyHandles(const RunState& run_state) const { 246645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const MojoDeadline deadline = GetDeadlineForWait(run_state); 247645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const MojoResult wait_result = Wait( 248645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez wait_set_handle_.get(), MOJO_HANDLE_SIGNAL_READABLE, deadline, nullptr); 249645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (wait_result == MOJO_RESULT_OK) { 250645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Handles may be ready. Or not since wake-ups can be spurious in certain 251645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // circumstances. 252645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 253645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else if (wait_result == MOJO_RESULT_DEADLINE_EXCEEDED) { 254645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 255645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 256645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 257645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::debug::Alias(&wait_result); 258645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Unexpected result is likely fatal, crash so we can determine cause. 259645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK(false); 260645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 261645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 262645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 263645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool MessagePumpMojo::ProcessReadyHandles() { 264645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Maximum number of handles to retrieve and process. Experimentally, the 95th 265645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // percentile is 1 handle, and the long-term average is 1.1. However, this has 266645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // been seen to reach >10 under heavy load. 8 is a hand-wavy compromise. 267645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const uint32_t kMaxServiced = 8; 268645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez uint32_t num_ready_handles = kMaxServiced; 269645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MojoHandle handles[kMaxServiced]; 270645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MojoResult handle_results[kMaxServiced]; 271645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 272645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const MojoResult get_result = 273645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MojoGetReadyHandles(wait_set_handle_.get().value(), &num_ready_handles, 274645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez handles, handle_results, nullptr); 275645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK(get_result == MOJO_RESULT_OK || get_result == MOJO_RESULT_SHOULD_WAIT); 276645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (get_result != MOJO_RESULT_OK) 277645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 278645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 279645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(num_ready_handles); 280645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK_LE(num_ready_handles, kMaxServiced); 281645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Do this in two steps, because notifying a handler may remove/add other 282645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // handles that may have also been woken up. 283645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // First, enumerate the IDs of the ready handles. Then, iterate over the 284645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // handles and only take action if the ID hasn't changed. 285645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Since the size of this map is bounded by |kMaxServiced|, use a SmallMap to 286645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // avoid the per-element allocation. 287645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::SmallMap<std::map<Handle, int>, kMaxServiced> ready_handles; 288645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (uint32_t i = 0; i < num_ready_handles; i++) { 289645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const Handle handle = Handle(handles[i]); 290645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Skip the control handle. It's special. 291645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (handle.value() == read_handle_.get().value()) 292645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez continue; 293645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(handle.is_valid()); 294645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const auto it = handlers_.find(handle); 295645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Skip handles that have been removed. This is possible because 296645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // RemoveHandler() can be called with a handle that has been closed. Because 297645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // the handle is closed, the MojoRemoveHandle() call in RemoveHandler() 298645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // would have failed, but the handle is still in the wait set. Once the 299645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // handle is retrieved using MojoGetReadyHandles(), it is implicitly removed 300645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // from the set. The result is either the pending result that existed when 301645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // the handle was closed, or |MOJO_RESULT_CANCELLED| to indicate that the 302645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // handle was closed. 303645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (it == handlers_.end()) 304645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez continue; 305645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ready_handles[handle] = it->second.id; 306645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 307645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 308645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (uint32_t i = 0; i < num_ready_handles; i++) { 309645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const Handle handle = Handle(handles[i]); 310645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 311645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // If the handle has been removed, or it's ID has changed, skip over it. 312645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // If the handle's ID has changed, and it still satisfies its signals, 313645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // then it'll be caught in the next message pump iteration. 314645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const auto it = handlers_.find(handle); 315645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if ((handle.value() != read_handle_.get().value()) && 316645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez (it == handlers_.end() || it->second.id != ready_handles[handle])) { 317645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez continue; 318645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 319645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 320645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez switch (handle_results[i]) { 321645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez case MOJO_RESULT_CANCELLED: 322645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez case MOJO_RESULT_FAILED_PRECONDITION: 323645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DVLOG(1) << "Error: " << handle_results[i] 324645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez << " handle: " << handle.value(); 325645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (handle.value() == read_handle_.get().value()) { 326645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The Mojo EDK is shutting down. We can't just quit the message pump 327645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // because that may cause the thread to quit, which causes the 328645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // thread's MessageLoop to be destroyed, which races with any use of 329645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // |Thread::task_runner()|. So instead, we enter a "dumb" mode which 330645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // bypasses Mojo and just acts like a trivial message pump. That way, 331645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // we can wait for the usual thread exiting mechanism to happen. 332645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The dumb mode is indicated by releasing the control pipe's read 333645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // handle. 334645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez read_handle_.reset(); 335645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 336645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez SignalHandleError(handle, handle_results[i]); 337645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 338645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez break; 339645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez case MOJO_RESULT_OK: 340645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (handle.value() == read_handle_.get().value()) { 341645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DVLOG(1) << "Signaled control pipe"; 342645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Control pipe was written to. 343645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ReadMessageRaw(read_handle_.get(), nullptr, nullptr, nullptr, nullptr, 344645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MOJO_READ_MESSAGE_FLAG_MAY_DISCARD); 345645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 346645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DVLOG(1) << "Handle ready: " << handle.value(); 347645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez SignalHandleReady(handle); 348645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 349645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez break; 350645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez default: 351645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::debug::Alias(&i); 352645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::debug::Alias(&handle_results[i]); 353645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Unexpected result is likely fatal, crash so we can determine cause. 354645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK(false); 355645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 356645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 357645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 358645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 359645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 360645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool MessagePumpMojo::RemoveExpiredHandles() { 361645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool removed = false; 362645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Notify and remove any handlers whose time has expired. First, iterate over 363645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // the set of handles that have a deadline, and add the expired handles to a 364645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // map of <Handle, id>. Then, iterate over those expired handles and remove 365645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // them. The two-step process is because a handler can add/remove new 366645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // handlers. 367645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::map<Handle, int> expired_handles; 368645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const base::TimeTicks now(internal::NowTicks()); 369645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (const Handle handle : deadline_handles_) { 370645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const auto it = handlers_.find(handle); 371645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Expect any handle in |deadline_handles_| to also be in |handlers_| since 372645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // the two are modified in lock-step. 373645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(it != handlers_.end()); 374645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!it->second.deadline.is_null() && it->second.deadline < now) 375645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez expired_handles[handle] = it->second.id; 376645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 377645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (const auto& pair : expired_handles) { 378645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez auto it = handlers_.find(pair.first); 379645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Don't need to check deadline again since it can't change if id hasn't 380645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // changed. 381645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (it != handlers_.end() && it->second.id == pair.second) { 382645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez SignalHandleError(pair.first, MOJO_RESULT_DEADLINE_EXCEEDED); 383645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez removed = true; 384645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 385645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 386645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return removed; 387645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 388645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 389645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MessagePumpMojo::SignalControlPipe() { 390645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const MojoResult result = 391645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez WriteMessageRaw(write_handle_.get(), NULL, 0, NULL, 0, 392645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MOJO_WRITE_MESSAGE_FLAG_NONE); 393645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (result == MOJO_RESULT_FAILED_PRECONDITION) { 394645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Mojo EDK is shutting down. 395645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez event_.Signal(); 396645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 397645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 398645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 399645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // If we can't write we likely won't wake up the thread and there is a strong 400645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // chance we'll deadlock. 401645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK_EQ(MOJO_RESULT_OK, result); 402645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 403645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 404645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezMojoDeadline MessagePumpMojo::GetDeadlineForWait( 405645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const RunState& run_state) const { 406645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const base::TimeTicks now(internal::NowTicks()); 407645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MojoDeadline deadline = TimeTicksToMojoDeadline(run_state.delayed_work_time, 408645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez now); 409645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (const Handle handle : deadline_handles_) { 410645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez auto it = handlers_.find(handle); 411645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(it != handlers_.end()); 412645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez deadline = std::min( 413645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez TimeTicksToMojoDeadline(it->second.deadline, now), deadline); 414645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 415645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return deadline; 416645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 417645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 418645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MessagePumpMojo::SignalHandleReady(Handle handle) { 419645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez auto it = handlers_.find(handle); 420645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(it != handlers_.end()); 421645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MessagePumpMojoHandler* handler = it->second.handler; 422645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 423645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez WillSignalHandler(); 424645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez handler->OnHandleReady(handle); 425645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DidSignalHandler(); 426645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 427645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 428645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MessagePumpMojo::SignalHandleError(Handle handle, MojoResult result) { 429645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez auto it = handlers_.find(handle); 430645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(it != handlers_.end()); 431645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MessagePumpMojoHandler* handler = it->second.handler; 432645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 433645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez RemoveHandler(handle); 434645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez WillSignalHandler(); 435645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez handler->OnHandleError(handle, result); 436645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DidSignalHandler(); 437645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 438645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 439645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MessagePumpMojo::WillSignalHandler() { 440645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez FOR_EACH_OBSERVER(Observer, observers_, WillSignalHandler()); 441645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 442645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 443645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MessagePumpMojo::DidSignalHandler() { 444645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez FOR_EACH_OBSERVER(Observer, observers_, DidSignalHandler()); 445645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 446645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 447645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace common 448645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace mojo 449