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

Unified Diff: base/task_scheduler/scheduler_worker_pool_impl_unittest.cc

Issue 2116163002: Add Lazy Creation and Thread Detachment Support in the Scheduler Worker Pool (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 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: base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
diff --git a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc b/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
index 7766f72e0d2aecc16b2c085a1fae8c522d59ce18..572d885821c88a8c6bb801c195cd6ee5bf853aad 100644
--- a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
+++ b/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
@@ -10,6 +10,7 @@
#include <unordered_set>
#include <vector>
+#include "base/atomicops.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
@@ -28,7 +29,9 @@
#include "base/task_scheduler/test_utils.h"
#include "base/threading/platform_thread.h"
#include "base/threading/simple_thread.h"
+#include "base/threading/thread_local_storage.h"
#include "base/threading/thread_restrictions.h"
+#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
@@ -38,6 +41,7 @@ namespace {
const size_t kNumWorkersInWorkerPool = 4;
const size_t kNumThreadsPostingTasks = 4;
const size_t kNumTasksPostedPerThread = 150;
+const TimeDelta kSuggestedReclaimTime = TimeDelta::FromMilliseconds(10);
using IORestriction = SchedulerWorkerPoolImpl::IORestriction;
@@ -65,6 +69,7 @@ class TaskSchedulerWorkerPoolImplTest
worker_pool_ = SchedulerWorkerPoolImpl::Create(
"TestWorkerPoolWithFileIO", ThreadPriority::NORMAL,
kNumWorkersInWorkerPool, IORestriction::ALLOWED,
+ kSuggestedReclaimTime,
Bind(&TaskSchedulerWorkerPoolImplTest::ReEnqueueSequenceCallback,
Unretained(this)),
&task_tracker_, &delayed_task_manager_);
@@ -364,8 +369,8 @@ TEST_P(TaskSchedulerWorkerPoolImplIORestrictionTest, IORestriction) {
auto worker_pool = SchedulerWorkerPoolImpl::Create(
"TestWorkerPoolWithParam", ThreadPriority::NORMAL, 1U, GetParam(),
- Bind(&NotReachedReEnqueueSequenceCallback), &task_tracker,
- &delayed_task_manager);
+ TimeDelta::Max(), Bind(&NotReachedReEnqueueSequenceCallback),
+ &task_tracker, &delayed_task_manager);
ASSERT_TRUE(worker_pool);
WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL,
@@ -384,5 +389,152 @@ INSTANTIATE_TEST_CASE_P(IODisallowed,
TaskSchedulerWorkerPoolImplIORestrictionTest,
::testing::Values(IORestriction::DISALLOWED));
+namespace {
+
+constexpr size_t kMagicTlsValue = 42;
+
+class TaskSchedulerWorkerPoolSingleThreadedTest
+ : public TaskSchedulerWorkerPoolImplTest {
+ public:
+ void SetTlsValue() {
+ slot_.Set(reinterpret_cast<void*>(kMagicTlsValue));
+ }
+
+ void CheckTlsValue() {
+ EXPECT_EQ(kMagicTlsValue, reinterpret_cast<size_t>(slot_.Get()));
+ }
+
+ protected:
+ TaskSchedulerWorkerPoolSingleThreadedTest() = default;
+
+ private:
+ ThreadLocalStorage::Slot slot_;
+
+ DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolSingleThreadedTest);
+};
+
+} // namespace
+
+// Verify that thread resources for a single thread remain.
+TEST_F(TaskSchedulerWorkerPoolSingleThreadedTest, SingleThreadTask) {
+ auto single_thread_task_runner =
+ worker_pool_->CreateTaskRunnerWithTraits(
+ TaskTraits().
+ WithShutdownBehavior(TaskShutdownBehavior::BLOCK_SHUTDOWN),
+ ExecutionMode::SINGLE_THREADED);
+ single_thread_task_runner->PostTask(
+ FROM_HERE,
+ Bind(&TaskSchedulerWorkerPoolSingleThreadedTest::SetTlsValue,
+ Unretained(this)));
+ WaitableEvent task_waiter(WaitableEvent::ResetPolicy::MANUAL,
+ WaitableEvent::InitialState::NOT_SIGNALED);
+ single_thread_task_runner->PostTask(
+ FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&task_waiter)));
+ task_waiter.Wait();
+ task_waiter.Reset();
+ worker_pool_->WaitForAllWorkersIdleForTesting();
+
+ // Give the worker pool a chance to reclaim its threads.
+ PlatformThread::Sleep(
+ kSuggestedReclaimTime + TimeDelta::FromMilliseconds(200));
+
+ single_thread_task_runner->PostTask(
+ FROM_HERE,
+ Bind(&TaskSchedulerWorkerPoolSingleThreadedTest::CheckTlsValue,
+ Unretained(this)));
+ single_thread_task_runner->PostTask(
+ FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&task_waiter)));
+ task_waiter.Wait();
+}
+
fdoray 2016/07/04 19:41:33 Test that no detachment occurs when suggested recl
robliao 2016/07/07 17:49:16 If we could test this, this would be better handle
fdoray 2016/07/07 20:45:57 Acknowledged.
+namespace {
+
+class TaskSchedulerWorkerPoolCheckTlsReuse
+ : public TaskSchedulerWorkerPoolImplTest {
+ public:
+ void SetTlsValueAndWait() {
+ slot_.Set(reinterpret_cast<void*>(kMagicTlsValue));
+ waiter_.Wait();
+ }
+
+ void CountZeroTlsValues() {
+ if (!slot_.Get())
+ subtle::NoBarrier_AtomicIncrement(&zero_tls_values_, 1);
+ }
+
+ protected:
+ TaskSchedulerWorkerPoolCheckTlsReuse() :
+ waiter_(WaitableEvent::ResetPolicy::MANUAL,
+ WaitableEvent::InitialState::NOT_SIGNALED) {}
+ subtle::Atomic32 zero_tls_values_ = 0;
+
+ WaitableEvent waiter_;
+
+ private:
+ ThreadLocalStorage::Slot slot_;
+
+ DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolCheckTlsReuse);
+};
+
+} // namespace
+
+// Checks that at least one thread has detached by checking the TLS.
+TEST_F(TaskSchedulerWorkerPoolCheckTlsReuse, CheckDetachedThreads) {
+ // Saturate the threads and mark each thread with a magic TLS value.
+ std::vector<std::unique_ptr<test::TestTaskFactory>> factories;
+ for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) {
+ factories.push_back(WrapUnique(new test::TestTaskFactory(
+ worker_pool_->CreateTaskRunnerWithTraits(
+ TaskTraits(), ExecutionMode::PARALLEL),
+ ExecutionMode::PARALLEL)));
+ ASSERT_TRUE(factories.back()->PostTask(
+ PostNestedTask::NO,
+ Bind(&TaskSchedulerWorkerPoolCheckTlsReuse::SetTlsValueAndWait,
+ Unretained(this))));
+ factories.back()->WaitForAllTasksToRun();
+ }
+
+ // Release tasks waiting on |waiter_|.
+ waiter_.Signal();
fdoray 2016/07/04 19:41:33 Should the Reset() be after WaitForAllWorkersIdleF
robliao 2016/07/07 17:49:16 The tricky bit here is that we can't wait for all
fdoray 2016/07/07 20:45:57 If Signal() stays before WaitForAllWorkersIdleForT
robliao 2016/07/08 17:25:49 I initially misread this. Yup, let's move Reset af
+ waiter_.Reset();
+
+ worker_pool_->WaitForAllWorkersIdleForTesting();
+
+ // Give the worker pool a chance to detach its threads.
+ PlatformThread::Sleep(
+ kSuggestedReclaimTime + TimeDelta::FromMilliseconds(200));
+
+ // Saturate and count the threads that do not have the magic TLS value. If the
+ // value is not there, that means we're at a new thread.
+ std::vector<std::unique_ptr<WaitableEvent>> count_waiters;
+ for (auto& factory : factories) {
+ ASSERT_TRUE(factory->PostTask(
+ PostNestedTask::NO,
+ Bind(&TaskSchedulerWorkerPoolCheckTlsReuse::CountZeroTlsValues,
fdoray 2016/07/04 19:41:32 Nothing prevents all CountZeroTlsValue tasks from
robliao 2016/07/07 17:49:16 Doesn't WaitForAllTasksToRun with a waiting task a
fdoray 2016/07/07 20:45:57 Line 486: You create factories with PARALLEL TaskR
robliao 2016/07/08 17:25:49 Ah yes, indeed. I've now moved both waitable event
+ Unretained(this))));
+ count_waiters.push_back(WrapUnique(new WaitableEvent(
+ WaitableEvent::ResetPolicy::MANUAL,
+ WaitableEvent::InitialState::NOT_SIGNALED)));
+ ASSERT_TRUE(factory->PostTask(
+ PostNestedTask::NO,
+ Bind(&WaitableEvent::Signal,
+ Unretained(count_waiters.back().get()))));
+ ASSERT_TRUE(factory->PostTask(PostNestedTask::NO,
+ Bind(&WaitableEvent::Wait,
+ Unretained(&waiter_))));
+ factory->WaitForAllTasksToRun();
+ }
+
+ // Wait for all counters to complete.
+ for (auto& count_waiter : count_waiters)
+ count_waiter->Wait();
+
+ EXPECT_GT(zero_tls_values_, 0);
+
+ // Release tasks waiting on |waiter_|.
+ waiter_.Signal();
+ worker_pool_->WaitForAllWorkersIdleForTesting();
+}
+
} // namespace internal
} // namespace base

Powered by Google App Engine
This is Rietveld 408576698