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