| Index: mojo/public/cpp/system/watcher.cc
|
| diff --git a/mojo/public/cpp/system/watcher.cc b/mojo/public/cpp/system/watcher.cc
|
| index 55dcf4023e2b719ea7e9fe28451c5280f05e9654..0022145d9b4aac5c18fd4f02b5df1fa6445e9e0a 100644
|
| --- a/mojo/public/cpp/system/watcher.cc
|
| +++ b/mojo/public/cpp/system/watcher.cc
|
| @@ -13,8 +13,10 @@
|
| namespace mojo {
|
|
|
| Watcher::Watcher(const tracked_objects::Location& from_here,
|
| + ArmingPolicy arming_policy,
|
| scoped_refptr<base::SingleThreadTaskRunner> runner)
|
| - : task_runner_(std::move(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()),
|
| @@ -26,6 +28,9 @@ Watcher::Watcher(const tracked_objects::Location& from_here,
|
| Watcher::~Watcher() {
|
| if(IsWatching())
|
| Cancel();
|
| +
|
| + if (was_deleted_flag_)
|
| + *was_deleted_flag_ = true;
|
| }
|
|
|
| bool Watcher::IsWatching() const {
|
| @@ -42,9 +47,9 @@ MojoResult Watcher::Start(Handle handle,
|
|
|
| callback_ = callback;
|
| handle_ = handle;
|
| - MojoResult result = MojoWatch(handle_.value(), signals,
|
| - &Watcher::CallOnHandleReady,
|
| - reinterpret_cast<uintptr_t>(this));
|
| + MojoResult result =
|
| + MojoRegisterWatcher(handle_.value(), signals, &Watcher::CallOnHandleReady,
|
| + reinterpret_cast<uintptr_t>(this));
|
| if (result != MOJO_RESULT_OK) {
|
| handle_.set_value(kInvalidHandleValue);
|
| callback_.Reset();
|
| @@ -53,18 +58,21 @@ MojoResult Watcher::Start(Handle handle,
|
| return result;
|
| }
|
|
|
| + if (arming_policy_ == ArmingPolicy::AUTOMATIC)
|
| + ArmOrNotify();
|
| +
|
| return MOJO_RESULT_OK;
|
| }
|
|
|
| void Watcher::Cancel() {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
|
|
| - // The watch may have already been cancelled if the handle was closed.
|
| + // The watcher may have already been cancelled if the handle was closed.
|
| if (!handle_.is_valid())
|
| return;
|
|
|
| MojoResult result =
|
| - MojoCancelWatch(handle_.value(), reinterpret_cast<uintptr_t>(this));
|
| + MojoUnregisterWatcher(handle_.value(), reinterpret_cast<uintptr_t>(this));
|
| // |result| may be MOJO_RESULT_INVALID_ARGUMENT if |handle_| has closed, but
|
| // OnHandleReady has not yet been called.
|
| DCHECK(result == MOJO_RESULT_INVALID_ARGUMENT || result == MOJO_RESULT_OK);
|
| @@ -72,6 +80,39 @@ void Watcher::Cancel() {
|
| callback_.Reset();
|
| }
|
|
|
| +MojoResult Watcher::Arm() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + return MojoArmWatcher(handle_.value(), reinterpret_cast<uintptr_t>(this));
|
| +}
|
| +
|
| +void Watcher::ArmOrNotify() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| + // Already cancelled, nothing to do.
|
| + if (!IsWatching())
|
| + return;
|
| +
|
| + MojoResult result = Arm();
|
| + switch (result) {
|
| + case MOJO_RESULT_OK:
|
| + // We're armed. Nothing else to do.
|
| + return;
|
| + case MOJO_RESULT_ALREADY_EXISTS:
|
| + // Signals are already satisfied. We post a notification of success.
|
| + result = MOJO_RESULT_OK;
|
| + break;
|
| + case MOJO_RESULT_FAILED_PRECONDITION:
|
| + // Signals are unsatisfiable. We post a notification to indicate this.
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| +
|
| + task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&Watcher::OnHandleReady, weak_self_, result));
|
| +}
|
| +
|
| void Watcher::OnHandleReady(MojoResult result) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
|
|
| @@ -84,7 +125,29 @@ void Watcher::OnHandleReady(MojoResult result) {
|
| // NOTE: It's legal for |callback| to delete |this|.
|
| if (!callback.is_null()) {
|
| TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION event(heap_profiler_tag_);
|
| +
|
| + bool was_deleted = false;
|
| + was_deleted_flag_ = &was_deleted;
|
| callback.Run(result);
|
| + if (was_deleted)
|
| + return;
|
| + was_deleted_flag_ = nullptr;
|
| + if (arming_policy_ == ArmingPolicy::AUTOMATIC && IsWatching())
|
| + ArmOrNotify();
|
| + }
|
| +}
|
| +
|
| +void Watcher::OnHandleReadyFromAnyThread(MojoResult result,
|
| + MojoWatchNotificationFlags flags) {
|
| + if ((flags & MOJO_WATCH_NOTIFICATION_FLAG_FROM_SYSTEM) &&
|
| + task_runner_->RunsTasksOnCurrentThread() && 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.
|
| + OnHandleReady(result);
|
| + } else {
|
| + task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&Watcher::OnHandleReady, weak_self_, result));
|
| }
|
| }
|
|
|
| @@ -97,21 +160,9 @@ void Watcher::CallOnHandleReady(uintptr_t context,
|
| // will never be run after the Watcher's destructor.
|
| //
|
| // TODO: Maybe we should also expose |signals_state| through the Watcher API.
|
| - // Current HandleWatcher users have no need for it, so it's omitted here.
|
| - Watcher* watcher = reinterpret_cast<Watcher*>(context);
|
| -
|
| - if ((flags & MOJO_WATCH_NOTIFICATION_FLAG_FROM_SYSTEM) &&
|
| - watcher->task_runner_->RunsTasksOnCurrentThread() &&
|
| - 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.
|
| - watcher->OnHandleReady(result);
|
| - } else {
|
| - watcher->task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&Watcher::OnHandleReady, watcher->weak_self_, result));
|
| - }
|
| + // Current users have no need for it, so it's omitted here.
|
| + auto* watcher = reinterpret_cast<Watcher*>(context);
|
| + watcher->OnHandleReadyFromAnyThread(result, flags);
|
| }
|
|
|
| } // namespace mojo
|
|
|