1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file. 4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "mojo/common/message_pump_mojo.h" 6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <algorithm> 8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <vector> 9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/debug/alias.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/lazy_instance.h" 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/threading/thread_local.h" 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/time/time.h" 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "mojo/common/message_pump_mojo_handler.h" 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "mojo/common/time_helper.h" 17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace mojo { 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace common { 206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace { 216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibase::LazyInstance<base::ThreadLocalPointer<MessagePumpMojo> >::Leaky 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci g_tls_current_pump = LAZY_INSTANCE_INITIALIZER; 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)MojoDeadline TimeTicksToMojoDeadline(base::TimeTicks time_ticks, 266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::TimeTicks now) { 276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // The is_null() check matches that of HandleWatcher as well as how 286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // |delayed_work_time| is used. 296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (time_ticks.is_null()) 306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return MOJO_DEADLINE_INDEFINITE; 316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const int64_t delta = (time_ticks - now).InMicroseconds(); 326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return delta < 0 ? static_cast<MojoDeadline>(0) : 336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) static_cast<MojoDeadline>(delta); 346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} // namespace 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// State needed for one iteration of WaitMany. The first handle and flags 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// corresponds to that of the control pipe. 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)struct MessagePumpMojo::WaitState { 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::vector<Handle> handles; 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<MojoHandleSignals> wait_signals; 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}; 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)struct MessagePumpMojo::RunState { 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) RunState() : should_quit(false) { 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CreateMessagePipe(NULL, &read_handle, &write_handle); 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::TimeTicks delayed_work_time; 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Used to wake up WaitForWork(). 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ScopedMessagePipeHandle read_handle; 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ScopedMessagePipeHandle write_handle; 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool should_quit; 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}; 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)MessagePumpMojo::MessagePumpMojo() : run_state_(NULL), next_handler_id_(0) { 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(!current()) 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << "There is already a MessagePumpMojo instance on this thread."; 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci g_tls_current_pump.Pointer()->Set(this); 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)MessagePumpMojo::~MessagePumpMojo() { 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(this, current()); 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci g_tls_current_pump.Pointer()->Set(NULL); 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 7023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// static 7123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)scoped_ptr<base::MessagePump> MessagePumpMojo::Create() { 7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return scoped_ptr<MessagePump>(new MessagePumpMojo()); 7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciMessagePumpMojo* MessagePumpMojo::current() { 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return g_tls_current_pump.Pointer()->Get(); 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MessagePumpMojo::AddHandler(MessagePumpMojoHandler* handler, 81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const Handle& handle, 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MojoHandleSignals wait_signals, 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::TimeTicks deadline) { 846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CHECK(handler); 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(handle.is_valid()); 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Assume it's an error if someone tries to reregister an existing handle. 876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CHECK_EQ(0u, handlers_.count(handle)); 88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Handler handler_data; 89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) handler_data.handler = handler; 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) handler_data.wait_signals = wait_signals; 91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) handler_data.deadline = deadline; 92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) handler_data.id = next_handler_id_++; 93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) handlers_[handle] = handler_data; 94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MessagePumpMojo::RemoveHandler(const Handle& handle) { 97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) handlers_.erase(handle); 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MessagePumpMojo::Run(Delegate* delegate) { 101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) RunState run_state; 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // TODO: better deal with error handling. 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CHECK(run_state.read_handle.is_valid()); 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CHECK(run_state.write_handle.is_valid()); 1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RunState* old_state = NULL; 1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::AutoLock auto_lock(run_state_lock_); 1080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch old_state = run_state_; 1090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch run_state_ = &run_state; 1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DoRunLoop(&run_state, delegate); 1120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch { 1130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::AutoLock auto_lock(run_state_lock_); 1140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch run_state_ = old_state; 1150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid MessagePumpMojo::Quit() { 1190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::AutoLock auto_lock(run_state_lock_); 1200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (run_state_) 1210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch run_state_->should_quit = true; 1220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid MessagePumpMojo::ScheduleWork() { 1250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::AutoLock auto_lock(run_state_lock_); 1260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (run_state_) 1270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch SignalControlPipe(*run_state_); 1280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid MessagePumpMojo::ScheduleDelayedWork( 1310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const base::TimeTicks& delayed_work_time) { 1320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::AutoLock auto_lock(run_state_lock_); 1330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!run_state_) 1340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch run_state_->delayed_work_time = delayed_work_time; 1360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid MessagePumpMojo::DoRunLoop(RunState* run_state, Delegate* delegate) { 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool more_work_is_plausible = true; 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (;;) { 141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const bool block = !more_work_is_plausible; 1420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DoInternalWork(*run_state, block); 143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // There isn't a good way to know if there are more handles ready, we assume 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // not. 146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) more_work_is_plausible = false; 147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (run_state->should_quit) 149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) break; 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) more_work_is_plausible |= delegate->DoWork(); 1520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (run_state->should_quit) 153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) break; 154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) more_work_is_plausible |= delegate->DoDelayedWork( 1560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &run_state->delayed_work_time); 1570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (run_state->should_quit) 158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) break; 159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (more_work_is_plausible) 161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) continue; 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) more_work_is_plausible = delegate->DoIdleWork(); 1640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (run_state->should_quit) 165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) break; 166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid MessagePumpMojo::DoInternalWork(const RunState& run_state, bool block) { 1700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const MojoDeadline deadline = block ? GetDeadlineForWait(run_state) : 0; 1710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const WaitState wait_state = GetWaitState(run_state); 172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const MojoResult result = 173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) WaitMany(wait_state.handles, wait_state.wait_signals, deadline); 174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (result == 0) { 175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Control pipe was written to. 176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uint32_t num_bytes = 0; 1770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReadMessageRaw(run_state.read_handle.get(), NULL, &num_bytes, NULL, NULL, 178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) MOJO_READ_MESSAGE_FLAG_MAY_DISCARD); 179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else if (result > 0) { 180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const size_t index = static_cast<size_t>(result); 181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(handlers_.find(wait_state.handles[index]) != handlers_.end()); 182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) handlers_[wait_state.handles[index]].handler->OnHandleReady( 183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) wait_state.handles[index]); 184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) switch (result) { 186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case MOJO_RESULT_CANCELLED: 187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case MOJO_RESULT_FAILED_PRECONDITION: 188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) RemoveFirstInvalidHandle(wait_state); 189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) break; 190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case MOJO_RESULT_DEADLINE_EXCEEDED: 191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) break; 192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) default: 193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::debug::Alias(&result); 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Unexpected result is likely fatal, crash so we can determine cause. 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CHECK(false); 196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Notify and remove any handlers whose time has expired. Make a copy in case 200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // someone tries to add/remove new handlers from notification. 201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const HandleToHandler cloned_handlers(handlers_); 202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::TimeTicks now(internal::NowTicks()); 203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (HandleToHandler::const_iterator i = cloned_handlers.begin(); 204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) i != cloned_handlers.end(); ++i) { 205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Since we're iterating over a clone of the handlers, verify the handler is 206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // still valid before notifying. 207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!i->second.deadline.is_null() && i->second.deadline < now && 208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) handlers_.find(i->first) != handlers_.end() && 209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) handlers_[i->first].id == i->second.id) { 210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) i->second.handler->OnHandleError(i->first, MOJO_RESULT_DEADLINE_EXCEEDED); 211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MessagePumpMojo::RemoveFirstInvalidHandle(const WaitState& wait_state) { 216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // TODO(sky): deal with control pipe going bad. 2176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) for (size_t i = 0; i < wait_state.handles.size(); ++i) { 218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const MojoResult result = 219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Wait(wait_state.handles[i], wait_state.wait_signals[i], 0); 2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (result == MOJO_RESULT_INVALID_ARGUMENT) { 2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // We should never have an invalid argument. If we do it indicates 2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // RemoveHandler() was not invoked and is likely to cause problems else 2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // where in the stack if we ignore it. 2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CHECK(false); 2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else if (result == MOJO_RESULT_FAILED_PRECONDITION || 2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result == MOJO_RESULT_CANCELLED) { 2276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CHECK_NE(i, 0u); // Indicates the control pipe went bad. 2286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Remove the handle first, this way if OnHandleError() tries to remove 230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // the handle our iterator isn't invalidated. 2316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CHECK(handlers_.find(wait_state.handles[i]) != handlers_.end()); 232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) MessagePumpMojoHandler* handler = 233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) handlers_[wait_state.handles[i]].handler; 234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) handlers_.erase(wait_state.handles[i]); 235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) handler->OnHandleError(wait_state.handles[i], result); 236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid MessagePumpMojo::SignalControlPipe(const RunState& run_state) { 2426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const MojoResult result = 2436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) WriteMessageRaw(run_state.write_handle.get(), NULL, 0, NULL, 0, 2446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) MOJO_WRITE_MESSAGE_FLAG_NONE); 2456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // If we can't write we likely won't wake up the thread and there is a strong 2466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // chance we'll deadlock. 2476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CHECK_EQ(MOJO_RESULT_OK, result); 248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2500529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochMessagePumpMojo::WaitState MessagePumpMojo::GetWaitState( 2510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const RunState& run_state) const { 252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) WaitState wait_state; 2530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch wait_state.handles.push_back(run_state.read_handle.get()); 254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) wait_state.wait_signals.push_back(MOJO_HANDLE_SIGNAL_READABLE); 255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (HandleToHandler::const_iterator i = handlers_.begin(); 257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) i != handlers_.end(); ++i) { 258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) wait_state.handles.push_back(i->first); 259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) wait_state.wait_signals.push_back(i->second.wait_signals); 260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return wait_state; 262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2640529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochMojoDeadline MessagePumpMojo::GetDeadlineForWait( 2650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const RunState& run_state) const { 2666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const base::TimeTicks now(internal::NowTicks()); 2676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) MojoDeadline deadline = TimeTicksToMojoDeadline(run_state.delayed_work_time, 2686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) now); 269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (HandleToHandler::const_iterator i = handlers_.begin(); 270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) i != handlers_.end(); ++i) { 2716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) deadline = std::min( 2726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) TimeTicksToMojoDeadline(i->second.deadline, now), deadline); 273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 2746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return deadline; 275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 277f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace common 278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace mojo 279