| Index: mojo/public/cpp/system/simple_watcher.cc
|
| diff --git a/mojo/public/cpp/system/simple_watcher.cc b/mojo/public/cpp/system/simple_watcher.cc
|
| deleted file mode 100644
|
| index 218a350fc95237d462c0b01bf7205c49921bd3a9..0000000000000000000000000000000000000000
|
| --- a/mojo/public/cpp/system/simple_watcher.cc
|
| +++ /dev/null
|
| @@ -1,273 +0,0 @@
|
| -// Copyright 2017 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "mojo/public/cpp/system/simple_watcher.h"
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/macros.h"
|
| -#include "base/memory/ptr_util.h"
|
| -#include "base/single_thread_task_runner.h"
|
| -#include "base/synchronization/lock.h"
|
| -#include "base/trace_event/heap_profiler.h"
|
| -#include "mojo/public/c/system/watcher.h"
|
| -
|
| -namespace mojo {
|
| -
|
| -// Thread-safe Context object used to dispatch watch notifications from a
|
| -// arbitrary threads.
|
| -class SimpleWatcher::Context : public base::RefCountedThreadSafe<Context> {
|
| - public:
|
| - // Creates a |Context| instance for a new watch on |watcher|, to watch
|
| - // |handle| for |signals|.
|
| - static scoped_refptr<Context> Create(
|
| - base::WeakPtr<SimpleWatcher> watcher,
|
| - scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
| - WatcherHandle watcher_handle,
|
| - Handle handle,
|
| - MojoHandleSignals signals,
|
| - MojoResult* watch_result) {
|
| - scoped_refptr<Context> context = new Context(watcher, task_runner);
|
| -
|
| - // If MojoWatch succeeds, it assumes ownership of a reference to |context|.
|
| - // In that case, this reference is balanced in CallNotify() when |result| is
|
| - // |MOJO_RESULT_CANCELLED|.
|
| - context->AddRef();
|
| -
|
| - *watch_result = MojoWatch(watcher_handle.value(), handle.value(), signals,
|
| - context->value());
|
| - if (*watch_result != MOJO_RESULT_OK) {
|
| - // Balanced by the AddRef() above since watching failed.
|
| - context->Release();
|
| - return nullptr;
|
| - }
|
| -
|
| - return context;
|
| - }
|
| -
|
| - static void CallNotify(uintptr_t context_value,
|
| - MojoResult result,
|
| - MojoHandleSignalsState signals_state,
|
| - MojoWatcherNotificationFlags flags) {
|
| - auto* context = reinterpret_cast<Context*>(context_value);
|
| - context->Notify(result, signals_state, flags);
|
| -
|
| - // That was the last notification for the context. We can release the ref
|
| - // owned by the watch, which may in turn delete the Context.
|
| - if (result == MOJO_RESULT_CANCELLED)
|
| - context->Release();
|
| - }
|
| -
|
| - uintptr_t value() const { return reinterpret_cast<uintptr_t>(this); }
|
| -
|
| - void DisableCancellationNotifications() {
|
| - base::AutoLock lock(lock_);
|
| - enable_cancellation_notifications_ = false;
|
| - }
|
| -
|
| - private:
|
| - friend class base::RefCountedThreadSafe<Context>;
|
| -
|
| - Context(base::WeakPtr<SimpleWatcher> weak_watcher,
|
| - scoped_refptr<base::SingleThreadTaskRunner> task_runner)
|
| - : weak_watcher_(weak_watcher), task_runner_(task_runner) {}
|
| - ~Context() {}
|
| -
|
| - void Notify(MojoResult result,
|
| - MojoHandleSignalsState signals_state,
|
| - MojoWatcherNotificationFlags flags) {
|
| - if (result == MOJO_RESULT_CANCELLED) {
|
| - // The SimpleWatcher may have explicitly cancelled this watch, so we don't
|
| - // bother dispatching the notification - it would be ignored anyway.
|
| - //
|
| - // TODO(rockot): This shouldn't really be necessary, but there are already
|
| - // instances today where bindings object may be bound and subsequently
|
| - // closed due to pipe error, all before the thread's TaskRunner has been
|
| - // properly initialized.
|
| - base::AutoLock lock(lock_);
|
| - if (!enable_cancellation_notifications_)
|
| - return;
|
| - }
|
| -
|
| - if ((flags & MOJO_WATCHER_NOTIFICATION_FLAG_FROM_SYSTEM) &&
|
| - task_runner_->RunsTasksOnCurrentThread() && weak_watcher_ &&
|
| - weak_watcher_->is_default_task_runner_) {
|
| - // System notifications will trigger from the task runner passed to
|
| - // mojo::edk::InitIPCSupport(). In Chrome this happens to always be the
|
| - // default task runner for the IO thread.
|
| - weak_watcher_->OnHandleReady(make_scoped_refptr(this), result);
|
| - } else {
|
| - task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&SimpleWatcher::OnHandleReady, weak_watcher_,
|
| - make_scoped_refptr(this), result));
|
| - }
|
| - }
|
| -
|
| - const base::WeakPtr<SimpleWatcher> weak_watcher_;
|
| - const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
| -
|
| - base::Lock lock_;
|
| - bool enable_cancellation_notifications_ = true;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(Context);
|
| -};
|
| -
|
| -SimpleWatcher::SimpleWatcher(const tracked_objects::Location& from_here,
|
| - ArmingPolicy arming_policy,
|
| - scoped_refptr<base::SingleThreadTaskRunner> runner)
|
| - : arming_policy_(arming_policy),
|
| - task_runner_(std::move(runner)),
|
| - is_default_task_runner_(task_runner_ ==
|
| - base::ThreadTaskRunnerHandle::Get()),
|
| - heap_profiler_tag_(from_here.file_name()),
|
| - weak_factory_(this) {
|
| - MojoResult rv = CreateWatcher(&Context::CallNotify, &watcher_handle_);
|
| - DCHECK_EQ(MOJO_RESULT_OK, rv);
|
| - DCHECK(task_runner_->BelongsToCurrentThread());
|
| -}
|
| -
|
| -SimpleWatcher::~SimpleWatcher() {
|
| - if (IsWatching())
|
| - Cancel();
|
| -}
|
| -
|
| -bool SimpleWatcher::IsWatching() const {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - return context_ != nullptr;
|
| -}
|
| -
|
| -MojoResult SimpleWatcher::Watch(Handle handle,
|
| - MojoHandleSignals signals,
|
| - const ReadyCallback& callback) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - DCHECK(!IsWatching());
|
| - DCHECK(!callback.is_null());
|
| -
|
| - callback_ = callback;
|
| - handle_ = handle;
|
| -
|
| - MojoResult watch_result = MOJO_RESULT_UNKNOWN;
|
| - context_ =
|
| - Context::Create(weak_factory_.GetWeakPtr(), task_runner_,
|
| - watcher_handle_.get(), handle_, signals, &watch_result);
|
| - if (!context_) {
|
| - handle_.set_value(kInvalidHandleValue);
|
| - callback_.Reset();
|
| - DCHECK_EQ(MOJO_RESULT_INVALID_ARGUMENT, watch_result);
|
| - return watch_result;
|
| - }
|
| -
|
| - if (arming_policy_ == ArmingPolicy::AUTOMATIC)
|
| - ArmOrNotify();
|
| -
|
| - return MOJO_RESULT_OK;
|
| -}
|
| -
|
| -void SimpleWatcher::Cancel() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - // The watcher may have already been cancelled if the handle was closed.
|
| - if (!context_)
|
| - return;
|
| -
|
| - // Prevent the cancellation notification from being dispatched to
|
| - // OnHandleReady() when cancellation is explicit. See the note in the
|
| - // implementation of DisableCancellationNotifications() above.
|
| - context_->DisableCancellationNotifications();
|
| -
|
| - handle_.set_value(kInvalidHandleValue);
|
| - callback_.Reset();
|
| -
|
| - // Ensure |context_| is unset by the time we call MojoCancelWatch, as may
|
| - // re-enter the notification callback and we want to ensure |context_| is
|
| - // unset by then.
|
| - scoped_refptr<Context> context;
|
| - std::swap(context, context_);
|
| - MojoResult rv =
|
| - MojoCancelWatch(watcher_handle_.get().value(), context->value());
|
| -
|
| - // It's possible this cancellation could race with a handle closure
|
| - // notification, in which case the watch may have already been implicitly
|
| - // cancelled.
|
| - DCHECK(rv == MOJO_RESULT_OK || rv == MOJO_RESULT_NOT_FOUND);
|
| -}
|
| -
|
| -MojoResult SimpleWatcher::Arm(MojoResult* ready_result) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - uint32_t num_ready_contexts = 1;
|
| - uintptr_t ready_context;
|
| - MojoResult local_ready_result;
|
| - MojoHandleSignalsState ready_state;
|
| - MojoResult rv =
|
| - MojoArmWatcher(watcher_handle_.get().value(), &num_ready_contexts,
|
| - &ready_context, &local_ready_result, &ready_state);
|
| - if (rv == MOJO_RESULT_FAILED_PRECONDITION) {
|
| - DCHECK(context_);
|
| - DCHECK_EQ(1u, num_ready_contexts);
|
| - DCHECK_EQ(context_->value(), ready_context);
|
| - if (ready_result)
|
| - *ready_result = local_ready_result;
|
| - }
|
| -
|
| - return rv;
|
| -}
|
| -
|
| -void SimpleWatcher::ArmOrNotify() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - // Already cancelled, nothing to do.
|
| - if (!IsWatching())
|
| - return;
|
| -
|
| - MojoResult ready_result;
|
| - MojoResult rv = Arm(&ready_result);
|
| - if (rv == MOJO_RESULT_OK)
|
| - return;
|
| -
|
| - DCHECK_EQ(MOJO_RESULT_FAILED_PRECONDITION, rv);
|
| - task_runner_->PostTask(FROM_HERE, base::Bind(&SimpleWatcher::OnHandleReady,
|
| - weak_factory_.GetWeakPtr(),
|
| - context_, ready_result));
|
| -}
|
| -
|
| -void SimpleWatcher::OnHandleReady(scoped_refptr<const Context> context,
|
| - MojoResult result) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - // This notification may be for a previously watched context, in which case
|
| - // we just ignore it.
|
| - if (context != context_)
|
| - return;
|
| -
|
| - ReadyCallback callback = callback_;
|
| - if (result == MOJO_RESULT_CANCELLED) {
|
| - // Implicit cancellation due to someone closing the watched handle. We clear
|
| - // the SimppleWatcher's state before dispatching this.
|
| - context_ = nullptr;
|
| - handle_.set_value(kInvalidHandleValue);
|
| - callback_.Reset();
|
| - }
|
| -
|
| - // NOTE: It's legal for |callback| to delete |this|.
|
| - if (!callback.is_null()) {
|
| - TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION event(heap_profiler_tag_);
|
| -
|
| - base::WeakPtr<SimpleWatcher> weak_self = weak_factory_.GetWeakPtr();
|
| - callback.Run(result);
|
| - if (!weak_self)
|
| - return;
|
| -
|
| - if (unsatisfiable_)
|
| - return;
|
| -
|
| - // Prevent |MOJO_RESULT_FAILED_PRECONDITION| task spam by only notifying
|
| - // at most once in AUTOMATIC arming mode.
|
| - if (result == MOJO_RESULT_FAILED_PRECONDITION)
|
| - unsatisfiable_ = true;
|
| -
|
| - if (arming_policy_ == ArmingPolicy::AUTOMATIC && IsWatching())
|
| - ArmOrNotify();
|
| - }
|
| -}
|
| -
|
| -} // namespace mojo
|
|
|