Commit c92dedd2 authored by Francois Doray's avatar Francois Doray Committed by Commit Bot

[threadpool] Support multiple fences active at the same time.

The goal is to support having a BEST_EFFORT execution fence prior to
main message loop start in BrowserMainLoop, and a fence when visible
tabs are loading in //chrome/browser/resource_coordinator. The lifetime
of both fences would overlap. The reason for not having a single fence
is that the first fence is controlled by //content whereas the second
fence is controlled by //chrome (precise tracking of whether a tab is
loading is a //chrome feature).

Bug: 839110, 1016825
Change-Id: Icaceee4cf9e5a1d4c52f9bb91e69e9f8125cee2c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1872807
Commit-Queue: François Doray <fdoray@chromium.org>
Reviewed-by: default avatarGabriel Charette <gab@chromium.org>
Cr-Commit-Position: refs/heads/master@{#711688}
parent 35396dc4
......@@ -350,17 +350,29 @@ void ThreadPoolImpl::JoinForTesting() {
#endif
}
void ThreadPoolImpl::SetHasFence(bool has_fence) {
void ThreadPoolImpl::BeginFence() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_NE(has_fence_, has_fence);
has_fence_ = has_fence;
++num_fences_;
UpdateCanRunPolicy();
}
void ThreadPoolImpl::SetHasBestEffortFence(bool has_best_effort_fence) {
void ThreadPoolImpl::EndFence() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_NE(has_best_effort_fence_, has_best_effort_fence);
has_best_effort_fence_ = has_best_effort_fence;
DCHECK_GT(num_fences_, 0);
--num_fences_;
UpdateCanRunPolicy();
}
void ThreadPoolImpl::BeginBestEffortFence() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
++num_best_effort_fences_;
UpdateCanRunPolicy();
}
void ThreadPoolImpl::EndBestEffortFence() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_GT(num_best_effort_fences_, 0);
--num_best_effort_fences_;
UpdateCanRunPolicy();
}
......@@ -511,14 +523,14 @@ void ThreadPoolImpl::UpdateCanRunPolicy() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
CanRunPolicy can_run_policy;
if ((!has_fence_ && !has_best_effort_fence_ &&
if ((num_fences_ == 0 && num_best_effort_fences_ == 0 &&
!has_disable_best_effort_switch_) ||
task_tracker_->HasShutdownStarted()) {
can_run_policy = CanRunPolicy::kAll;
} else if (has_fence_) {
} else if (num_fences_ != 0) {
can_run_policy = CanRunPolicy::kNone;
} else {
DCHECK(has_best_effort_fence_ || has_disable_best_effort_switch_);
DCHECK(num_best_effort_fences_ > 0 || has_disable_best_effort_switch_);
can_run_policy = CanRunPolicy::kForegroundOnly;
}
......
......@@ -79,8 +79,10 @@ class BASE_EXPORT ThreadPoolImpl : public ThreadPoolInstance,
void FlushForTesting() override;
void FlushAsyncForTesting(OnceClosure flush_callback) override;
void JoinForTesting() override;
void SetHasFence(bool has_fence) override;
void SetHasBestEffortFence(bool has_best_effort_fence) override;
void BeginFence() override;
void EndFence() override;
void BeginBestEffortFence() override;
void EndBestEffortFence() override;
// TaskExecutor:
bool PostDelayedTask(const Location& from_here,
......@@ -120,8 +122,8 @@ class BASE_EXPORT ThreadPoolImpl : public ThreadPoolInstance,
void ProcessRipeDelayedTasksForTesting();
private:
// Invoked after |has_fence_| or |has_best_effort_fence_| is updated. Sets the
// CanRunPolicy in TaskTracker and wakes up workers as appropriate.
// Invoked after |num_fences_| or |num_best_effort_fences_| is updated. Sets
// the CanRunPolicy in TaskTracker and wakes up workers as appropriate.
void UpdateCanRunPolicy();
// Returns |traits|, with priority set to TaskPriority::USER_BLOCKING if
......@@ -170,10 +172,10 @@ class BASE_EXPORT ThreadPoolImpl : public ThreadPoolInstance,
// BEST_EFFORT tasks until shutdown.
const bool has_disable_best_effort_switch_;
// Whether a fence is preventing execution of tasks of any/BEST_EFFORT
// priority. Access controlled by |sequence_checker_|.
bool has_fence_ = false;
bool has_best_effort_fence_ = false;
// Number of fences preventing execution of tasks of any/BEST_EFFORT priority.
// Access controlled by |sequence_checker_|.
int num_fences_ = 0;
int num_best_effort_fences_ = 0;
#if DCHECK_IS_ON()
// Set once JoinForTesting() has returned.
......
......@@ -222,7 +222,7 @@ class ThreadPostingTasks : public SimpleThread {
// Returns a vector with a TraitsExecutionModePair for each valid combination of
// {ExecutionMode, TaskPriority, ThreadPolicy, MayBlock()}.
std::vector<TraitsExecutionModePair> GetTraitsExecutionModePair() {
std::vector<TraitsExecutionModePair> GetTraitsExecutionModePairs() {
std::vector<TraitsExecutionModePair> params;
constexpr TaskSourceExecutionMode execution_modes[] = {
......@@ -249,6 +249,21 @@ std::vector<TraitsExecutionModePair> GetTraitsExecutionModePair() {
return params;
}
// Returns a vector with enough TraitsExecutionModePairs to cover all valid
// combinations of task destination (background/foreground ThreadGroup,
// single-thread) and whether the task is affected by a BEST_EFFORT fence.
std::vector<TraitsExecutionModePair>
GetTraitsExecutionModePairsToCoverAllSchedulingOptions() {
return {TraitsExecutionModePair({ThreadPool(), TaskPriority::BEST_EFFORT},
TaskSourceExecutionMode::kSequenced),
TraitsExecutionModePair({ThreadPool(), TaskPriority::USER_BLOCKING},
TaskSourceExecutionMode::kSequenced),
TraitsExecutionModePair({ThreadPool(), TaskPriority::BEST_EFFORT},
TaskSourceExecutionMode::kSingleThread),
TraitsExecutionModePair({ThreadPool(), TaskPriority::USER_BLOCKING},
TaskSourceExecutionMode::kSingleThread)};
}
class ThreadPoolImplTestBase : public testing::Test {
public:
ThreadPoolImplTestBase()
......@@ -324,12 +339,15 @@ class ThreadPoolImplTest : public ThreadPoolImplTestBase,
DISALLOW_COPY_AND_ASSIGN(ThreadPoolImplTest);
};
class ThreadPoolImplTestAllTraitsExecutionModes
// Tests run for enough traits and execution mode combinations to cover all
// valid combinations of task destination (background/foreground ThreadGroup,
// single-thread) and whether the task is affected by a BEST_EFFORT fence.
class ThreadPoolImplTest_CoverAllSchedulingOptions
: public ThreadPoolImplTestBase,
public testing::WithParamInterface<
std::tuple<test::PoolType, TraitsExecutionModePair>> {
public:
ThreadPoolImplTestAllTraitsExecutionModes() = default;
ThreadPoolImplTest_CoverAllSchedulingOptions() = default;
test::PoolType GetPoolType() const override {
return std::get<0>(GetParam());
......@@ -340,7 +358,7 @@ class ThreadPoolImplTestAllTraitsExecutionModes
}
private:
DISALLOW_COPY_AND_ASSIGN(ThreadPoolImplTestAllTraitsExecutionModes);
DISALLOW_COPY_AND_ASSIGN(ThreadPoolImplTest_CoverAllSchedulingOptions);
};
} // namespace
......@@ -348,7 +366,7 @@ class ThreadPoolImplTestAllTraitsExecutionModes
// Verifies that a Task posted via PostDelayedTask with parameterized TaskTraits
// and no delay runs on a thread with the expected priority and I/O
// restrictions. The ExecutionMode parameter is ignored by this test.
TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, PostDelayedTaskNoDelay) {
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, PostDelayedTaskNoDelay) {
StartThreadPool();
WaitableEvent task_ran;
thread_pool_->PostDelayedTask(
......@@ -363,7 +381,7 @@ TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, PostDelayedTaskNoDelay) {
// TaskTraits and a non-zero delay runs on a thread with the expected priority
// and I/O restrictions after the delay expires. The ExecutionMode parameter is
// ignored by this test.
TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, PostDelayedTaskWithDelay) {
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, PostDelayedTaskWithDelay) {
StartThreadPool();
WaitableEvent task_ran;
thread_pool_->PostDelayedTask(
......@@ -378,7 +396,7 @@ TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, PostDelayedTaskWithDelay) {
// Verifies that Tasks posted via a TaskRunner with parameterized TaskTraits and
// ExecutionMode run on a thread with the expected priority and I/O restrictions
// and respect the characteristics of their ExecutionMode.
TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, PostTasksViaTaskRunner) {
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, PostTasksViaTaskRunner) {
StartThreadPool();
test::TestTaskFactory factory(
CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
......@@ -398,7 +416,7 @@ TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, PostTasksViaTaskRunner) {
// Verifies that a task posted via PostDelayedTask without a delay doesn't run
// before Start() is called.
TEST_P(ThreadPoolImplTestAllTraitsExecutionModes,
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
PostDelayedTaskNoDelayBeforeStart) {
WaitableEvent task_running;
thread_pool_->PostDelayedTask(
......@@ -420,7 +438,7 @@ TEST_P(ThreadPoolImplTestAllTraitsExecutionModes,
// Verifies that a task posted via PostDelayedTask with a delay doesn't run
// before Start() is called.
TEST_P(ThreadPoolImplTestAllTraitsExecutionModes,
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
PostDelayedTaskWithDelayBeforeStart) {
WaitableEvent task_running;
thread_pool_->PostDelayedTask(
......@@ -443,7 +461,7 @@ TEST_P(ThreadPoolImplTestAllTraitsExecutionModes,
// Verifies that a task posted via a TaskRunner doesn't run before Start() is
// called.
TEST_P(ThreadPoolImplTestAllTraitsExecutionModes,
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
PostTaskViaTaskRunnerBeforeStart) {
WaitableEvent task_running;
CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
......@@ -467,7 +485,7 @@ TEST_P(ThreadPoolImplTestAllTraitsExecutionModes,
// Verify that posting tasks after the thread pool was destroyed fails but
// doesn't crash.
TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, PostTaskAfterDestroy) {
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, PostTaskAfterDestroy) {
StartThreadPool();
auto task_runner = CreateTaskRunnerAndExecutionMode(
......@@ -483,7 +501,7 @@ TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, PostTaskAfterDestroy) {
// Verify that all tasks posted to a TaskRunner after Start() run in a
// USER_BLOCKING environment when the AllTasksUserBlocking variation param of
// the BrowserScheduler experiment is true.
TEST_P(ThreadPoolImplTestAllTraitsExecutionModes,
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
AllTasksAreUserBlockingTaskRunner) {
TaskTraits user_blocking_traits = GetTraits();
user_blocking_traits.UpdatePriority(TaskPriority::USER_BLOCKING);
......@@ -503,7 +521,7 @@ TEST_P(ThreadPoolImplTestAllTraitsExecutionModes,
// Verify that all tasks posted via PostDelayedTask() after Start() run in a
// USER_BLOCKING environment when the AllTasksUserBlocking variation param of
// the BrowserScheduler experiment is true.
TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, AllTasksAreUserBlocking) {
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, AllTasksAreUserBlocking) {
TaskTraits user_blocking_traits = GetTraits();
user_blocking_traits.UpdatePriority(TaskPriority::USER_BLOCKING);
......@@ -522,7 +540,8 @@ TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, AllTasksAreUserBlocking) {
// Verifies that FlushAsyncForTesting() calls back correctly for all trait and
// execution mode pairs.
TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, FlushAsyncForTestingSimple) {
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
FlushAsyncForTestingSimple) {
StartThreadPool();
WaitableEvent unblock_task;
......@@ -579,8 +598,8 @@ TEST(ThreadPoolImplTest_Switch, DisableBestEffortTasksSwitch) {
PlatformThread::Sleep(TestTimeouts::tiny_timeout());
// The BEST_EFFORT task should not run when a BEST_EFFORT fence is deleted.
thread_pool.SetHasBestEffortFence(true);
thread_pool.SetHasBestEffortFence(false);
thread_pool.BeginBestEffortFence();
thread_pool.EndBestEffortFence();
PlatformThread::Sleep(TestTimeouts::tiny_timeout());
......@@ -591,13 +610,36 @@ TEST(ThreadPoolImplTest_Switch, DisableBestEffortTasksSwitch) {
thread_pool.JoinForTesting();
}
// Verifies that tasks only run when allowed by SetHasFence().
TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, SetHasFence) {
// Verifies that tasks only run when allowed by fences.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, Fence) {
StartThreadPool();
AtomicFlag can_run;
WaitableEvent did_run;
thread_pool_->BeginFence();
CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
GetExecutionMode())
->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
EXPECT_TRUE(can_run.IsSet());
did_run.Signal();
}));
PlatformThread::Sleep(TestTimeouts::tiny_timeout());
can_run.Set();
thread_pool_->EndFence();
did_run.Wait();
}
// Verifies that multiple fences can exist at the same time.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, MultipleFences) {
StartThreadPool();
AtomicFlag can_run;
WaitableEvent did_run;
thread_pool_->SetHasFence(true);
thread_pool_->BeginFence();
thread_pool_->BeginFence();
CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
GetExecutionMode())
......@@ -608,14 +650,19 @@ TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, SetHasFence) {
PlatformThread::Sleep(TestTimeouts::tiny_timeout());
thread_pool_->EndFence();
PlatformThread::Sleep(TestTimeouts::tiny_timeout());
// The task can only run when both fences are removed.
can_run.Set();
thread_pool_->SetHasFence(false);
thread_pool_->EndFence();
did_run.Wait();
}
// Verifies that a call to SetHasFence(true) before Start() is honored.
TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, SetHasFenceBeforeStart) {
thread_pool_->SetHasFence(true);
// Verifies that a call to BeginFence() before Start() is honored.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, FenceBeforeStart) {
thread_pool_->BeginFence();
StartThreadPool();
AtomicFlag can_run;
......@@ -631,18 +678,70 @@ TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, SetHasFenceBeforeStart) {
PlatformThread::Sleep(TestTimeouts::tiny_timeout());
can_run.Set();
thread_pool_->SetHasFence(false);
thread_pool_->EndFence();
did_run.Wait();
}
// Verifies that tasks only run when allowed by BEST_EFFORT fences.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, BestEffortFence) {
StartThreadPool();
AtomicFlag can_run;
WaitableEvent did_run;
thread_pool_->BeginBestEffortFence();
CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
GetExecutionMode())
->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
if (GetTraits().priority() == TaskPriority::BEST_EFFORT)
EXPECT_TRUE(can_run.IsSet());
did_run.Signal();
}));
PlatformThread::Sleep(TestTimeouts::tiny_timeout());
can_run.Set();
thread_pool_->EndBestEffortFence();
did_run.Wait();
}
// Verifies that multiple BEST_EFFORT fences can exist at the same time.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, MultipleBestEffortFences) {
StartThreadPool();
AtomicFlag can_run;
WaitableEvent did_run;
thread_pool_->BeginBestEffortFence();
thread_pool_->BeginBestEffortFence();
CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
GetExecutionMode())
->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
if (GetTraits().priority() == TaskPriority::BEST_EFFORT)
EXPECT_TRUE(can_run.IsSet());
did_run.Signal();
}));
PlatformThread::Sleep(TestTimeouts::tiny_timeout());
thread_pool_->EndBestEffortFence();
PlatformThread::Sleep(TestTimeouts::tiny_timeout());
// The task can only run when both fences are removed.
can_run.Set();
thread_pool_->EndBestEffortFence();
did_run.Wait();
}
// Verifies that BEST_EFFORT tasks only run when allowed by
// SetHasBestEffortFence().
TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, SetHasBestEffortFence) {
// Verifies that a call to BeginBestEffortFence() before Start() is honored.
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
BestEffortFenceBeforeStart) {
thread_pool_->BeginBestEffortFence();
StartThreadPool();
AtomicFlag can_run;
WaitableEvent did_run;
thread_pool_->SetHasBestEffortFence(true);
CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(),
GetExecutionMode())
......@@ -655,7 +754,7 @@ TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, SetHasBestEffortFence) {
PlatformThread::Sleep(TestTimeouts::tiny_timeout());
can_run.Set();
thread_pool_->SetHasBestEffortFence(false);
thread_pool_->EndBestEffortFence();
did_run.Wait();
}
......@@ -666,7 +765,7 @@ TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, SetHasBestEffortFence) {
TEST_P(ThreadPoolImplTest, MultipleTraitsExecutionModePair) {
StartThreadPool();
std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks;
for (const auto& test_params : GetTraitsExecutionModePair()) {
for (const auto& test_params : GetTraitsExecutionModePairs()) {
threads_posting_tasks.push_back(std::make_unique<ThreadPostingTasks>(
thread_pool_.get(), test_params.traits, GetPoolType(),
test_params.execution_mode));
......@@ -1193,7 +1292,8 @@ class MustBeDestroyed {
} // namespace
// Regression test for https://crbug.com/945087.
TEST_P(ThreadPoolImplTestAllTraitsExecutionModes, NoLeakWhenPostingNestedTask) {
TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions,
NoLeakWhenPostingNestedTask) {
StartThreadPool();
SequenceLocalStorageSlot<std::unique_ptr<MustBeDestroyed>> sls;
......@@ -1307,10 +1407,10 @@ void TestUpdatePrioritySequenceNotScheduled(ThreadPoolImplTest* test,
CreateTaskRunnersAndEvents(test->thread_pool_.get(), thread_policy);
// Prevent tasks from running.
test->thread_pool_->SetHasFence(true);
test->thread_pool_->BeginFence();
// Post tasks to multiple task runners while they are at initial priority.
// They won't run immediately because of the call to SetHasFence(true) above.
// They won't run immediately because of the call to BeginFence() above.
for (auto& task_runner_and_events : task_runners_and_events) {
task_runner_and_events->task_runner->PostTask(
FROM_HERE,
......@@ -1339,7 +1439,7 @@ void TestUpdatePrioritySequenceNotScheduled(ThreadPoolImplTest* test,
}
// Allow tasks to run.
test->thread_pool_->SetHasFence(false);
test->thread_pool_->EndFence();
for (auto& task_runner_and_events : task_runners_and_events)
test::WaitWithoutBlockingObserver(&task_runner_and_events->task_ran);
......@@ -1435,25 +1535,24 @@ TEST_P(ThreadPoolImplTest, UpdatePriorityFromBestEffortNoThreadPolicy) {
}
}
INSTANTIATE_TEST_SUITE_P(,
ThreadPoolImplTest,
::testing::Values(test::PoolType::GENERIC
auto GetPoolValues() {
return ::testing::Values(test::PoolType::GENERIC
#if HAS_NATIVE_THREAD_POOL()
,
test::PoolType::NATIVE
,
test::PoolType::NATIVE
#endif
));
);
}
INSTANTIATE_TEST_SUITE_P(, ThreadPoolImplTest, GetPoolValues());
INSTANTIATE_TEST_SUITE_P(
,
ThreadPoolImplTestAllTraitsExecutionModes,
::testing::Combine(::testing::Values(test::PoolType::GENERIC
#if HAS_NATIVE_THREAD_POOL()
,
test::PoolType::NATIVE
#endif
),
::testing::ValuesIn(GetTraitsExecutionModePair())));
ThreadPoolImplTest_CoverAllSchedulingOptions,
::testing::Combine(
GetPoolValues(),
::testing::ValuesIn(
GetTraitsExecutionModePairsToCoverAllSchedulingOptions())));
} // namespace internal
} // namespace base
......@@ -29,24 +29,24 @@ ThreadPoolInstance::InitParams::~InitParams() = default;
ThreadPoolInstance::ScopedExecutionFence::ScopedExecutionFence() {
DCHECK(g_thread_pool);
g_thread_pool->SetHasFence(true);
g_thread_pool->BeginFence();
}
ThreadPoolInstance::ScopedExecutionFence::~ScopedExecutionFence() {
DCHECK(g_thread_pool);
g_thread_pool->SetHasFence(false);
g_thread_pool->EndFence();
}
ThreadPoolInstance::ScopedBestEffortExecutionFence::
ScopedBestEffortExecutionFence() {
DCHECK(g_thread_pool);
g_thread_pool->SetHasBestEffortFence(true);
g_thread_pool->BeginBestEffortFence();
}
ThreadPoolInstance::ScopedBestEffortExecutionFence::
~ScopedBestEffortExecutionFence() {
DCHECK(g_thread_pool);
g_thread_pool->SetHasBestEffortFence(false);
g_thread_pool->EndBestEffortFence();
}
#if !defined(OS_NACL)
......
......@@ -100,11 +100,12 @@ class BASE_EXPORT ThreadPoolInstance {
};
// A Scoped(BestEffort)ExecutionFence prevents new tasks of any/BEST_EFFORT
// priority from being scheduled in ThreadPoolInstance within its scope. Upon
// its destruction, tasks that were preeempted are released. Note: the
// constructor of Scoped(BestEffort)ExecutionFence will not wait for currently
// running tasks (as they were posted before entering this scope and do not
// violate the contract; some of them could be CONTINUE_ON_SHUTDOWN and
// priority from being scheduled in ThreadPoolInstance within its scope.
// Multiple fences can exist at the same time. Upon destruction of all
// Scoped(BestEffort)ExecutionFences, tasks that were preeempted are released.
// Note: the constructor of Scoped(BestEffort)ExecutionFence will not wait for
// currently running tasks (as they were posted before entering this scope and
// do not violate the contract; some of them could be CONTINUE_ON_SHUTDOWN and
// waiting for them to complete is ill-advised).
class BASE_EXPORT ScopedExecutionFence {
public:
......@@ -244,10 +245,12 @@ class BASE_EXPORT ThreadPoolInstance {
virtual int GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
const TaskTraits& traits) const = 0;
// Sets whether a fence prevents execution of tasks of any / BEST_EFFORT
// Starts/stops a fence that prevents execution of tasks of any / BEST_EFFORT
// priority.
virtual void SetHasFence(bool can_run) = 0;
virtual void SetHasBestEffortFence(bool can_run) = 0;
virtual void BeginFence() = 0;
virtual void EndFence() = 0;
virtual void BeginBestEffortFence() = 0;
virtual void EndBestEffortFence() = 0;
};
} // namespace base
......
......@@ -12,25 +12,28 @@ namespace base {
class ThreadPoolTestHelpers {
public:
// Enables/disables an execution fence that prevents tasks from running.
static void SetThreadPoolExecutionFenceEnabledForTesting(bool has_fence);
static void BeginFenceForTesting();
static void EndFenceForTesting();
};
// static
void ThreadPoolTestHelpers::SetThreadPoolExecutionFenceEnabledForTesting(
bool has_fence) {
ThreadPoolInstance::Get()->SetHasFence(has_fence);
void ThreadPoolTestHelpers::BeginFenceForTesting() {
ThreadPoolInstance::Get()->BeginFence();
}
// static
void ThreadPoolTestHelpers::EndFenceForTesting() {
ThreadPoolInstance::Get()->EndFence();
}
} // namespace base
void JNI_ThreadPoolTestHelpers_EnableThreadPoolExecutionForTesting(
JNIEnv* env) {
base::ThreadPoolTestHelpers::
SetThreadPoolExecutionFenceEnabledForTesting(false);
base::ThreadPoolTestHelpers::EndFenceForTesting();
}
void JNI_ThreadPoolTestHelpers_DisableThreadPoolExecutionForTesting(
JNIEnv* env) {
base::ThreadPoolTestHelpers::
SetThreadPoolExecutionFenceEnabledForTesting(true);
}
base::ThreadPoolTestHelpers::BeginFenceForTesting();
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment