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

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

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.h
diff --git a/mojo/public/cpp/system/watcher.h b/mojo/public/cpp/system/watcher.h
index 236788b1c853139367df8b0a56b44859064219ca..db4853106c3aed5859cb8e9d21c167479a76d3f3 100644
--- a/mojo/public/cpp/system/watcher.h
+++ b/mojo/public/cpp/system/watcher.h
@@ -23,6 +23,28 @@ namespace mojo {
// NOTE: Watchers may only be used on threads which have a running MessageLoop.
class MOJO_CPP_SYSTEM_EXPORT Watcher {
public:
+ // Selects how this Watcher is to be armed.
+ enum class ArmingPolicy {
+ // The Watcher is armed automatically on Start() and rearmed again after
+ // every invocation of the ReadyCallback. There is no need to manually call
+ // Arm() on a Watcher using this policy.
+ //
+ // This provides a reasonable approximation of edge-triggered behavior,
+ // mitigating (but not completely eliminating) the potential for redundant
+ // notifications.
+ //
+ // For perfect edge-triggered behavior, use MANUAL policy and manually Arm()
+ // the Watcher as soon as it becomes possible to do so again.
+ AUTOMATIC,
+
+ // The Watcher is never armed automatically. Arm() must be called manually
+ // before any non-cancellation notification can be dispatched to the
+ // ReadyCallback. Immediately before the ReadyCallback is invoked, the
+ // Watcher is disarmed again and will require another manual call to Arm()
+ // before the next notification can fire.
+ MANUAL,
+ };
+
// A callback to be called any time a watched handle changes state in some
// interesting way. The |result| argument indicates one of the following
// conditions depending on its value:
@@ -37,6 +59,7 @@ class MOJO_CPP_SYSTEM_EXPORT Watcher {
using ReadyCallback = base::Callback<void(MojoResult result)>;
Watcher(const tracked_objects::Location& from_here,
+ ArmingPolicy arming_policy,
scoped_refptr<base::SingleThreadTaskRunner> runner =
base::ThreadTaskRunnerHandle::Get());
@@ -61,17 +84,35 @@ class MOJO_CPP_SYSTEM_EXPORT Watcher {
// closure or cancellation.
//
// Once the watch is started, |callback| may be called at any time on the
- // current thread until |Cancel()| is called or the handle is closed.
+ // current thread until |Cancel()| is called or the handle is closed. Note
+ // that |callback| will only be called for results other than
+ // |MOJO_RESULT_CANCELLED| if the Watcher is currently armed. Use ArmingPolicy
+ // to configure how a Watcher is armed.
//
// Destroying the Watcher implicitly calls |Cancel()|.
MojoResult Start(Handle handle,
MojoHandleSignals signals,
const ReadyCallback& callback);
- // Cancels the current watch. Once this returns, the callback previously
+ // Cancels the current watch. Once this returns, the ReadyCallback previously
// passed to |Start()| will never be called again for this Watcher.
void Cancel();
+ // Manually arm the watcher. See documentation for MojoArmWatcher() for
+ // result code details.
+ //
+ // This is only needed when using MANUAL ArmingPolicy (see above.)
+ MojoResult Arm();
+
+ // Manually arm the watcher, or post a task to invoke the ReadyCallback
+ // with the result of the failed arming attempt. This is meant as a convenient
+ // helper for a common usage of Arm(), and it ensures that the ReadyCallback
+ // will be invoked asynchronously again as soon as the Watcher's conditions
+ // are satisfied, assuming the Watcher isn't cancelled first.
+ //
+ // Unlike Arm() above, this can never fail.
+ void ArmOrNotify();
+
Handle handle() const { return handle_; }
ReadyCallback ready_callback() const { return callback_; }
@@ -83,6 +124,8 @@ class MOJO_CPP_SYSTEM_EXPORT Watcher {
private:
void OnHandleReady(MojoResult result);
+ void OnHandleReadyFromAnyThread(MojoResult result,
+ MojoWatchNotificationFlags flags);
static void CallOnHandleReady(uintptr_t context,
MojoResult result,
@@ -91,6 +134,9 @@ class MOJO_CPP_SYSTEM_EXPORT Watcher {
base::ThreadChecker thread_checker_;
+ // The policy used to determine how this Watcher is armed.
+ const ArmingPolicy arming_policy_;
+
// The TaskRunner of this Watcher's owning thread. This field is safe to
// access from any thread.
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
@@ -115,6 +161,10 @@ class MOJO_CPP_SYSTEM_EXPORT Watcher {
// this watcher.
const char* heap_profiler_tag_ = nullptr;
+ // If this address is non-null during Watcher destruction, the value this
+ // references is set to |true|.
+ bool* was_deleted_flag_ = nullptr;
yzshen1 2017/03/03 00:03:50 Is the reason to use this instead of DestructionTr
Ken Rockot(use gerrit already) 2017/03/03 00:37:05 N/A - using WeakPtr now. But for the record, the
+
base::WeakPtrFactory<Watcher> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(Watcher);

Powered by Google App Engine
This is Rietveld 408576698