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

Unified 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: Created 5 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 side-by-side diff with in-line comments
Download patch
« media/base/bind_to_current_loop.h ('K') | « media/base/bind_to_current_loop.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/base/bind_to_current_loop_unittest.cc
diff --git a/media/base/bind_to_current_loop_unittest.cc b/media/base/bind_to_current_loop_unittest.cc
index 23030856675d69052dc3f37aab8eacd08c8614b1..2330df7f540f78782b06996e3786cc82b1a17696 100644
--- a/media/base/bind_to_current_loop_unittest.cc
+++ b/media/base/bind_to_current_loop_unittest.cc
@@ -4,8 +4,11 @@
#include "media/base/bind_to_current_loop.h"
+#include "base/barrier_closure.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media {
@@ -165,4 +168,124 @@ TEST_F(BindToCurrentLoopTest, Integers) {
EXPECT_EQ(b, -1);
}
+namespace {
+
+void ExpectRunOn(scoped_refptr<base::SingleThreadTaskRunner> loop,
+ const base::Closure& done_closure) {
+ EXPECT_TRUE(loop->BelongsToCurrentThread());
+ done_closure.Run();
+}
+
+} // namespace
+
+TEST_F(BindToCurrentLoopTest, CalledOnOriginalThread) {
+ scoped_refptr<base::SingleThreadTaskRunner> origin_loop =
+ base::ThreadTaskRunnerHandle::Get();
+ ASSERT_TRUE(origin_loop->BelongsToCurrentThread());
+
+ base::Thread thread("Other thread");
+ ASSERT_TRUE(thread.Start());
+ scoped_refptr<base::SingleThreadTaskRunner> thread_loop =
+ thread.task_runner();
+ ASSERT_FALSE(thread_loop->BelongsToCurrentThread());
+
+ base::RunLoop run_loop;
+ base::Closure barrier_closure =
+ base::BarrierClosure(2, BindToCurrentLoop(run_loop.QuitClosure()));
+
+ base::Closure thread_cb = base::Bind(
+ &ExpectRunOn, thread_loop, barrier_closure);
+ base::Closure origin_cb = BindToCurrentLoop(base::Bind(
+ &ExpectRunOn, origin_loop, barrier_closure));
+
+ thread_loop->PostTask(FROM_HERE, thread_cb);
+ thread_loop->PostTask(FROM_HERE, origin_cb);
+
+ run_loop.Run();
+
+ thread.Stop();
+}
+
+namespace {
+
+class ExpectDeletedOnOrigin {
+ public:
+ ExpectDeletedOnOrigin(
+ scoped_refptr<base::SingleThreadTaskRunner> origin_loop,
+ const base::Closure& deleted_closure)
+ : origin_loop_(origin_loop),
+ deleted_closure_(deleted_closure) {}
+
+ ~ExpectDeletedOnOrigin() {
+ EXPECT_TRUE(origin_loop_->BelongsToCurrentThread());
+ deleted_closure_.Run();
+ }
+
+ scoped_refptr<base::SingleThreadTaskRunner> origin_loop_;
+ base::Closure deleted_closure_;
+};
+
+class RefCountedExpectDeletedOnOrigin
+ : public ExpectDeletedOnOrigin,
+ public base::RefCountedThreadSafe<RefCountedExpectDeletedOnOrigin> {
+ public:
+ RefCountedExpectDeletedOnOrigin(
+ scoped_refptr<base::SingleThreadTaskRunner> origin_loop,
+ const base::Closure& deleted_closure)
+ : ExpectDeletedOnOrigin(origin_loop, deleted_closure) {}
+
+ private:
+ friend class base::RefCountedThreadSafe<RefCountedExpectDeletedOnOrigin>;
+ ~RefCountedExpectDeletedOnOrigin() {}
+};
+
+void CallbackWithParamsToDelete(
+ ExpectDeletedOnOrigin* unused_owned,
+ scoped_ptr<ExpectDeletedOnOrigin> unused_passed,
+ scoped_refptr<RefCountedExpectDeletedOnOrigin> unused_ref_counted) {}
+
+} // namespace
+
+TEST_F(BindToCurrentLoopTest, CallbackDeletedOnOriginalThread) {
+ scoped_refptr<base::SingleThreadTaskRunner> origin_loop =
+ base::ThreadTaskRunnerHandle::Get();
+
+ base::Thread thread("Other thread");
+ ASSERT_TRUE(thread.Start());
+ scoped_refptr<base::SingleThreadTaskRunner> thread_loop =
+ thread.task_runner();
+
+ base::RunLoop run_loop;
+ base::Closure barrier_closure =
+ base::BarrierClosure(3, BindToCurrentLoop(run_loop.QuitClosure()));
+
+ base::Closure* origin_cb_ptr;
+ {
+ ExpectDeletedOnOrigin* new_delete_on_origin =
+ new ExpectDeletedOnOrigin(origin_loop, barrier_closure);
+ scoped_ptr<ExpectDeletedOnOrigin> scoped_delete_on_origin(
+ new ExpectDeletedOnOrigin(origin_loop, barrier_closure));
+ scoped_refptr<RefCountedExpectDeletedOnOrigin> counted_delete_on_origin =
+ new RefCountedExpectDeletedOnOrigin(origin_loop, barrier_closure);
+ origin_cb_ptr = new base::Closure(BindToCurrentLoop(base::Bind(
+ &CallbackWithParamsToDelete,
+ base::Owned(new_delete_on_origin),
+ base::Passed(&scoped_delete_on_origin),
+ counted_delete_on_origin)));
+ }
+
+ // Delete the callback returned by BindToCurrentLoop on the other thread. This
+ // must cause the wrapped callback that was passed in to BindToCurrentLoop to
+ // be deleted on the origin thread (where BindToCurrentLoop was invoked), and
+ // hence the parameters of that wrapped callback must also be deleted on the
+ // origin thread.
+ thread_loop->DeleteSoon(FROM_HERE, origin_cb_ptr);
+
+ // If this test times out, that means one of the ExpectDeletedOnOrigin or
+ // RefCountedExpectDeletedOnOrigin objects failed to be deleted (bad).
+ run_loop.Run();
+
+ thread.Stop();
+}
+
} // namespace media
« media/base/bind_to_current_loop.h ('K') | « media/base/bind_to_current_loop.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698