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

Side by Side Diff: media/base/bind_to_current_loop_unittest.cc

Issue 1082113004: BindToCurrentLoop should delete callback on original thread Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 4 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
« no previous file with comments | « media/base/bind_to_current_loop.cc ('k') | media/media.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "media/base/bind_to_current_loop.h" 5 #include "media/base/bind_to_current_loop.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/barrier_closure.h"
9 #include "base/memory/free_deleter.h" 10 #include "base/memory/free_deleter.h"
10 #include "base/message_loop/message_loop.h" 11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
11 #include "base/synchronization/waitable_event.h" 13 #include "base/synchronization/waitable_event.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "base/threading/thread.h"
12 #include "testing/gtest/include/gtest/gtest.h" 16 #include "testing/gtest/include/gtest/gtest.h"
13 17
14 namespace media { 18 namespace media {
15 19
16 void BoundBoolSet(bool* var, bool val) { 20 void BoundBoolSet(bool* var, bool val) {
17 *var = val; 21 *var = val;
18 } 22 }
19 23
20 void BoundBoolSetFromScopedPtr(bool* var, scoped_ptr<bool> val) { 24 void BoundBoolSetFromScopedPtr(bool* var, scoped_ptr<bool> val) {
21 *var = *val; 25 *var = *val;
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 base::Callback<void(int, int)> cb = BindToCurrentLoop(base::Bind( 165 base::Callback<void(int, int)> cb = BindToCurrentLoop(base::Bind(
162 &BoundIntegersSet, &a, &b)); 166 &BoundIntegersSet, &a, &b));
163 cb.Run(1, -1); 167 cb.Run(1, -1);
164 EXPECT_EQ(a, 0); 168 EXPECT_EQ(a, 0);
165 EXPECT_EQ(b, 0); 169 EXPECT_EQ(b, 0);
166 loop_.RunUntilIdle(); 170 loop_.RunUntilIdle();
167 EXPECT_EQ(a, 1); 171 EXPECT_EQ(a, 1);
168 EXPECT_EQ(b, -1); 172 EXPECT_EQ(b, -1);
169 } 173 }
170 174
175 namespace {
176
177 void ExpectRunOn(scoped_refptr<base::SingleThreadTaskRunner> loop,
178 const base::Closure& done_closure) {
179 EXPECT_TRUE(loop->BelongsToCurrentThread());
180 done_closure.Run();
181 }
182
183 } // namespace
184
185 TEST_F(BindToCurrentLoopTest, CalledOnOriginalThread) {
186 scoped_refptr<base::SingleThreadTaskRunner> origin_loop =
187 base::ThreadTaskRunnerHandle::Get();
188 ASSERT_TRUE(origin_loop->BelongsToCurrentThread());
189
190 base::Thread thread("Other thread");
191 ASSERT_TRUE(thread.Start());
192 scoped_refptr<base::SingleThreadTaskRunner> thread_loop =
193 thread.task_runner();
194 ASSERT_FALSE(thread_loop->BelongsToCurrentThread());
195
196 base::RunLoop run_loop;
197 base::Closure barrier_closure =
198 base::BarrierClosure(2, BindToCurrentLoop(run_loop.QuitClosure()));
199
200 base::Closure thread_cb = base::Bind(
201 &ExpectRunOn, thread_loop, barrier_closure);
202 base::Closure origin_cb = BindToCurrentLoop(base::Bind(
203 &ExpectRunOn, origin_loop, barrier_closure));
204
205 thread_loop->PostTask(FROM_HERE, thread_cb);
206 thread_loop->PostTask(FROM_HERE, origin_cb);
207
208 run_loop.Run();
209
210 thread.Stop();
211 }
212
213 namespace {
214
215 class ExpectDeletedOnOrigin {
216 public:
217 ExpectDeletedOnOrigin(
218 scoped_refptr<base::SingleThreadTaskRunner> origin_loop,
219 const base::Closure& deleted_closure)
220 : origin_loop_(origin_loop),
221 deleted_closure_(deleted_closure) {}
222
223 ~ExpectDeletedOnOrigin() {
224 EXPECT_TRUE(origin_loop_->BelongsToCurrentThread());
225 deleted_closure_.Run();
226 }
227
228 scoped_refptr<base::SingleThreadTaskRunner> origin_loop_;
229 base::Closure deleted_closure_;
230 };
231
232 class RefCountedExpectDeletedOnOrigin
233 : public ExpectDeletedOnOrigin,
234 public base::RefCountedThreadSafe<RefCountedExpectDeletedOnOrigin> {
235 public:
236 RefCountedExpectDeletedOnOrigin(
237 scoped_refptr<base::SingleThreadTaskRunner> origin_loop,
238 const base::Closure& deleted_closure)
239 : ExpectDeletedOnOrigin(origin_loop, deleted_closure) {}
240
241 private:
242 friend class base::RefCountedThreadSafe<RefCountedExpectDeletedOnOrigin>;
243 ~RefCountedExpectDeletedOnOrigin() {}
244 };
245
246 void CallbackWithParamsToDelete(
247 ExpectDeletedOnOrigin* unused_owned,
248 scoped_ptr<ExpectDeletedOnOrigin> unused_passed,
249 scoped_refptr<RefCountedExpectDeletedOnOrigin> unused_ref_counted) {}
250
251 } // namespace
252
253 TEST_F(BindToCurrentLoopTest, CallbackDeletedOnOriginalThread) {
254 scoped_refptr<base::SingleThreadTaskRunner> origin_loop =
255 base::ThreadTaskRunnerHandle::Get();
256
257 base::Thread thread("Other thread");
258 ASSERT_TRUE(thread.Start());
259 scoped_refptr<base::SingleThreadTaskRunner> thread_loop =
260 thread.task_runner();
261
262 base::RunLoop run_loop;
263 base::Closure barrier_closure =
264 base::BarrierClosure(3, BindToCurrentLoop(run_loop.QuitClosure()));
265
266 base::Closure* origin_cb_ptr;
267 {
268 ExpectDeletedOnOrigin* new_delete_on_origin =
269 new ExpectDeletedOnOrigin(origin_loop, barrier_closure);
270 scoped_ptr<ExpectDeletedOnOrigin> scoped_delete_on_origin(
271 new ExpectDeletedOnOrigin(origin_loop, barrier_closure));
272 scoped_refptr<RefCountedExpectDeletedOnOrigin> counted_delete_on_origin =
273 new RefCountedExpectDeletedOnOrigin(origin_loop, barrier_closure);
274 origin_cb_ptr = new base::Closure(BindToCurrentLoop(base::Bind(
275 &CallbackWithParamsToDelete,
276 base::Owned(new_delete_on_origin),
277 base::Passed(&scoped_delete_on_origin),
278 counted_delete_on_origin)));
279 }
280
281 // Delete the callback returned by BindToCurrentLoop on the other thread. This
282 // must cause the wrapped callback that was passed in to BindToCurrentLoop to
283 // be deleted on the origin thread (where BindToCurrentLoop was invoked), and
284 // hence the parameters of that wrapped callback must also be deleted on the
285 // origin thread.
286 thread_loop->DeleteSoon(FROM_HERE, origin_cb_ptr);
287
288 // If this test times out, that means one of the ExpectDeletedOnOrigin or
289 // RefCountedExpectDeletedOnOrigin objects failed to be deleted (bad).
290 run_loop.Run();
291
292 thread.Stop();
293 }
294
171 } // namespace media 295 } // namespace media
OLDNEW
« no previous file with comments | « media/base/bind_to_current_loop.cc ('k') | media/media.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698