Chromium Code Reviews| Index: third_party/WebKit/Source/core/mojo/MojoWatcher.cpp |
| diff --git a/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp b/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp |
| index 804536d40d710b92a73294c1b43e30129550f58e..e31cc152d5823eb69c853c508497928c23e90bf4 100644 |
| --- a/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp |
| +++ b/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp |
| @@ -20,6 +20,7 @@ static void runWatchCallback(MojoWatchCallback* callback, |
| callback->call(wrappable, result); |
| } |
| +// static |
| MojoWatcher* MojoWatcher::create(mojo::Handle handle, |
| const MojoHandleSignals& signalsDict, |
| MojoWatchCallback* callback, |
| @@ -42,42 +43,16 @@ MojoWatcher* MojoWatcher::create(mojo::Handle handle, |
| return watcher; |
| } |
| -MojoWatcher::MojoWatcher(ExecutionContext* context, MojoWatchCallback* callback) |
| - : ContextLifecycleObserver(context), |
| - m_taskRunner(TaskRunnerHelper::get(TaskType::UnspecedTimer, context)), |
| - m_callback(this, callback) {} |
| - |
| MojoWatcher::~MojoWatcher() { |
| DCHECK(!m_handle.is_valid()); |
| } |
| -MojoResult MojoWatcher::watch(mojo::Handle handle, |
| - const MojoHandleSignals& signalsDict) { |
| - ::MojoHandleSignals signals = MOJO_HANDLE_SIGNAL_NONE; |
| - if (signalsDict.readable()) |
| - signals |= MOJO_HANDLE_SIGNAL_READABLE; |
| - if (signalsDict.writable()) |
| - signals |= MOJO_HANDLE_SIGNAL_WRITABLE; |
| - if (signalsDict.peerClosed()) |
| - signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; |
| - |
| - MojoResult result = |
| - MojoWatch(handle.value(), signals, &MojoWatcher::onHandleReady, |
| - reinterpret_cast<uintptr_t>(this)); |
| - if (result == MOJO_RESULT_OK) { |
| - m_handle = handle; |
| - } |
| - return result; |
| -} |
| - |
| MojoResult MojoWatcher::cancel() { |
| - if (!m_handle.is_valid()) |
| - return MOJO_RESULT_OK; |
| + if (!m_watcherHandle.is_valid()) |
| + return MOJO_RESULT_INVALID_ARGUMENT; |
| - MojoResult result = |
| - MojoCancelWatch(m_handle.value(), reinterpret_cast<uintptr_t>(this)); |
| - m_handle = mojo::Handle(); |
| - return result; |
| + m_watcherHandle.reset(); |
| + return MOJO_RESULT_OK; |
| } |
| DEFINE_TRACE(MojoWatcher) { |
| @@ -97,13 +72,76 @@ void MojoWatcher::contextDestroyed(ExecutionContext*) { |
| cancel(); |
| } |
| +MojoWatcher::MojoWatcher(ExecutionContext* context, MojoWatchCallback* callback) |
| + : ContextLifecycleObserver(context), |
| + m_taskRunner(TaskRunnerHelper::get(TaskType::UnspecedTimer, context)), |
| + m_callback(this, callback) {} |
| + |
| +MojoResult MojoWatcher::watch(mojo::Handle handle, |
| + const MojoHandleSignals& signalsDict) { |
| + ::MojoHandleSignals signals = MOJO_HANDLE_SIGNAL_NONE; |
| + if (signalsDict.readable()) |
| + signals |= MOJO_HANDLE_SIGNAL_READABLE; |
| + if (signalsDict.writable()) |
| + signals |= MOJO_HANDLE_SIGNAL_WRITABLE; |
| + if (signalsDict.peerClosed()) |
| + signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED; |
| + |
| + MojoResult rv = |
|
haraken
2017/03/14 15:10:32
Nit: rv => result
Blink prefers a fully qualified
Ken Rockot(use gerrit already)
2017/03/14 15:52:21
Done
|
| + mojo::CreateWatcher(&MojoWatcher::onHandleReady, &m_watcherHandle); |
| + DCHECK_EQ(MOJO_RESULT_OK, rv); |
| + |
| + rv = MojoWatch(m_watcherHandle.get().value(), handle.value(), signals, |
| + reinterpret_cast<uintptr_t>(this)); |
| + if (rv != MOJO_RESULT_OK) |
| + return rv; |
| + |
| + m_handle = handle; |
| + |
| + MojoResult readyResult; |
| + rv = arm(&readyResult); |
| + if (rv == MOJO_RESULT_OK) |
| + return rv; |
| + |
| + // We couldn't arm the watcher because the handle is already ready to |
| + // trigger a success notification. Post a notification manually. |
| + DCHECK_EQ(MOJO_RESULT_FAILED_PRECONDITION, rv); |
| + m_taskRunner->postTask(BLINK_FROM_HERE, |
| + WTF::bind(&MojoWatcher::runReadyCallback, |
| + wrapPersistent(this), readyResult)); |
| + return MOJO_RESULT_OK; |
| +} |
| + |
| +MojoResult MojoWatcher::arm(MojoResult* readyResult) { |
| + // Nothing to do if the watcher is inactive. |
| + if (!m_handle.is_valid()) |
| + return MOJO_RESULT_OK; |
| + |
| + uint32_t numReadyContexts = 1; |
| + uintptr_t readyContext; |
| + MojoResult localReadyResult; |
| + MojoHandleSignalsState readySignals; |
| + MojoResult rv = |
| + MojoArmWatcher(m_watcherHandle.get().value(), &numReadyContexts, |
| + &readyContext, &localReadyResult, &readySignals); |
| + if (rv == MOJO_RESULT_OK) |
| + return MOJO_RESULT_OK; |
| + |
| + DCHECK_EQ(MOJO_RESULT_FAILED_PRECONDITION, rv); |
| + DCHECK_EQ(1u, numReadyContexts); |
| + DCHECK_EQ(reinterpret_cast<uintptr_t>(this), readyContext); |
| + *readyResult = localReadyResult; |
| + return rv; |
| +} |
| + |
| void MojoWatcher::onHandleReady(uintptr_t context, |
| MojoResult result, |
| MojoHandleSignalsState, |
| - MojoWatchNotificationFlags) { |
| - // It is safe to assume the MojoWatcher still exists because this |
| - // callback will never be run after MojoWatcher destructor, |
| - // which cancels the watch. |
| + MojoWatcherNotificationFlags) { |
| + // It is safe to assume the MojoWatcher still exists. It stays alive at least |
| + // as long as |m_handle| is valid, and |m_handle| is only reset after we |
| + // dispatch a |MOJO_RESULT_CANCELLED| notification. That is always the last |
| + // notification received by this callback. |
| MojoWatcher* watcher = reinterpret_cast<MojoWatcher*>(context); |
| watcher->m_taskRunner->postTask( |
| BLINK_FROM_HERE, |
| @@ -112,17 +150,41 @@ void MojoWatcher::onHandleReady(uintptr_t context, |
| } |
| void MojoWatcher::runReadyCallback(MojoResult result) { |
| - // Ignore callbacks if not watching. |
| - if (!m_handle.is_valid()) |
| + if (result == MOJO_RESULT_CANCELLED) { |
| + // Last notification. |
| + m_handle = mojo::Handle(); |
| + |
| + // Only dispatch to the callback if this cancellation was implicit due to |
| + // |m_handle| closure. If it was explicit, |m_watcherHandle| has already |
| + // been reset. |
| + if (m_watcherHandle.is_valid()) { |
| + m_watcherHandle.reset(); |
| + runWatchCallback(m_callback, this, result); |
| + } |
| return; |
| + } |
| - // MOJO_RESULT_CANCELLED indicates that the handle has been closed, in which |
| - // case watch has been implicitly cancelled. There is no need to explicitly |
| - // cancel the watch. |
| - if (result == MOJO_RESULT_CANCELLED) |
| - m_handle = mojo::Handle(); |
| + // Ignore callbacks if not watching. |
| + if (!m_watcherHandle.is_valid()) |
| + return; |
| runWatchCallback(m_callback, this, result); |
| + |
| + // Rearm the watcher so another notification can fire. |
| + // |
| + // TODO(rockot): MojoWatcher should expose some better approximation of the |
| + // new watcher API, including explicit add and removal of handles from the |
| + // watcher, as well as explicit arming. |
| + MojoResult readyResult; |
| + MojoResult rv = arm(&readyResult); |
| + if (rv == MOJO_RESULT_OK) |
| + return; |
| + |
| + DCHECK_EQ(MOJO_RESULT_FAILED_PRECONDITION, rv); |
| + |
| + m_taskRunner->postTask(BLINK_FROM_HERE, |
| + WTF::bind(&MojoWatcher::runReadyCallback, |
| + wrapWeakPersistent(this), readyResult)); |
| } |
| } // namespace blink |