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

Side by Side Diff: base/threading/sequenced_worker_pool_unittest.cc

Issue 1414793009: Allow SequencedTaskRunnerHandle::Get() while running unsequenced tasks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: moar test Created 5 years 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 | « base/threading/sequenced_worker_pool.cc ('k') | no next file » | 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 "base/threading/sequenced_worker_pool.h" 5 #include "base/threading/sequenced_worker_pool.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/memory/ref_counted.h" 11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h" 13 #include "base/message_loop/message_loop.h"
14 #include "base/sequence_checker_impl.h"
14 #include "base/stl_util.h" 15 #include "base/stl_util.h"
15 #include "base/synchronization/condition_variable.h" 16 #include "base/synchronization/condition_variable.h"
16 #include "base/synchronization/lock.h" 17 #include "base/synchronization/lock.h"
18 #include "base/synchronization/waitable_event.h"
17 #include "base/test/sequenced_task_runner_test_template.h" 19 #include "base/test/sequenced_task_runner_test_template.h"
18 #include "base/test/sequenced_worker_pool_owner.h" 20 #include "base/test/sequenced_worker_pool_owner.h"
19 #include "base/test/task_runner_test_template.h" 21 #include "base/test/task_runner_test_template.h"
20 #include "base/test/test_timeouts.h" 22 #include "base/test/test_timeouts.h"
21 #include "base/threading/platform_thread.h" 23 #include "base/threading/platform_thread.h"
22 #include "base/time/time.h" 24 #include "base/time/time.h"
23 #include "base/tracked_objects.h" 25 #include "base/tracked_objects.h"
24 #include "testing/gtest/include/gtest/gtest.h" 26 #include "testing/gtest/include/gtest/gtest.h"
25 27
26 namespace base { 28 namespace base {
(...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 // Should be fine to call on an idle instance with all threads created, and 886 // Should be fine to call on an idle instance with all threads created, and
885 // spamming the method shouldn't deadlock or confuse the class. 887 // spamming the method shouldn't deadlock or confuse the class.
886 pool()->FlushForTesting(); 888 pool()->FlushForTesting();
887 pool()->FlushForTesting(); 889 pool()->FlushForTesting();
888 890
889 // Should be fine to call after shutdown too. 891 // Should be fine to call after shutdown too.
890 pool()->Shutdown(); 892 pool()->Shutdown();
891 pool()->FlushForTesting(); 893 pool()->FlushForTesting();
892 } 894 }
893 895
894 namespace { 896 // Helper method for VerifyCurrentSequencedTaskRunner() and
895 897 // VerifyCurrentSequencedTaskRunnerForUnsequencedTask().
896 void CheckWorkerPoolAndSequenceToken( 898 void VerifySequencedTaskRunnerRunsOnCurrentThread(
897 const scoped_refptr<SequencedWorkerPool>& expected_pool, 899 SequencedTaskRunner* task_runner,
898 SequencedWorkerPool::SequenceToken expected_token) { 900 bool should_run_on_current_thread,
899 SequencedWorkerPool::SequenceToken token = 901 const Closure& callback) {
900 SequencedWorkerPool::GetSequenceTokenForCurrentThread(); 902 EXPECT_EQ(should_run_on_current_thread,
901 EXPECT_EQ(expected_token.ToString(), token.ToString()); 903 task_runner->RunsTasksOnCurrentThread());
902 904 callback.Run();
903 scoped_refptr<SequencedWorkerPool> pool =
904 SequencedWorkerPool::GetWorkerPoolForCurrentThread();
905 EXPECT_EQ(expected_pool, pool);
906 } 905 }
907 906
908 } // namespace 907 void VerifyCurrentSequencedTaskRunner(
908 SequencedTaskRunner* expected_task_runner,
909 bool expected_equal,
910 const Closure& callback) {
911 scoped_refptr<SequencedTaskRunner> task_runner =
912 SequencedWorkerPool::GetSequencedTaskRunnerForCurrentThread();
909 913
910 TEST_F(SequencedWorkerPoolTest, GetWorkerPoolAndSequenceTokenForCurrentThread) { 914 EXPECT_TRUE(task_runner->RunsTasksOnCurrentThread());
915
916 // SequencedTaskRunner does not allow directly checking for equality, but we
917 // can post a task to one task runner and verify that the other task runner
918 // is on the same sequence.
919 task_runner->PostTask(
920 FROM_HERE,
921 Bind(&VerifySequencedTaskRunnerRunsOnCurrentThread,
922 base::Unretained(expected_task_runner), expected_equal, callback));
923 }
924
925 void VerifyCurrentSequencedTaskRunnerForUnsequencedTask(
926 SequencedWorkerPool* pool,
927 const Closure& callback) {
928 ASSERT_FALSE(
929 SequencedWorkerPool::GetSequenceTokenForCurrentThread().IsValid());
930
931 scoped_refptr<SequencedTaskRunner> task_runner =
932 SequencedWorkerPool::GetSequencedTaskRunnerForCurrentThread();
933
934 EXPECT_TRUE(task_runner->RunsTasksOnCurrentThread());
935
936 scoped_refptr<SequencedTaskRunner> expected_task_runner =
937 SequencedWorkerPool::GetSequencedTaskRunnerForCurrentThread();
938
939 // The pool should now be running a sequence. This also verifies that no other
940 // thread will start running tasks with this sequence token.
941 const SequencedWorkerPool::SequenceToken sequence_token =
942 SequencedWorkerPool::GetSequenceTokenForCurrentThread();
943 ASSERT_TRUE(sequence_token.IsValid());
danakj 2015/12/17 23:49:51 nit: i generally prefer to always EXPECT rather th
Bernhard Bauer 2015/12/18 19:00:00 Done.
944 EXPECT_TRUE(pool->IsRunningSequence(sequence_token));
945
946 // The two sequenced task runners should be the same. See
947 // VerifyCurrentSequencedTaskRunner() above for why the check is implemented
948 // this way.
949 const bool expected_equal = true;
950 task_runner->PostTask(
951 FROM_HERE,
952 Bind(&VerifySequencedTaskRunnerRunsOnCurrentThread,
953 std::move(expected_task_runner), expected_equal, callback));
954 }
955
956 TEST_F(SequencedWorkerPoolTest, GetSequencedTaskRunnerForCurrentThread) {
911 EnsureAllWorkersCreated(); 957 EnsureAllWorkersCreated();
912 958
913 // The current thread should have neither a worker pool nor a sequence token. 959 // The current thread should not have a sequenced task runner from a
914 SequencedWorkerPool::SequenceToken local_token = 960 // worker pool.
915 SequencedWorkerPool::GetSequenceTokenForCurrentThread(); 961 scoped_refptr<SequencedTaskRunner> local_task_runner =
916 scoped_refptr<SequencedWorkerPool> local_pool = 962 SequencedWorkerPool::GetSequencedTaskRunnerForCurrentThread();
917 SequencedWorkerPool::GetWorkerPoolForCurrentThread(); 963 EXPECT_FALSE(local_task_runner);
918 EXPECT_FALSE(local_token.IsValid()) << local_token.ToString();
919 EXPECT_FALSE(local_pool);
920 964
921 SequencedWorkerPool::SequenceToken token1 = pool()->GetSequenceToken(); 965 WaitableEvent event(false, false);
922 SequencedWorkerPool::SequenceToken token2 = pool()->GetSequenceToken(); 966 Closure signal = Bind(&WaitableEvent::Signal, Unretained(&event));
923 pool()->PostSequencedWorkerTask( 967 scoped_refptr<SequencedTaskRunner> task_runner_1 =
924 token1, FROM_HERE, 968 pool()->GetSequencedTaskRunner(SequencedWorkerPool::GetSequenceToken());
925 base::Bind(&CheckWorkerPoolAndSequenceToken, pool(), token1)); 969 scoped_refptr<SequencedTaskRunner> task_runner_2 =
926 pool()->PostSequencedWorkerTask( 970 pool()->GetSequencedTaskRunner(SequencedWorkerPool::GetSequenceToken());
927 token2, FROM_HERE, 971 task_runner_1->PostTask(
928 base::Bind(&CheckWorkerPoolAndSequenceToken, pool(), token2)); 972 FROM_HERE, Bind(&VerifyCurrentSequencedTaskRunner,
973 base::Unretained(task_runner_1.get()), true, signal));
974 event.Wait();
975 task_runner_2->PostTask(
976 FROM_HERE, Bind(&VerifyCurrentSequencedTaskRunner,
977 base::Unretained(task_runner_2.get()), true, signal));
978 event.Wait();
929 979
930 pool()->PostWorkerTask(FROM_HERE, 980 task_runner_1->PostTask(
931 base::Bind(&CheckWorkerPoolAndSequenceToken, pool(), 981 FROM_HERE, Bind(&VerifyCurrentSequencedTaskRunner,
932 SequencedWorkerPool::SequenceToken())); 982 base::Unretained(task_runner_2.get()), false, signal));
983 event.Wait();
933 984
934 pool()->FlushForTesting(); 985 pool()->PostWorkerTask(
986 FROM_HERE, Bind(&VerifyCurrentSequencedTaskRunnerForUnsequencedTask,
987 pool(), signal));
988 event.Wait();
989 }
990
991 class ChecksSequenceOnDestruction
992 : public RefCountedThreadSafe<ChecksSequenceOnDestruction> {
993 public:
994 void DoNothing() {}
995
996 private:
997 friend class RefCountedThreadSafe<ChecksSequenceOnDestruction>;
998
999 ~ChecksSequenceOnDestruction() {
1000 EXPECT_TRUE(sequence_checker_.CalledOnValidSequencedThread());
1001 }
1002
1003 SequenceCheckerImpl sequence_checker_;
1004 };
1005
1006 void VerifySequenceOnDestruction(const Closure& callback) {
1007 scoped_refptr<SequencedTaskRunner> task_runner =
1008 SequencedWorkerPool::GetSequencedTaskRunnerForCurrentThread();
1009 scoped_refptr<ChecksSequenceOnDestruction> check_sequence(
1010 new ChecksSequenceOnDestruction);
1011
1012 // Post a task to an empty method. This will keep the only reference to the
1013 // object, so it will be destroyed right after running the task.
1014 task_runner->PostTask(FROM_HERE, Bind(&ChecksSequenceOnDestruction::DoNothing,
1015 std::move(check_sequence)));
1016
1017 // Post the callback afterwards, so we can be sure the first task completed.
1018 task_runner->PostTask(FROM_HERE, callback);
1019 }
1020
1021 TEST_F(SequencedWorkerPoolTest, CheckSequenceOnDestruction) {
1022 EnsureAllWorkersCreated();
1023
1024 WaitableEvent event(false, false);
1025 Closure signal = Bind(&WaitableEvent::Signal, Unretained(&event));
1026 pool()->PostWorkerTask(FROM_HERE, Bind(&VerifySequenceOnDestruction, signal));
1027 event.Wait();
935 } 1028 }
936 1029
937 TEST_F(SequencedWorkerPoolTest, ShutsDownCleanWithContinueOnShutdown) { 1030 TEST_F(SequencedWorkerPoolTest, ShutsDownCleanWithContinueOnShutdown) {
938 scoped_refptr<SequencedTaskRunner> task_runner = 1031 scoped_refptr<SequencedTaskRunner> task_runner =
939 pool()->GetSequencedTaskRunnerWithShutdownBehavior( 1032 pool()->GetSequencedTaskRunnerWithShutdownBehavior(
940 pool()->GetSequenceToken(), 1033 pool()->GetSequenceToken(),
941 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); 1034 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
942 1035
943 // Upon test exit, should shut down without hanging. 1036 // Upon test exit, should shut down without hanging.
944 pool()->Shutdown(); 1037 pool()->Shutdown();
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1063 SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest, 1156 SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest,
1064 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); 1157 SequencedWorkerPoolSequencedTaskRunnerTestDelegate);
1065 INSTANTIATE_TYPED_TEST_CASE_P( 1158 INSTANTIATE_TYPED_TEST_CASE_P(
1066 SequencedWorkerPoolSequencedTaskRunner, 1159 SequencedWorkerPoolSequencedTaskRunner,
1067 SequencedTaskRunnerDelayedTest, 1160 SequencedTaskRunnerDelayedTest,
1068 SequencedWorkerPoolSequencedTaskRunnerTestDelegate); 1161 SequencedWorkerPoolSequencedTaskRunnerTestDelegate);
1069 1162
1070 } // namespace 1163 } // namespace
1071 1164
1072 } // namespace base 1165 } // namespace base
OLDNEW
« no previous file with comments | « base/threading/sequenced_worker_pool.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698