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