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

Side by Side Diff: base/synchronization/waitable_event_watcher_posix.cc

Issue 2801593002: Convert WaitableEvent::EventCallback to OnceCallback (Closed)
Patch Set: test Created 3 years, 8 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/synchronization/waitable_event_watcher.h" 5 #include "base/synchronization/waitable_event_watcher.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 DISALLOW_COPY_AND_ASSIGN(Flag); 54 DISALLOW_COPY_AND_ASSIGN(Flag);
55 }; 55 };
56 56
57 // ----------------------------------------------------------------------------- 57 // -----------------------------------------------------------------------------
58 // This is an asynchronous waiter which posts a task to a SequencedTaskRunner 58 // This is an asynchronous waiter which posts a task to a SequencedTaskRunner
59 // when fired. An AsyncWaiter may only be in a single wait-list. 59 // when fired. An AsyncWaiter may only be in a single wait-list.
60 // ----------------------------------------------------------------------------- 60 // -----------------------------------------------------------------------------
61 class AsyncWaiter : public WaitableEvent::Waiter { 61 class AsyncWaiter : public WaitableEvent::Waiter {
62 public: 62 public:
63 AsyncWaiter(scoped_refptr<SequencedTaskRunner> task_runner, 63 AsyncWaiter(scoped_refptr<SequencedTaskRunner> task_runner,
64 const base::Closure& callback, 64 base::OnceClosure callback,
Tom Sepez 2017/04/14 18:49:55 Funny, I thought this would have to be a base::Onc
dcheng 2017/04/14 21:56:58 In Google/Chromium, move-only types are passed by
65 Flag* flag) 65 Flag* flag)
66 : task_runner_(std::move(task_runner)), 66 : task_runner_(std::move(task_runner)),
67 callback_(callback), 67 callback_(std::move(callback)),
68 flag_(flag) {} 68 flag_(flag) {}
69 69
70 bool Fire(WaitableEvent* event) override { 70 bool Fire(WaitableEvent* event) override {
71 // Post the callback if we haven't been cancelled. 71 // Post the callback if we haven't been cancelled.
72 if (!flag_->value()) 72 if (!flag_->value())
73 task_runner_->PostTask(FROM_HERE, callback_); 73 task_runner_->PostTask(FROM_HERE, std::move(callback_));
74 74
75 // We are removed from the wait-list by the WaitableEvent itself. It only 75 // We are removed from the wait-list by the WaitableEvent itself. It only
76 // remains to delete ourselves. 76 // remains to delete ourselves.
77 delete this; 77 delete this;
78 78
79 // We can always return true because an AsyncWaiter is never in two 79 // We can always return true because an AsyncWaiter is never in two
80 // different wait-lists at the same time. 80 // different wait-lists at the same time.
81 return true; 81 return true;
82 } 82 }
83 83
84 // See StopWatching for discussion 84 // See StopWatching for discussion
85 bool Compare(void* tag) override { return tag == flag_.get(); } 85 bool Compare(void* tag) override { return tag == flag_.get(); }
86 86
87 private: 87 private:
88 const scoped_refptr<SequencedTaskRunner> task_runner_; 88 const scoped_refptr<SequencedTaskRunner> task_runner_;
89 const base::Closure callback_; 89 base::OnceClosure callback_;
90 const scoped_refptr<Flag> flag_; 90 const scoped_refptr<Flag> flag_;
91 }; 91 };
92 92
93 // ----------------------------------------------------------------------------- 93 // -----------------------------------------------------------------------------
94 // For async waits we need to run a callback on a sequence. We do this by 94 // For async waits we need to run a callback on a sequence. We do this by
95 // posting an AsyncCallbackHelper task, which calls the callback and keeps track 95 // posting an AsyncCallbackHelper task, which calls the callback and keeps track
96 // of when the event is canceled. 96 // of when the event is canceled.
97 // ----------------------------------------------------------------------------- 97 // -----------------------------------------------------------------------------
98 void AsyncCallbackHelper(Flag* flag, 98 void AsyncCallbackHelper(Flag* flag,
99 const WaitableEventWatcher::EventCallback& callback, 99 WaitableEventWatcher::EventCallback callback,
100 WaitableEvent* event) { 100 WaitableEvent* event) {
101 // Runs on the sequence that called StartWatching(). 101 // Runs on the sequence that called StartWatching().
102 if (!flag->value()) { 102 if (!flag->value()) {
103 // This is to let the WaitableEventWatcher know that the event has occured. 103 // This is to let the WaitableEventWatcher know that the event has occured.
104 flag->Set(); 104 flag->Set();
105 callback.Run(event); 105 std::move(callback).Run(event);
106 } 106 }
107 } 107 }
108 108
109 WaitableEventWatcher::WaitableEventWatcher() { 109 WaitableEventWatcher::WaitableEventWatcher() {
110 sequence_checker_.DetachFromSequence(); 110 sequence_checker_.DetachFromSequence();
111 } 111 }
112 112
113 WaitableEventWatcher::~WaitableEventWatcher() { 113 WaitableEventWatcher::~WaitableEventWatcher() {
114 // The destructor may be called from a different sequence than StartWatching() 114 // The destructor may be called from a different sequence than StartWatching()
115 // when there is no active watch. To avoid triggering a DCHECK in 115 // when there is no active watch. To avoid triggering a DCHECK in
116 // StopWatching(), do not call it when there is no active watch. 116 // StopWatching(), do not call it when there is no active watch.
117 if (cancel_flag_ && !cancel_flag_->value()) 117 if (cancel_flag_ && !cancel_flag_->value())
118 StopWatching(); 118 StopWatching();
119 } 119 }
120 120
121 // ----------------------------------------------------------------------------- 121 // -----------------------------------------------------------------------------
122 // The Handle is how the user cancels a wait. After deleting the Handle we 122 // The Handle is how the user cancels a wait. After deleting the Handle we
123 // insure that the delegate cannot be called. 123 // insure that the delegate cannot be called.
124 // ----------------------------------------------------------------------------- 124 // -----------------------------------------------------------------------------
125 bool WaitableEventWatcher::StartWatching( 125 bool WaitableEventWatcher::StartWatching(WaitableEvent* event,
126 WaitableEvent* event, 126 EventCallback callback) {
127 const EventCallback& callback) {
128 DCHECK(sequence_checker_.CalledOnValidSequence()); 127 DCHECK(sequence_checker_.CalledOnValidSequence());
129 DCHECK(SequencedTaskRunnerHandle::Get()); 128 DCHECK(SequencedTaskRunnerHandle::Get());
130 129
131 // A user may call StartWatching from within the callback function. In this 130 // A user may call StartWatching from within the callback function. In this
132 // case, we won't know that we have finished watching, expect that the Flag 131 // case, we won't know that we have finished watching, expect that the Flag
133 // will have been set in AsyncCallbackHelper(). 132 // will have been set in AsyncCallbackHelper().
134 if (cancel_flag_.get() && cancel_flag_->value()) 133 if (cancel_flag_.get() && cancel_flag_->value())
135 cancel_flag_ = nullptr; 134 cancel_flag_ = nullptr;
136 135
137 DCHECK(!cancel_flag_) << "StartWatching called while still watching"; 136 DCHECK(!cancel_flag_) << "StartWatching called while still watching";
138 137
139 cancel_flag_ = new Flag; 138 cancel_flag_ = new Flag;
140 const Closure internal_callback = base::Bind( 139 OnceClosure internal_callback =
141 &AsyncCallbackHelper, base::RetainedRef(cancel_flag_), callback, event); 140 base::BindOnce(&AsyncCallbackHelper, base::RetainedRef(cancel_flag_),
141 std::move(callback), event);
142 WaitableEvent::WaitableEventKernel* kernel = event->kernel_.get(); 142 WaitableEvent::WaitableEventKernel* kernel = event->kernel_.get();
143 143
144 AutoLock locked(kernel->lock_); 144 AutoLock locked(kernel->lock_);
145 145
146 if (kernel->signaled_) { 146 if (kernel->signaled_) {
147 if (!kernel->manual_reset_) 147 if (!kernel->manual_reset_)
148 kernel->signaled_ = false; 148 kernel->signaled_ = false;
149 149
150 // No hairpinning - we can't call the delegate directly here. We have to 150 // No hairpinning - we can't call the delegate directly here. We have to
151 // post a task to the SequencedTaskRunnerHandle as usual. 151 // post a task to the SequencedTaskRunnerHandle as usual.
152 SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE, internal_callback); 152 SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
153 std::move(internal_callback));
153 return true; 154 return true;
154 } 155 }
155 156
156 kernel_ = kernel; 157 kernel_ = kernel;
157 waiter_ = new AsyncWaiter(SequencedTaskRunnerHandle::Get(), internal_callback, 158 waiter_ = new AsyncWaiter(SequencedTaskRunnerHandle::Get(),
158 cancel_flag_.get()); 159 std::move(internal_callback), cancel_flag_.get());
159 event->Enqueue(waiter_); 160 event->Enqueue(waiter_);
160 161
161 return true; 162 return true;
162 } 163 }
163 164
164 void WaitableEventWatcher::StopWatching() { 165 void WaitableEventWatcher::StopWatching() {
165 DCHECK(sequence_checker_.CalledOnValidSequence()); 166 DCHECK(sequence_checker_.CalledOnValidSequence());
166 167
167 if (!cancel_flag_.get()) // if not currently watching... 168 if (!cancel_flag_.get()) // if not currently watching...
168 return; 169 return;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 // If the waiter has already run then the task has been enqueued. If the Task 225 // If the waiter has already run then the task has been enqueued. If the Task
225 // hasn't yet run, the flag will stop the delegate from getting called. (This 226 // hasn't yet run, the flag will stop the delegate from getting called. (This
226 // is thread safe because one may only delete a Handle from the sequence that 227 // is thread safe because one may only delete a Handle from the sequence that
227 // called StartWatching()). 228 // called StartWatching()).
228 // 229 //
229 // If the delegate has already been called then we have nothing to do. The 230 // If the delegate has already been called then we have nothing to do. The
230 // task has been deleted by the MessageLoop. 231 // task has been deleted by the MessageLoop.
231 } 232 }
232 233
233 } // namespace base 234 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698