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/handle_watcher.h"
6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <map>
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/atomic_sequence_num.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/bind.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/lazy_instance.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/logging.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/macros.h"
14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/memory/singleton.h"
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/weak_ptr.h"
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/message_loop/message_loop.h"
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
18e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/synchronization/lock.h"
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/synchronization/waitable_event.h"
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/threading/thread.h"
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/threading/thread_restrictions.h"
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/time/time.h"
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "mojo/common/message_pump_mojo.h"
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "mojo/common/message_pump_mojo_handler.h"
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "mojo/common/time_helper.h"
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace mojo {
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace common {
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)typedef int WatcherID;
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace {
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char kWatcherThreadName[] = "handle-watcher-thread";
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::TimeTicks MojoDeadlineToTimeTicks(MojoDeadline deadline) {
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return deadline == MOJO_DEADLINE_INDEFINITE ? base::TimeTicks() :
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      internal::NowTicks() + base::TimeDelta::FromMicroseconds(deadline);
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Tracks the data for a single call to Start().
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)struct WatchData {
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WatchData()
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      : id(0),
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        handle_signals(MOJO_HANDLE_SIGNAL_NONE),
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        message_loop(NULL) {}
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WatcherID id;
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Handle handle;
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MojoHandleSignals handle_signals;
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::TimeTicks deadline;
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::Callback<void(MojoResult)> callback;
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> message_loop;
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// WatcherBackend --------------------------------------------------------------
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// WatcherBackend is responsible for managing the requests and interacting with
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// MessagePumpMojo. All access (outside of creation/destruction) is done on the
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// thread WatcherThreadManager creates.
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class WatcherBackend : public MessagePumpMojoHandler {
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WatcherBackend();
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual ~WatcherBackend();
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void StartWatching(const WatchData& data);
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Cancels a previously scheduled request to start a watch.
6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  void StopWatching(WatcherID watcher_id);
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private:
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  typedef std::map<Handle, WatchData> HandleToWatchDataMap;
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Invoked when a handle needs to be removed and notified.
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void RemoveAndNotify(const Handle& handle, MojoResult result);
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Searches through |handle_to_data_| for |watcher_id|. Returns true if found
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // and sets |handle| to the Handle. Returns false if not a known id.
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool GetMojoHandleByWatcherID(WatcherID watcher_id, Handle* handle) const;
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // MessagePumpMojoHandler overrides:
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnHandleReady(const Handle& handle) OVERRIDE;
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnHandleError(const Handle& handle, MojoResult result) OVERRIDE;
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Maps from assigned id to WatchData.
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  HandleToWatchDataMap handle_to_data_;
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(WatcherBackend);
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)WatcherBackend::WatcherBackend() {
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)WatcherBackend::~WatcherBackend() {
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void WatcherBackend::StartWatching(const WatchData& data) {
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RemoveAndNotify(data.handle, MOJO_RESULT_CANCELLED);
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(0u, handle_to_data_.count(data.handle));
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  handle_to_data_[data.handle] = data;
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MessagePumpMojo::current()->AddHandler(this, data.handle,
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         data.handle_signals,
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         data.deadline);
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
10803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void WatcherBackend::StopWatching(WatcherID watcher_id) {
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Because of the thread hop it is entirely possible to get here and not
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // have a valid handle registered for |watcher_id|.
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Handle handle;
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (GetMojoHandleByWatcherID(watcher_id, &handle)) {
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    handle_to_data_.erase(handle);
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    MessagePumpMojo::current()->RemoveHandler(handle);
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void WatcherBackend::RemoveAndNotify(const Handle& handle,
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     MojoResult result) {
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (handle_to_data_.count(handle) == 0)
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const WatchData data(handle_to_data_[handle]);
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  handle_to_data_.erase(handle);
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MessagePumpMojo::current()->RemoveHandler(handle);
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  data.message_loop->PostTask(FROM_HERE, base::Bind(data.callback, result));
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool WatcherBackend::GetMojoHandleByWatcherID(WatcherID watcher_id,
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                              Handle* handle) const {
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (HandleToWatchDataMap::const_iterator i = handle_to_data_.begin();
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       i != handle_to_data_.end(); ++i) {
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (i->second.id == watcher_id) {
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      *handle = i->second.handle;
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return true;
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return false;
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void WatcherBackend::OnHandleReady(const Handle& handle) {
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RemoveAndNotify(handle, MOJO_RESULT_OK);
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void WatcherBackend::OnHandleError(const Handle& handle, MojoResult result) {
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RemoveAndNotify(handle, result);
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// WatcherThreadManager --------------------------------------------------------
150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// WatcherThreadManager manages the background thread that listens for handles
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// to be ready. All requests are handled by WatcherBackend.
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class WatcherThreadManager {
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
157e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  ~WatcherThreadManager();
158e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Returns the shared instance.
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static WatcherThreadManager* GetInstance();
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Starts watching the requested handle. Returns a unique ID that is used to
163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // stop watching the handle. When the handle is ready |callback| is notified
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // on the thread StartWatching() was invoked on.
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // This may be invoked on any thread.
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WatcherID StartWatching(const Handle& handle,
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                          MojoHandleSignals handle_signals,
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          base::TimeTicks deadline,
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          const base::Callback<void(MojoResult)>& callback);
170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Stops watching a handle.
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // This may be invoked on any thread.
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void StopWatching(WatcherID watcher_id);
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private:
17603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  enum RequestType {
17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    REQUEST_START,
17803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    REQUEST_STOP,
17903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  };
18003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
18103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // See description of |requests_| for details.
18203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  struct RequestData {
18303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    RequestData() : type(REQUEST_START), stop_id(0), stop_event(NULL) {}
18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
18503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    RequestType type;
18603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    WatchData start_data;
18703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    WatcherID stop_id;
18803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::WaitableEvent* stop_event;
18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  };
19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
19103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  typedef std::vector<RequestData> Requests;
19203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  friend struct DefaultSingletonTraits<WatcherThreadManager>;
19403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WatcherThreadManager();
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
19703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Schedules a request on the background thread. See |requests_| for details.
19803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  void AddRequest(const RequestData& data);
19903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
20003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Processes requests added to |requests_|. This is invoked on the backend
20103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // thread.
20203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  void ProcessRequestsOnBackendThread();
20303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::Thread thread_;
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::AtomicSequenceNumber watcher_id_generator_;
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WatcherBackend backend_;
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
21003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Protects |requests_|.
21103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::Lock lock_;
21203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
21303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Start/Stop result in adding a RequestData to |requests_| (protected by
21403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // |lock_|). When the background thread wakes up it processes the requests.
21503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  Requests requests_;
21603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(WatcherThreadManager);
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
220e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochWatcherThreadManager::~WatcherThreadManager() {
221e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  thread_.Stop();
222e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
223e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)WatcherThreadManager* WatcherThreadManager::GetInstance() {
225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return Singleton<WatcherThreadManager>::get();
226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)WatcherID WatcherThreadManager::StartWatching(
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const Handle& handle,
230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    MojoHandleSignals handle_signals,
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::TimeTicks deadline,
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const base::Callback<void(MojoResult)>& callback) {
23303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  RequestData request_data;
23403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request_data.type = REQUEST_START;
23503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request_data.start_data.id = watcher_id_generator_.GetNext();
23603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request_data.start_data.handle = handle;
23703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request_data.start_data.callback = callback;
23803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request_data.start_data.handle_signals = handle_signals;
23903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request_data.start_data.deadline = deadline;
24003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request_data.start_data.message_loop = base::MessageLoopProxy::current();
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_NE(static_cast<base::MessageLoopProxy*>(NULL),
24203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            request_data.start_data.message_loop.get());
24303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  AddRequest(request_data);
24403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return request_data.start_data.id;
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void WatcherThreadManager::StopWatching(WatcherID watcher_id) {
24803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Handle the case of StartWatching() followed by StopWatching() before
24903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // |thread_| woke up.
25003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  {
25103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::AutoLock auto_lock(lock_);
25203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    for (Requests::iterator i = requests_.begin(); i != requests_.end(); ++i) {
25303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      if (i->type == REQUEST_START && i->start_data.id == watcher_id) {
25403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        // Watcher ids are not reused, so if we find it we can stop.
25503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        requests_.erase(i);
25603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        return;
25703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      }
25803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
25903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
26003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::ThreadRestrictions::ScopedAllowWait allow_wait;
2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::WaitableEvent event(true, false);
26303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  RequestData request_data;
26403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request_data.type = REQUEST_STOP;
26503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request_data.stop_id = watcher_id;
26603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  request_data.stop_event = &event;
26703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  AddRequest(request_data);
26803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
26903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // We need to block until the handle is actually removed.
27003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  event.Wait();
27103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
27203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
27303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void WatcherThreadManager::AddRequest(const RequestData& data) {
27403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  {
27503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::AutoLock auto_lock(lock_);
27603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const bool was_empty = requests_.empty();
27703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    requests_.push_back(data);
27803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (!was_empty)
27903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return;
28003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // We own |thread_|, so it's safe to use Unretained() here.
282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  thread_.message_loop()->PostTask(
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FROM_HERE,
28403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      base::Bind(&WatcherThreadManager::ProcessRequestsOnBackendThread,
28503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                 base::Unretained(this)));
28603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
28803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void WatcherThreadManager::ProcessRequestsOnBackendThread() {
28903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DCHECK_EQ(thread_.message_loop(), base::MessageLoop::current());
29003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
29103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  Requests requests;
29203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  {
29303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::AutoLock auto_lock(lock_);
29403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    requests_.swap(requests);
29503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
29603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (size_t i = 0; i < requests.size(); ++i) {
29703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (requests[i].type == REQUEST_START) {
29803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      backend_.StartWatching(requests[i].start_data);
29903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    } else {
30003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      backend_.StopWatching(requests[i].stop_id);
30103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      requests[i].stop_event->Signal();
30203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
30303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)WatcherThreadManager::WatcherThreadManager()
307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : thread_(kWatcherThreadName) {
308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::Thread::Options thread_options;
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  thread_options.message_pump_factory = base::Bind(&MessagePumpMojo::Create);
310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  thread_.StartWithOptions(thread_options);
311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// HandleWatcher::StateBase and subclasses -------------------------------------
314f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// The base class of HandleWatcher's state. Owns the user's callback and
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// monitors the current thread's MessageLoop to know when to force the callback
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// to run (with an error) even though the pipe hasn't been signaled yet.
3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass HandleWatcher::StateBase : public base::MessageLoop::DestructionObserver {
319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  StateBase(HandleWatcher* watcher,
3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            const base::Callback<void(MojoResult)>& callback)
322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      : watcher_(watcher),
323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        callback_(callback),
3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        got_ready_(false) {
325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::MessageLoop::current()->AddDestructionObserver(this);
326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual ~StateBase() {
329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::MessageLoop::current()->RemoveDestructionObserver(this);
3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci protected:
3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void NotifyHandleReady(MojoResult result) {
3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    got_ready_ = true;
3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    NotifyAndDestroy(result);
336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
337f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool got_ready() const { return got_ready_; }
3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private:
341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void WillDestroyCurrentMessageLoop() OVERRIDE {
342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // The current thread is exiting. Simulate a watch error.
34303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    NotifyAndDestroy(MOJO_RESULT_ABORTED);
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
34603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  void NotifyAndDestroy(MojoResult result) {
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::Callback<void(MojoResult)> callback = callback_;
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    watcher_->Stop();  // Destroys |this|.
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    callback.Run(result);
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  HandleWatcher* watcher_;
354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::Callback<void(MojoResult)> callback_;
355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
35603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Have we been notified that the handle is ready?
35703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  bool got_ready_;
35803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DISALLOW_COPY_AND_ASSIGN(StateBase);
3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// If the thread on which HandleWatcher is used runs MessagePumpMojo,
3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// SameThreadWatchingState is used to directly watch the handle on the same
3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// thread.
3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass HandleWatcher::SameThreadWatchingState : public StateBase,
3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                               public MessagePumpMojoHandler {
3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public:
3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SameThreadWatchingState(HandleWatcher* watcher,
3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          const Handle& handle,
3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          MojoHandleSignals handle_signals,
3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          MojoDeadline deadline,
3721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          const base::Callback<void(MojoResult)>& callback)
3731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      : StateBase(watcher, callback),
3741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        handle_(handle) {
3751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK(MessagePumpMojo::IsCurrent());
3761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    MessagePumpMojo::current()->AddHandler(
3781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        this, handle, handle_signals, MojoDeadlineToTimeTicks(deadline));
3791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual ~SameThreadWatchingState() {
3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!got_ready())
3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MessagePumpMojo::current()->RemoveHandler(handle_);
3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private:
3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // MessagePumpMojoHandler overrides:
3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnHandleReady(const Handle& handle) OVERRIDE {
3891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    StopWatchingAndNotifyReady(handle, MOJO_RESULT_OK);
3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnHandleError(const Handle& handle, MojoResult result) OVERRIDE {
3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    StopWatchingAndNotifyReady(handle, result);
3941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void StopWatchingAndNotifyReady(const Handle& handle, MojoResult result) {
3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK_EQ(handle.value(), handle_.value());
3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    MessagePumpMojo::current()->RemoveHandler(handle_);
3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    NotifyHandleReady(result);
4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Handle handle_;
4031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DISALLOW_COPY_AND_ASSIGN(SameThreadWatchingState);
4051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
4061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// If the thread on which HandleWatcher is used runs a message pump different
4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// from MessagePumpMojo, SecondaryThreadWatchingState is used to watch the
4091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// handle on the handle watcher thread.
4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass HandleWatcher::SecondaryThreadWatchingState : public StateBase {
4111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public:
4121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SecondaryThreadWatchingState(HandleWatcher* watcher,
4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               const Handle& handle,
4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               MojoHandleSignals handle_signals,
4151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               MojoDeadline deadline,
4161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               const base::Callback<void(MojoResult)>& callback)
4171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      : StateBase(watcher, callback),
4181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        weak_factory_(this) {
4191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    watcher_id_ = WatcherThreadManager::GetInstance()->StartWatching(
4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        handle,
4211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        handle_signals,
4221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        MojoDeadlineToTimeTicks(deadline),
4231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(&SecondaryThreadWatchingState::NotifyHandleReady,
4241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   weak_factory_.GetWeakPtr()));
4251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual ~SecondaryThreadWatchingState() {
4281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // If we've been notified the handle is ready (|got_ready()| is true) then
4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // the watch has been implicitly removed by
4301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // WatcherThreadManager/MessagePumpMojo and we don't have to call
4311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // StopWatching(). To do so would needlessly entail posting a task and
4321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // blocking until the background thread services it.
4331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!got_ready())
4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      WatcherThreadManager::GetInstance()->StopWatching(watcher_id_);
4351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private:
4381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  WatcherID watcher_id_;
4391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Used to weakly bind |this| to the WatcherThreadManager.
4411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::WeakPtrFactory<SecondaryThreadWatchingState> weak_factory_;
4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DISALLOW_COPY_AND_ASSIGN(SecondaryThreadWatchingState);
444f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
445f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
446f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// HandleWatcher ---------------------------------------------------------------
447f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
448f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)HandleWatcher::HandleWatcher() {
449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
450f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
451f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)HandleWatcher::~HandleWatcher() {
452f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
453f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
454f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void HandleWatcher::Start(const Handle& handle,
455f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                          MojoHandleSignals handle_signals,
456f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          MojoDeadline deadline,
457f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          const base::Callback<void(MojoResult)>& callback) {
458f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(handle.is_valid());
459f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK_NE(MOJO_HANDLE_SIGNAL_NONE, handle_signals);
460f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (MessagePumpMojo::IsCurrent()) {
4621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    state_.reset(new SameThreadWatchingState(
4631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        this, handle, handle_signals, deadline, callback));
4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
4651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    state_.reset(new SecondaryThreadWatchingState(
4661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        this, handle, handle_signals, deadline, callback));
4671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
468f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
469f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
470f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void HandleWatcher::Stop() {
471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  state_.reset();
472f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
473f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
474f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace common
475f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace mojo
476