Commit 1eb7c8cc authored by Francois Doray's avatar Francois Doray Committed by Commit Bot

Add Lazy(Sequenced|SingleThread|COMSTA)TaskRunner.

A Lazy(Sequenced|SingleThread|COMSTA)TaskRunner lazily creates a TaskRunner.

A Lazy(Sequenced|SingleThread|COMSTA)TaskRunner is meant to be instantiated in
an anonymous namespace and used to post tasks to the same sequence/thread
from pieces of code that don't have a better way of sharing a TaskRunner.
Adding a Lazy(Sequenced|SingleThread|COMSTA)TaskRunner to an anonymous
namespace doesn't generate a static initializer.

Bug: 730170
Change-Id: Idb35cfe9a5ca5501b7057d7b90b9df3f702faff1
Reviewed-on: https://chromium-review.googlesource.com/524141
Commit-Queue: Francois Doray <fdoray@chromium.org>
Reviewed-by: default avatarRobert Liao <robliao@chromium.org>
Reviewed-by: default avatarGabriel Charette <gab@chromium.org>
Cr-Commit-Position: refs/heads/master@{#478779}
parent 3280f87f
...@@ -818,6 +818,8 @@ component("base") { ...@@ -818,6 +818,8 @@ component("base") {
"task_scheduler/environment_config.h", "task_scheduler/environment_config.h",
"task_scheduler/initialization_util.cc", "task_scheduler/initialization_util.cc",
"task_scheduler/initialization_util.h", "task_scheduler/initialization_util.h",
"task_scheduler/lazy_task_runner.cc",
"task_scheduler/lazy_task_runner.h",
"task_scheduler/post_task.cc", "task_scheduler/post_task.cc",
"task_scheduler/post_task.h", "task_scheduler/post_task.h",
"task_scheduler/priority_queue.cc", "task_scheduler/priority_queue.cc",
...@@ -2163,6 +2165,7 @@ test("base_unittests") { ...@@ -2163,6 +2165,7 @@ test("base_unittests") {
"task/cancelable_task_tracker_unittest.cc", "task/cancelable_task_tracker_unittest.cc",
"task_runner_util_unittest.cc", "task_runner_util_unittest.cc",
"task_scheduler/delayed_task_manager_unittest.cc", "task_scheduler/delayed_task_manager_unittest.cc",
"task_scheduler/lazy_task_runner_unittest.cc",
"task_scheduler/priority_queue_unittest.cc", "task_scheduler/priority_queue_unittest.cc",
"task_scheduler/scheduler_lock_unittest.cc", "task_scheduler/scheduler_lock_unittest.cc",
"task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc", "task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc",
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/task_scheduler/lazy_task_runner.h"
#include <utility>
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/task_scheduler/post_task.h"
namespace base {
namespace internal {
namespace {
ScopedLazyTaskRunnerListForTesting* g_scoped_lazy_task_runner_list_for_testing =
nullptr;
} // namespace
template <typename TaskRunnerType, bool com_sta>
void LazyTaskRunner<TaskRunnerType, com_sta>::Reset() {
subtle::AtomicWord state = subtle::Acquire_Load(&state_);
DCHECK_NE(state, kLazyInstanceStateCreating) << "Race: all threads should be "
"unwound in unittests before "
"resetting TaskRunners.";
// Return if no reference is held by this instance.
if (!state)
return;
// Release the reference acquired in Get().
SequencedTaskRunner* task_runner = reinterpret_cast<TaskRunnerType*>(state);
task_runner->Release();
// Clear the state.
subtle::NoBarrier_Store(&state_, 0);
}
template <>
scoped_refptr<SequencedTaskRunner>
LazyTaskRunner<SequencedTaskRunner, false>::Create() {
// It is invalid to specify a SingleThreadTaskRunnerThreadMode with a
// LazySequencedTaskRunner.
DCHECK_EQ(thread_mode_, SingleThreadTaskRunnerThreadMode::SHARED);
return CreateSequencedTaskRunnerWithTraits(traits_);
}
template <>
scoped_refptr<SingleThreadTaskRunner>
LazyTaskRunner<SingleThreadTaskRunner, false>::Create() {
return CreateSingleThreadTaskRunnerWithTraits(traits_, thread_mode_);
}
#if defined(OS_WIN)
template <>
scoped_refptr<SingleThreadTaskRunner>
LazyTaskRunner<SingleThreadTaskRunner, true>::Create() {
return CreateCOMSTATaskRunnerWithTraits(traits_, thread_mode_);
}
#endif
template <typename TaskRunnerType, bool com_sta>
scoped_refptr<TaskRunnerType> LazyTaskRunner<TaskRunnerType, com_sta>::Get() {
return make_scoped_refptr(static_cast<TaskRunnerType*>(GetOrCreateLazyPointer(
&state_,
[this]() {
scoped_refptr<TaskRunnerType> task_runner = Create();
// Acquire a reference to the TaskRunner. The reference will either
// never be released or be released in Reset(). The reference is not
// managed by a scoped_refptr because adding a scoped_refptr member to
// LazyTaskRunner would prevent its static initialization.
task_runner->AddRef();
// Reset this instance when the current
// ScopedLazyTaskRunnerListForTesting is destroyed, if any.
if (g_scoped_lazy_task_runner_list_for_testing) {
g_scoped_lazy_task_runner_list_for_testing->AddCallback(
BindOnce(&LazyTaskRunner<TaskRunnerType, com_sta>::Reset,
Unretained(this)));
}
return task_runner.get();
},
nullptr, nullptr)));
}
template class LazyTaskRunner<SequencedTaskRunner, false>;
template class LazyTaskRunner<SingleThreadTaskRunner, false>;
#if defined(OS_WIN)
template class LazyTaskRunner<SingleThreadTaskRunner, true>;
#endif
ScopedLazyTaskRunnerListForTesting::ScopedLazyTaskRunnerListForTesting() {
DCHECK(!g_scoped_lazy_task_runner_list_for_testing);
g_scoped_lazy_task_runner_list_for_testing = this;
}
ScopedLazyTaskRunnerListForTesting::~ScopedLazyTaskRunnerListForTesting() {
internal::AutoSchedulerLock auto_lock(lock_);
for (auto& callback : callbacks_)
std::move(callback).Run();
g_scoped_lazy_task_runner_list_for_testing = nullptr;
}
void ScopedLazyTaskRunnerListForTesting::AddCallback(OnceClosure callback) {
internal::AutoSchedulerLock auto_lock(lock_);
callbacks_.push_back(std::move(callback));
}
} // namespace internal
} // namespace base
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_TASK_SCHEDULER_LAZY_TASK_RUNNER_H_
#define BASE_TASK_SCHEDULER_LAZY_TASK_RUNNER_H_
#include <vector>
#include "base/atomicops.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/lazy_instance.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/task_scheduler/scheduler_lock.h"
#include "base/task_scheduler/single_thread_task_runner_thread_mode.h"
#include "base/task_scheduler/task_traits.h"
#include "build/build_config.h"
// Lazy(Sequenced|SingleThread|COMSTA)TaskRunner lazily creates a TaskRunner.
//
// Lazy(Sequenced|SingleThread|COMSTA)TaskRunner is meant to be instantiated in
// an anonymous namespace (no static initializer is generated) and used to post
// tasks to the same sequence/thread from pieces of code that don't have a
// better way of sharing a TaskRunner. It is important to use this class
// instead of a self-managed global variable or LazyInstance so that the
// TaskRunners do not outlive the scope of the ScopedTaskEnvironment in unit
// tests (otherwise the next test in the same process will die in use-after-
// frees).
//
// IMPORTANT: Only use this API as a last resort. Prefer storing a
// (Sequenced|SingleThread)TaskRunner returned by
// base::Create(Sequenced|SingleThread|COMSTA)TaskRunnerWithTraits() as a member
// on an object accessible by all PostTask() call sites.
//
// Example usage 1:
//
// namespace {
// base::LazySequencedTaskRunner g_sequenced_task_runner =
// LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER({base::MayBlock()});
// } // namespace
//
// void SequencedFunction() {
// // Different invocations of this function post to the same
// // MayBlock() SequencedTaskRunner.
// g_sequenced_task_runner.Get()->PostTask(FROM_HERE, base::BindOnce(...));
// }
//
// Example usage 2:
//
// namespace {
// base::LazySequencedTaskRunner g_sequenced_task_task_runner =
// LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER({base::MayBlock()});
// } // namespace
//
// // Code from different files can access the SequencedTaskRunner via this
// // function.
// scoped_refptr<base::SequencedTaskRunner> GetTaskRunner() {
// return g_sequenced_task_runner.Get();
// }
namespace base {
namespace internal {
template <typename TaskRunnerType, bool com_sta>
class BASE_EXPORT LazyTaskRunner;
} // namespace internal
// Lazy SequencedTaskRunner.
using LazySequencedTaskRunner =
internal::LazyTaskRunner<SequencedTaskRunner, false>;
// Lazy SingleThreadTaskRunner.
using LazySingleThreadTaskRunner =
internal::LazyTaskRunner<SingleThreadTaskRunner, false>;
#if defined(OS_WIN)
// Lazy COM-STA enabled SingleThreadTaskRunner.
using LazyCOMSTATaskRunner =
internal::LazyTaskRunner<SingleThreadTaskRunner, true>;
#endif
// Helper macros to generate a variable name by concatenation.
#define LAZY_TASK_RUNNER_CONCATENATE_INTERNAL2(a, b) a##b
#define LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(a, b) \
LAZY_TASK_RUNNER_CONCATENATE_INTERNAL2(a, b)
// Use the macros below to initialize a LazyTaskRunner. These macros verify that
// their arguments are constexpr, which is important to prevent the generation
// of a static initializer.
// |traits| are TaskTraits used when creating the SequencedTaskRunner.
#define LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER(traits) \
base::LazySequencedTaskRunner::CreateInternal(traits); \
ALLOW_UNUSED_TYPE constexpr base::TaskTraits \
LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyTraitsAreConstexpr, \
__LINE__) = traits
// |traits| are TaskTraits used when creating the SingleThreadTaskRunner.
// |thread_mode| specifies whether the SingleThreadTaskRunner can share its
// thread with other SingleThreadTaskRunners.
#define LAZY_SINGLE_THREAD_TASK_RUNNER_INITIALIZER(traits, thread_mode) \
base::LazySingleThreadTaskRunner::CreateInternal(traits, thread_mode); \
ALLOW_UNUSED_TYPE constexpr base::TaskTraits \
LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyTraitsAreConstexpr, \
__LINE__) = traits; \
ALLOW_UNUSED_TYPE constexpr SingleThreadTaskRunnerThreadMode \
LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyThreadModeIsConstexpr, \
__LINE__) = thread_mode
// |traits| are TaskTraits used when creating the COM STA
// SingleThreadTaskRunner. |thread_mode| specifies whether the COM STA
// SingleThreadTaskRunner can share its thread with other
// SingleThreadTaskRunners.
#define LAZY_COM_STA_TASK_RUNNER_INITIALIZER(traits, thread_mode) \
base::LazyCOMSTATaskRunner::CreateInternal(traits, thread_mode); \
ALLOW_UNUSED_TYPE constexpr base::TaskTraits \
LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyTraitsAreConstexpr, \
__LINE__) = traits; \
ALLOW_UNUSED_TYPE constexpr SingleThreadTaskRunnerThreadMode \
LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyThreadModeIsConstexpr, \
__LINE__) = thread_mode
namespace internal {
template <typename TaskRunnerType, bool com_sta>
class BASE_EXPORT LazyTaskRunner {
public:
// Use the macros above rather than a direct call to this.
//
// |traits| are TaskTraits to use to create the TaskRunner. If this
// LazyTaskRunner is specialized to create a SingleThreadTaskRunner,
// |thread_mode| specifies whether the SingleThreadTaskRunner can share its
// thread with other SingleThreadTaskRunner. Otherwise, it is unused.
static constexpr LazyTaskRunner CreateInternal(
const TaskTraits& traits,
SingleThreadTaskRunnerThreadMode thread_mode =
SingleThreadTaskRunnerThreadMode::SHARED) {
return LazyTaskRunner(traits, thread_mode);
}
// Returns the TaskRunner held by this instance. Creates it if it didn't
// already exist. Thread-safe.
scoped_refptr<TaskRunnerType> Get();
private:
constexpr LazyTaskRunner(const TaskTraits& traits,
SingleThreadTaskRunnerThreadMode thread_mode =
SingleThreadTaskRunnerThreadMode::SHARED)
: traits_(traits), thread_mode_(thread_mode) {}
// Releases the TaskRunner held by this instance.
void Reset();
// Creates and returns a new TaskRunner.
scoped_refptr<TaskRunnerType> Create();
// TaskTraits to create the TaskRunner.
const TaskTraits traits_;
// SingleThreadTaskRunnerThreadMode to create the TaskRunner.
const SingleThreadTaskRunnerThreadMode thread_mode_;
// Can have 3 states:
// - This instance does not hold a TaskRunner: 0
// - This instance is creating a TaskRunner: kLazyInstanceStateCreating
// - This instance holds a TaskRunner: Pointer to the TaskRunner.
// LazyInstance's internals are reused to handle transition between states.
subtle::AtomicWord state_ = 0;
// No DISALLOW_COPY_AND_ASSIGN since that prevents static initialization with
// Visual Studio (warning C4592: 'symbol will be dynamically initialized
// (implementation limitation))'.
};
// When a LazyTaskRunner becomes active (invokes Get()), it adds a callback to
// the current ScopedLazyTaskRunnerListForTesting, if any. Callbacks run when
// the ScopedLazyTaskRunnerListForTesting is destroyed. In a test process, a
// ScopedLazyTaskRunnerListForTesting must be instantiated before any
// LazyTaskRunner becomes active.
class BASE_EXPORT ScopedLazyTaskRunnerListForTesting {
public:
ScopedLazyTaskRunnerListForTesting();
~ScopedLazyTaskRunnerListForTesting();
private:
friend class LazyTaskRunner<SequencedTaskRunner, false>;
friend class LazyTaskRunner<SingleThreadTaskRunner, false>;
#if defined(OS_WIN)
friend class LazyTaskRunner<SingleThreadTaskRunner, true>;
#endif
// Add |callback| to the list of callbacks to run on destruction.
void AddCallback(OnceClosure callback);
// Synchronizes accesses to |callbacks_|.
SchedulerLock lock_;
// List of callbacks to run on destruction.
std::vector<OnceClosure> callbacks_;
DISALLOW_COPY_AND_ASSIGN(ScopedLazyTaskRunnerListForTesting);
};
} // namespace internal
} // namespace base
#endif // BASE_TASK_SCHEDULER_LAZY_TASK_RUNNER_H_
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/task_scheduler/lazy_task_runner.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/sequence_checker_impl.h"
#include "base/task_scheduler/scoped_set_task_priority_for_current_thread.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_checker_impl.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_WIN)
#include "base/win/com_init_util.h"
#endif
namespace base {
namespace {
LazySequencedTaskRunner g_sequenced_task_runner_user_visible =
LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER({TaskPriority::USER_VISIBLE});
LazySequencedTaskRunner g_sequenced_task_runner_user_blocking =
LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER({TaskPriority::USER_BLOCKING});
LazySingleThreadTaskRunner g_single_thread_task_runner_user_visible =
LAZY_SINGLE_THREAD_TASK_RUNNER_INITIALIZER(
{TaskPriority::USER_VISIBLE},
SingleThreadTaskRunnerThreadMode::SHARED);
LazySingleThreadTaskRunner g_single_thread_task_runner_user_blocking =
LAZY_SINGLE_THREAD_TASK_RUNNER_INITIALIZER(
{TaskPriority::USER_BLOCKING},
SingleThreadTaskRunnerThreadMode::SHARED);
#if defined(OS_WIN)
LazyCOMSTATaskRunner g_com_sta_task_runner_user_visible =
LAZY_COM_STA_TASK_RUNNER_INITIALIZER(
{TaskPriority::USER_VISIBLE},
SingleThreadTaskRunnerThreadMode::SHARED);
LazyCOMSTATaskRunner g_com_sta_task_runner_user_blocking =
LAZY_COM_STA_TASK_RUNNER_INITIALIZER(
{TaskPriority::USER_BLOCKING},
SingleThreadTaskRunnerThreadMode::SHARED);
#endif // defined(OS_WIN)
void InitCheckers(SequenceCheckerImpl* sequence_checker,
ThreadCheckerImpl* thread_checker) {
sequence_checker->DetachFromSequence();
EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
thread_checker->DetachFromThread();
EXPECT_TRUE(thread_checker->CalledOnValidThread());
}
void ExpectSequencedEnvironment(SequenceCheckerImpl* sequence_checker,
ThreadCheckerImpl* thread_checker,
TaskPriority expected_priority) {
EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
EXPECT_FALSE(thread_checker->CalledOnValidThread());
EXPECT_EQ(expected_priority, internal::GetTaskPriorityForCurrentThread());
}
void ExpectSingleThreadEnvironment(SequenceCheckerImpl* sequence_checker,
ThreadCheckerImpl* thread_checker,
TaskPriority expected_priority
#if defined(OS_WIN)
,
bool expect_com_sta = false
#endif
) {
EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
EXPECT_TRUE(thread_checker->CalledOnValidThread());
EXPECT_EQ(expected_priority, internal::GetTaskPriorityForCurrentThread());
#if defined(OS_WIN)
if (expect_com_sta)
win::AssertComApartmentType(win::ComApartmentType::STA);
#endif
}
class TaskSchedulerLazyTaskRunnerEnvironmentTest : public testing::Test {
protected:
TaskSchedulerLazyTaskRunnerEnvironmentTest() = default;
void TestTaskRunnerEnvironment(scoped_refptr<SequencedTaskRunner> task_runner,
bool expect_single_thread,
TaskPriority expected_priority
#if defined(OS_WIN)
,
bool expect_com_sta = false
#endif
) {
SequenceCheckerImpl sequence_checker;
ThreadCheckerImpl thread_checker;
task_runner->PostTask(FROM_HERE,
BindOnce(&InitCheckers, Unretained(&sequence_checker),
Unretained(&thread_checker)));
scoped_task_environment_.RunUntilIdle();
OnceClosure task =
expect_single_thread
? BindOnce(&ExpectSingleThreadEnvironment,
Unretained(&sequence_checker),
Unretained(&thread_checker), expected_priority
#if defined(OS_WIN)
,
expect_com_sta
#endif
)
: BindOnce(&ExpectSequencedEnvironment,
Unretained(&sequence_checker),
Unretained(&thread_checker), expected_priority);
task_runner->PostTask(FROM_HERE, std::move(task));
scoped_task_environment_.RunUntilIdle();
}
test::ScopedTaskEnvironment scoped_task_environment_;
private:
DISALLOW_COPY_AND_ASSIGN(TaskSchedulerLazyTaskRunnerEnvironmentTest);
};
} // namespace
TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
LazySequencedTaskRunnerUserVisible) {
TestTaskRunnerEnvironment(g_sequenced_task_runner_user_visible.Get(), false,
TaskPriority::USER_VISIBLE);
}
TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
LazySequencedTaskRunnerUserBlocking) {
TestTaskRunnerEnvironment(g_sequenced_task_runner_user_blocking.Get(), false,
TaskPriority::USER_BLOCKING);
}
TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
LazySingleThreadTaskRunnerUserVisible) {
TestTaskRunnerEnvironment(g_single_thread_task_runner_user_visible.Get(),
true, TaskPriority::USER_VISIBLE);
}
TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
LazySingleThreadTaskRunnerUserBlocking) {
TestTaskRunnerEnvironment(g_single_thread_task_runner_user_blocking.Get(),
true, TaskPriority::USER_BLOCKING);
}
#if defined(OS_WIN)
TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
LazyCOMSTATaskRunnerUserVisible) {
TestTaskRunnerEnvironment(g_com_sta_task_runner_user_visible.Get(), true,
TaskPriority::USER_VISIBLE, true);
}
TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
LazyCOMSTATaskRunnerUserBlocking) {
TestTaskRunnerEnvironment(g_com_sta_task_runner_user_blocking.Get(), true,
TaskPriority::USER_BLOCKING, true);
}
#endif // defined(OS_WIN)
TEST(TaskSchdulerLazyTaskRunnerTest, LazySequencedTaskRunnerReset) {
for (int i = 0; i < 2; ++i) {
test::ScopedTaskEnvironment scoped_task_environment;
// If the TaskRunner isn't released when the test::ScopedTaskEnvironment
// goes out of scope, the second invocation of the line below will access a
// deleted TaskScheduler and crash.
g_sequenced_task_runner_user_visible.Get()->PostTask(FROM_HERE,
BindOnce(&DoNothing));
}
}
TEST(TaskSchdulerLazyTaskRunnerTest, LazySingleThreadTaskRunnerReset) {
for (int i = 0; i < 2; ++i) {
test::ScopedTaskEnvironment scoped_task_environment;
// If the TaskRunner isn't released when the test::ScopedTaskEnvironment
// goes out of scope, the second invocation of the line below will access a
// deleted TaskScheduler and crash.
g_single_thread_task_runner_user_visible.Get()->PostTask(
FROM_HERE, BindOnce(&DoNothing));
}
}
#if defined(OS_WIN)
TEST(TaskSchdulerLazyTaskRunnerTest, LazyCOMSTATaskRunnerReset) {
for (int i = 0; i < 2; ++i) {
test::ScopedTaskEnvironment scoped_task_environment;
// If the TaskRunner isn't released when the test::ScopedTaskEnvironment
// goes out of scope, the second invocation of the line below will access a
// deleted TaskScheduler and crash.
g_com_sta_task_runner_user_visible.Get()->PostTask(FROM_HERE,
BindOnce(&DoNothing));
}
}
#endif // defined(OS_WIN)
} // namespace base
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/task_scheduler/lazy_task_runner.h"
namespace base { namespace base {
...@@ -102,6 +103,10 @@ class ScopedTaskEnvironment { ...@@ -102,6 +103,10 @@ class ScopedTaskEnvironment {
// Owned by |task_scheduler_|. // Owned by |task_scheduler_|.
TestTaskTracker* const task_tracker_; TestTaskTracker* const task_tracker_;
// Ensures destruction of lazy TaskRunners when this is destroyed.
internal::ScopedLazyTaskRunnerListForTesting
scoped_lazy_task_runner_list_for_testing_;
DISALLOW_COPY_AND_ASSIGN(ScopedTaskEnvironment); DISALLOW_COPY_AND_ASSIGN(ScopedTaskEnvironment);
}; };
......
...@@ -122,11 +122,11 @@ assigned files by: ...@@ -122,11 +122,11 @@ assigned files by:
## Other known migration hurdles and recommended paradigms ## Other known migration hurdles and recommended paradigms
* Everything in a file/component needs to run on the same sequence but there * Everything in a file/component needs to run on the same sequence but there
isn't a clear place to own/access the common SequencedTaskRunner => isn't a clear place to own/access the common SequencedTaskRunner =>
[base::Lazy*TaskRunner](https://chromium-review.googlesource.com/c/524141/). base::Lazy(Sequenced|SingleThread|COMSTA)TaskRunner.
* Mojo isn't sequence-friendly yet ([coming soon](https://crbug.com/678155)). * Mojo isn't sequence-friendly yet ([coming soon](https://crbug.com/678155)).
Use base::CreateSingleThreadTaskRunnerWithTraits() instead of Use base::CreateSingleThreadTaskRunnerWithTraits() instead of
base::CreateSequenceTaskRunnerWithTraits() for sequences that need to use mojo base::CreateSequencedTaskRunnerWithTraits() for sequences that need to use
constructs for now (tag with TODO against https://crbug.com/678155). mojo constructs for now (tag with TODO against https://crbug.com/678155).
* For anything else, ping [base/task_scheduler/OWNERS](https://cs.chromium.org/chromium/src/base/task_scheduler/OWNERS) * For anything else, ping [base/task_scheduler/OWNERS](https://cs.chromium.org/chromium/src/base/task_scheduler/OWNERS)
or [scheduler-dev@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/scheduler-dev), or [scheduler-dev@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/scheduler-dev),
thanks! thanks!
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