| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "mojo/public/cpp/system/watcher.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/location.h" | |
| 9 #include "base/macros.h" | |
| 10 #include "base/message_loop/message_loop.h" | |
| 11 #include "base/thread_task_runner_handle.h" | |
| 12 #include "mojo/public/c/system/functions.h" | |
| 13 | |
| 14 namespace mojo { | |
| 15 | |
| 16 class Watcher::MessageLoopObserver | |
| 17 : public base::MessageLoop::DestructionObserver { | |
| 18 public: | |
| 19 explicit MessageLoopObserver(Watcher* watcher) : watcher_(watcher) { | |
| 20 base::MessageLoop::current()->AddDestructionObserver(this); | |
| 21 } | |
| 22 | |
| 23 ~MessageLoopObserver() override { | |
| 24 StopObservingIfNecessary(); | |
| 25 } | |
| 26 | |
| 27 private: | |
| 28 // base::MessageLoop::DestructionObserver: | |
| 29 void WillDestroyCurrentMessageLoop() override { | |
| 30 StopObservingIfNecessary(); | |
| 31 if (watcher_->IsWatching()) | |
| 32 watcher_->OnHandleReady(MOJO_RESULT_ABORTED); | |
| 33 } | |
| 34 | |
| 35 void StopObservingIfNecessary() { | |
| 36 if (is_observing_) { | |
| 37 is_observing_ = false; | |
| 38 base::MessageLoop::current()->RemoveDestructionObserver(this); | |
| 39 } | |
| 40 } | |
| 41 | |
| 42 bool is_observing_ = true; | |
| 43 Watcher* watcher_; | |
| 44 | |
| 45 DISALLOW_COPY_AND_ASSIGN(MessageLoopObserver); | |
| 46 }; | |
| 47 | |
| 48 Watcher::Watcher() | |
| 49 : task_runner_(base::ThreadTaskRunnerHandle::Get()), | |
| 50 weak_factory_(this) { | |
| 51 weak_self_ = weak_factory_.GetWeakPtr(); | |
| 52 } | |
| 53 | |
| 54 Watcher::~Watcher() { | |
| 55 if(IsWatching()) | |
| 56 Cancel(); | |
| 57 } | |
| 58 | |
| 59 bool Watcher::IsWatching() const { | |
| 60 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 61 return handle_.is_valid(); | |
| 62 } | |
| 63 | |
| 64 MojoResult Watcher::Start(Handle handle, | |
| 65 MojoHandleSignals signals, | |
| 66 const ReadyCallback& callback) { | |
| 67 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 68 DCHECK(!IsWatching()); | |
| 69 DCHECK(!callback.is_null()); | |
| 70 | |
| 71 message_loop_observer_.reset(new MessageLoopObserver(this)); | |
| 72 callback_ = callback; | |
| 73 handle_ = handle; | |
| 74 MojoResult result = MojoWatch(handle_.value(), signals, | |
| 75 &Watcher::CallOnHandleReady, | |
| 76 reinterpret_cast<uintptr_t>(this)); | |
| 77 if (result != MOJO_RESULT_OK) { | |
| 78 handle_.set_value(kInvalidHandleValue); | |
| 79 callback_.Reset(); | |
| 80 message_loop_observer_.reset(); | |
| 81 DCHECK(result == MOJO_RESULT_FAILED_PRECONDITION || | |
| 82 result == MOJO_RESULT_INVALID_ARGUMENT); | |
| 83 return result; | |
| 84 } | |
| 85 | |
| 86 return MOJO_RESULT_OK; | |
| 87 } | |
| 88 | |
| 89 void Watcher::Cancel() { | |
| 90 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 91 | |
| 92 // The watch may have already been cancelled if the handle was closed. | |
| 93 if (!handle_.is_valid()) | |
| 94 return; | |
| 95 | |
| 96 MojoResult result = | |
| 97 MojoCancelWatch(handle_.value(), reinterpret_cast<uintptr_t>(this)); | |
| 98 message_loop_observer_.reset(); | |
| 99 DCHECK_EQ(result, MOJO_RESULT_OK); | |
| 100 handle_.set_value(kInvalidHandleValue); | |
| 101 callback_.Reset(); | |
| 102 } | |
| 103 | |
| 104 void Watcher::OnHandleReady(MojoResult result) { | |
| 105 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 106 | |
| 107 ReadyCallback callback = callback_; | |
| 108 if (result == MOJO_RESULT_CANCELLED) { | |
| 109 message_loop_observer_.reset(); | |
| 110 handle_.set_value(kInvalidHandleValue); | |
| 111 callback_.Reset(); | |
| 112 } | |
| 113 | |
| 114 // NOTE: It's legal for |callback| to delete |this|. | |
| 115 if (!callback.is_null()) | |
| 116 callback.Run(result); | |
| 117 } | |
| 118 | |
| 119 // static | |
| 120 void Watcher::CallOnHandleReady(uintptr_t context, | |
| 121 MojoResult result, | |
| 122 MojoHandleSignalsState signals_state) { | |
| 123 // NOTE: It is safe to assume the Watcher still exists because this callback | |
| 124 // will never be run after the Watcher's destructor. | |
| 125 // | |
| 126 // TODO: Maybe we should also expose |signals_state| throught he Watcher API. | |
| 127 // Current HandleWatcher users have no need for it, so it's omitted here. | |
| 128 Watcher* watcher = reinterpret_cast<Watcher*>(context); | |
| 129 watcher->task_runner_->PostTask( | |
| 130 FROM_HERE, | |
| 131 base::Bind(&Watcher::OnHandleReady, watcher->weak_self_, result)); | |
| 132 } | |
| 133 | |
| 134 } // namespace mojo | |
| OLD | NEW |