Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(349)

Unified Diff: mojo/public/cpp/system/watcher.cc

Issue 2725133002: Mojo: Armed Watchers (Closed)
Patch Set: . Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698