diff options
Diffstat (limited to 'chromium/base/threading')
-rw-r--r-- | chromium/base/threading/platform_thread_unittest.cc | 7 | ||||
-rw-r--r-- | chromium/base/threading/platform_thread_win.cc | 50 | ||||
-rw-r--r-- | chromium/base/threading/platform_thread_win.h | 4 | ||||
-rw-r--r-- | chromium/base/threading/platform_thread_win_unittest.cc | 20 | ||||
-rw-r--r-- | chromium/base/threading/sequenced_task_runner_handle.cc | 6 | ||||
-rw-r--r-- | chromium/base/threading/thread.cc | 97 | ||||
-rw-r--r-- | chromium/base/threading/thread.h | 20 | ||||
-rw-r--r-- | chromium/base/threading/thread_perftest.cc | 1 | ||||
-rw-r--r-- | chromium/base/threading/thread_restrictions.h | 17 | ||||
-rw-r--r-- | chromium/base/threading/thread_task_runner_handle.cc | 7 | ||||
-rw-r--r-- | chromium/base/threading/thread_unittest.cc | 43 |
11 files changed, 183 insertions, 89 deletions
diff --git a/chromium/base/threading/platform_thread_unittest.cc b/chromium/base/threading/platform_thread_unittest.cc index 2ef69fe32f0..96ea6629fc7 100644 --- a/chromium/base/threading/platform_thread_unittest.cc +++ b/chromium/base/threading/platform_thread_unittest.cc @@ -289,9 +289,7 @@ TEST(PlatformThreadTest, MAYBE_SetCurrentThreadPriority) { #if defined(OS_WIN) // Test changing a created thread's priority, with the // kWindowsThreadModeBackground feature enabled. -// Flaky: https://crbug.com/931706 -TEST(PlatformThreadTest, - DISABLED_SetCurrentThreadPriorityWithThreadModeBackground) { +TEST(PlatformThreadTest, SetCurrentThreadPriorityWithThreadModeBackground) { test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeature( features::kWindowsThreadModeBackground); @@ -301,9 +299,8 @@ TEST(PlatformThreadTest, // Test changing a created thread's priority, with the // kWindowsThreadModeBackground feature enabled, in an IDLE_PRIORITY_CLASS // process (regression test for https://crbug.com/901483). -// Flaky: https://crbug.com/931706 TEST(PlatformThreadTest, - DISABLED_SetCurrentThreadPriorityWithThreadModeBackgroundIdleProcess) { + SetCurrentThreadPriorityWithThreadModeBackgroundIdleProcess) { ::SetPriorityClass(Process::Current().Handle(), IDLE_PRIORITY_CLASS); test::ScopedFeatureList scoped_feature_list; diff --git a/chromium/base/threading/platform_thread_win.cc b/chromium/base/threading/platform_thread_win.cc index 0fef2a8d69c..2889b253b75 100644 --- a/chromium/base/threading/platform_thread_win.cc +++ b/chromium/base/threading/platform_thread_win.cc @@ -29,9 +29,9 @@ namespace base { namespace { -// The value returned by ::GetThreadPriority() after background thread mode is -// enabled on Windows 8+. -constexpr int kWin8AboveBackgroundThreadModePriority = -4; +// The most common value returned by ::GetThreadPriority() after background +// thread mode is enabled on Windows 7. +constexpr int kWin7BackgroundThreadModePriority = 4; // The information on how to set the thread name comes from // a MSDN article: http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspx @@ -401,17 +401,45 @@ void PlatformThread::SetCurrentThreadPriorityImpl(ThreadPriority priority) { // static ThreadPriority PlatformThread::GetCurrentThreadPriority() { + static_assert( + THREAD_PRIORITY_IDLE < 0, + "THREAD_PRIORITY_IDLE is >= 0 and will incorrectly cause errors."); + static_assert( + THREAD_PRIORITY_LOWEST < 0, + "THREAD_PRIORITY_LOWEST is >= 0 and will incorrectly cause errors."); + static_assert(THREAD_PRIORITY_BELOW_NORMAL < 0, + "THREAD_PRIORITY_BELOW_NORMAL is >= 0 and will incorrectly " + "cause errors."); + static_assert( + THREAD_PRIORITY_NORMAL == 0, + "The logic below assumes that THREAD_PRIORITY_NORMAL is zero. If it is " + "not, ThreadPriority::BACKGROUND may be incorrectly detected."); + static_assert(THREAD_PRIORITY_ABOVE_NORMAL >= 0, + "THREAD_PRIORITY_ABOVE_NORMAL is < 0 and will incorrectly be " + "translated to ThreadPriority::BACKGROUND."); + static_assert(THREAD_PRIORITY_HIGHEST >= 0, + "THREAD_PRIORITY_HIGHEST is < 0 and will incorrectly be " + "translated to ThreadPriority::BACKGROUND."); + static_assert(THREAD_PRIORITY_TIME_CRITICAL >= 0, + "THREAD_PRIORITY_TIME_CRITICAL is < 0 and will incorrectly be " + "translated to ThreadPriority::BACKGROUND."); + static_assert(THREAD_PRIORITY_ERROR_RETURN >= 0, + "THREAD_PRIORITY_ERROR_RETURN is < 0 and will incorrectly be " + "translated to ThreadPriority::BACKGROUND."); + const int priority = ::GetThreadPriority(PlatformThread::CurrentHandle().platform_handle()); + // Negative values represent a background priority. We have observed -3, -4, + // -6 when THREAD_MODE_BACKGROUND_* is used. THREAD_PRIORITY_IDLE, + // THREAD_PRIORITY_LOWEST and THREAD_PRIORITY_BELOW_NORMAL are other possible + // negative values. + if (priority < THREAD_PRIORITY_NORMAL) + return ThreadPriority::BACKGROUND; + switch (priority) { - case THREAD_PRIORITY_IDLE: - case internal::kWin7BackgroundThreadModePriority: + case kWin7BackgroundThreadModePriority: DCHECK_EQ(win::GetVersion(), win::Version::WIN7); - FALLTHROUGH; - case kWin8AboveBackgroundThreadModePriority: - case THREAD_PRIORITY_LOWEST: - case THREAD_PRIORITY_BELOW_NORMAL: return ThreadPriority::BACKGROUND; case THREAD_PRIORITY_NORMAL: return ThreadPriority::NORMAL; @@ -421,10 +449,10 @@ ThreadPriority PlatformThread::GetCurrentThreadPriority() { case THREAD_PRIORITY_TIME_CRITICAL: return ThreadPriority::REALTIME_AUDIO; case THREAD_PRIORITY_ERROR_RETURN: - DPCHECK(false) << "GetThreadPriority error"; + DPCHECK(false) << "::GetThreadPriority error"; } - NOTREACHED() << "GetCurrentThreadPriority returned " << priority << "."; + NOTREACHED() << "::GetThreadPriority returned " << priority << "."; return ThreadPriority::NORMAL; } diff --git a/chromium/base/threading/platform_thread_win.h b/chromium/base/threading/platform_thread_win.h index d1bf4205de4..879d5062667 100644 --- a/chromium/base/threading/platform_thread_win.h +++ b/chromium/base/threading/platform_thread_win.h @@ -25,10 +25,6 @@ BASE_EXPORT extern const Feature kWindowsThreadModeBackground; namespace internal { -// The value returned by ::GetThreadPriority() after background thread mode is -// enabled on Windows 7. Exposed for unit tests. -constexpr int kWin7BackgroundThreadModePriority = 4; - // Assert that the memory priority of |thread| is |memory_priority|. No-op on // Windows 7 because ::GetThreadInformation() is not available. Exposed for unit // tests. diff --git a/chromium/base/threading/platform_thread_win_unittest.cc b/chromium/base/threading/platform_thread_win_unittest.cc index 15c9939da46..de1d2cab595 100644 --- a/chromium/base/threading/platform_thread_win_unittest.cc +++ b/chromium/base/threading/platform_thread_win_unittest.cc @@ -24,9 +24,7 @@ namespace base { // behavior which we suspect is a Windows kernel bug. If this test starts // failing, the mitigation for https://crbug.com/901483 in // PlatformThread::SetCurrentThreadPriority() should be revisited. -// Fails on various windows bots: https://crbug.com/931720. -TEST(PlatformThreadWinTest, - DISABLED_SetBackgroundThreadModeFailsInIdlePriorityProcess) { +TEST(PlatformThreadWinTest, SetBackgroundThreadModeFailsInIdlePriorityProcess) { PlatformThreadHandle::Handle thread_handle = PlatformThread::CurrentHandle().platform_handle(); @@ -53,23 +51,19 @@ TEST(PlatformThreadWinTest, EXPECT_TRUE(::SetThreadPriority(thread_handle, THREAD_MODE_BACKGROUND_BEGIN)); // On Win8, GetThreadPriority() stays NORMAL. On Win7, it can stay NORMAL or - // switch to one of the 2 priorities that are usually observed after entering + // switch to one of the various priorities that are observed after entering // thread mode background in a NORMAL_PRIORITY_CLASS process. On all Windows - // verisons, memory priority becomes VERY_LOW. + // versions, memory priority becomes VERY_LOW. // // Note: this documents the aforementioned kernel bug. Ideally this would // *not* be the case. const float priority_after_thread_mode_background_begin = ::GetThreadPriority(thread_handle); if (win::GetVersion() == win::Version::WIN7) { - constexpr std::array<int, 3> kExpectedWin7Priorities( - {// Priority if GetThreadPriority() is not affected. - THREAD_PRIORITY_NORMAL, - // Priorities if GetThreadPriority() behaves like in a - // NORMAL_PRIORITY_CLASS process. - THREAD_PRIORITY_IDLE, internal::kWin7BackgroundThreadModePriority}); - EXPECT_THAT(kExpectedWin7Priorities, - testing::Contains(priority_after_thread_mode_background_begin)); + if (priority_after_thread_mode_background_begin != THREAD_PRIORITY_NORMAL) { + EXPECT_EQ(ThreadPriority::BACKGROUND, + base::PlatformThread::GetCurrentThreadPriority()); + } } else { EXPECT_EQ(priority_after_thread_mode_background_begin, THREAD_PRIORITY_NORMAL); diff --git a/chromium/base/threading/sequenced_task_runner_handle.cc b/chromium/base/threading/sequenced_task_runner_handle.cc index 8a7e129cbe9..2bfc0cf42ee 100644 --- a/chromium/base/threading/sequenced_task_runner_handle.cc +++ b/chromium/base/threading/sequenced_task_runner_handle.cc @@ -23,8 +23,10 @@ LazyInstance<ThreadLocalPointer<SequencedTaskRunnerHandle>>::Leaky const scoped_refptr<SequencedTaskRunner>& SequencedTaskRunnerHandle::Get() { const SequencedTaskRunnerHandle* current = sequenced_task_runner_tls.Pointer()->Get(); - CHECK(current) << "Error: This caller requires a sequenced context (i.e. the " - "current task needs to run from a SequencedTaskRunner)."; + CHECK(current) + << "Error: This caller requires a sequenced context (i.e. the current " + "task needs to run from a SequencedTaskRunner). If you're in a test " + "refer to //docs/threading_and_tasks_testing.md."; return current->task_runner_; } diff --git a/chromium/base/threading/thread.cc b/chromium/base/threading/thread.cc index a411bb8a0e2..eecd3491890 100644 --- a/chromium/base/threading/thread.cc +++ b/chromium/base/threading/thread.cc @@ -4,14 +4,22 @@ #include "base/threading/thread.h" +#include <type_traits> + #include "base/bind.h" #include "base/bind_helpers.h" #include "base/lazy_instance.h" #include "base/location.h" #include "base/logging.h" #include "base/memory/ptr_util.h" +#include "base/memory/scoped_refptr.h" +#include "base/message_loop/message_loop_current.h" +#include "base/message_loop/message_pump.h" #include "base/run_loop.h" #include "base/synchronization/waitable_event.h" +#include "base/task/sequence_manager/sequence_manager_impl.h" +#include "base/task/sequence_manager/task_queue.h" +#include "base/task/simple_task_executor.h" #include "base/third_party/dynamic_annotations/dynamic_annotations.h" #include "base/threading/thread_id_name_manager.h" #include "base/threading/thread_local.h" @@ -38,6 +46,58 @@ namespace { base::LazyInstance<base::ThreadLocalBoolean>::Leaky lazy_tls_bool = LAZY_INSTANCE_INITIALIZER; +class SequenceManagerThreadDelegate : public Thread::Delegate { + public: + explicit SequenceManagerThreadDelegate( + MessagePumpType message_pump_type, + OnceCallback<std::unique_ptr<MessagePump>()> message_pump_factory) + : sequence_manager_( + sequence_manager::internal::SequenceManagerImpl::CreateUnbound( + sequence_manager::SequenceManager::Settings::Builder() + .SetMessagePumpType(message_pump_type) + .Build())), + default_task_queue_(sequence_manager_->CreateTaskQueue( + sequence_manager::TaskQueue::Spec("default_tq"))), + message_pump_factory_(std::move(message_pump_factory)) { + sequence_manager_->SetDefaultTaskRunner(default_task_queue_->task_runner()); + } + + ~SequenceManagerThreadDelegate() override = default; + + scoped_refptr<SingleThreadTaskRunner> GetDefaultTaskRunner() override { + // Surprisingly this might not be default_task_queue_->task_runner() which + // we set in the constructor. The Thread::Init() method could create a + // SequenceManager on top of the current one and call + // SequenceManager::SetDefaultTaskRunner which would propagate the new + // TaskRunner down to our SequenceManager. Turns out, code actually relies + // on this and somehow relies on + // SequenceManagerThreadDelegate::GetDefaultTaskRunner returning this new + // TaskRunner. So instead of returning default_task_queue_->task_runner() we + // need to query the SequenceManager for it. + // The underlying problem here is that Subclasses of Thread can do crazy + // stuff in Init() but they are not really in control of what happens in the + // Thread::Delegate, as this is passed in on calling StartWithOptions which + // could happen far away from where the Thread is created. We should + // consider getting rid of StartWithOptions, and pass them as a constructor + // argument instead. + return sequence_manager_->GetTaskRunner(); + } + + void BindToCurrentThread(TimerSlack timer_slack) override { + sequence_manager_->BindToMessagePump( + std::move(message_pump_factory_).Run()); + sequence_manager_->SetTimerSlack(timer_slack); + simple_task_executor_.emplace(GetDefaultTaskRunner()); + } + + private: + std::unique_ptr<sequence_manager::internal::SequenceManagerImpl> + sequence_manager_; + scoped_refptr<sequence_manager::TaskQueue> default_task_queue_; + OnceCallback<std::unique_ptr<MessagePump>()> message_pump_factory_; + base::Optional<SimpleTaskExecutor> simple_task_executor_; +}; + } // namespace Thread::Options::Options() = default; @@ -100,11 +160,13 @@ bool Thread::StartWithOptions(const Options& options) { DCHECK(!options.message_pump_factory); delegate_ = WrapUnique(options.delegate); } else if (options.message_pump_factory) { - delegate_ = std::make_unique<internal::MessageLoopThreadDelegate>( - MessageLoop::CreateUnbound(options.message_pump_factory.Run())); + delegate_ = std::make_unique<SequenceManagerThreadDelegate>( + MessagePumpType::CUSTOM, options.message_pump_factory); } else { - delegate_ = std::make_unique<internal::MessageLoopThreadDelegate>( - MessageLoop::CreateUnbound(options.message_pump_type)); + delegate_ = std::make_unique<SequenceManagerThreadDelegate>( + options.message_pump_type, + BindOnce([](MessagePumpType type) { return MessagePump::Create(type); }, + options.message_pump_type)); } start_event_.Reset(); @@ -291,9 +353,10 @@ void Thread::ThreadMain() { #if defined(OS_WIN) std::unique_ptr<win::ScopedCOMInitializer> com_initializer; if (com_status_ != NONE) { - com_initializer.reset((com_status_ == STA) ? - new win::ScopedCOMInitializer() : - new win::ScopedCOMInitializer(win::ScopedCOMInitializer::kMTA)); + com_initializer.reset( + (com_status_ == STA) + ? new win::ScopedCOMInitializer() + : new win::ScopedCOMInitializer(win::ScopedCOMInitializer::kMTA)); } #endif @@ -337,24 +400,4 @@ void Thread::ThreadQuitHelper() { SetThreadWasQuitProperly(true); } -namespace internal { - -MessageLoopThreadDelegate::MessageLoopThreadDelegate( - std::unique_ptr<MessageLoop> message_loop) - : message_loop_(std::move(message_loop)) {} - -MessageLoopThreadDelegate::~MessageLoopThreadDelegate() {} - -scoped_refptr<SingleThreadTaskRunner> -MessageLoopThreadDelegate::GetDefaultTaskRunner() { - return message_loop_->task_runner(); -} - -void MessageLoopThreadDelegate::BindToCurrentThread(TimerSlack timer_slack) { - message_loop_->BindToCurrentThread(); - message_loop_->SetTimerSlack(timer_slack); -} - -} // namespace internal - } // namespace base diff --git a/chromium/base/threading/thread.h b/chromium/base/threading/thread.h index 73a444f178a..312caab25a2 100644 --- a/chromium/base/threading/thread.h +++ b/chromium/base/threading/thread.h @@ -13,8 +13,6 @@ #include "base/base_export.h" #include "base/callback.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/message_loop/message_loop_current.h" #include "base/message_loop/message_pump_type.h" #include "base/message_loop/timer_slack.h" #include "base/sequence_checker.h" @@ -331,24 +329,6 @@ class BASE_EXPORT Thread : PlatformThread::Delegate { DISALLOW_COPY_AND_ASSIGN(Thread); }; -namespace internal { - -class BASE_EXPORT MessageLoopThreadDelegate : public Thread::Delegate { - public: - explicit MessageLoopThreadDelegate(std::unique_ptr<MessageLoop> message_loop); - - ~MessageLoopThreadDelegate() override; - - // Thread::Delegate: - scoped_refptr<SingleThreadTaskRunner> GetDefaultTaskRunner() override; - void BindToCurrentThread(TimerSlack timer_slack) override; - - private: - std::unique_ptr<MessageLoop> message_loop_; -}; - -} // namespace internal - } // namespace base #endif // BASE_THREADING_THREAD_H_ diff --git a/chromium/base/threading/thread_perftest.cc b/chromium/base/threading/thread_perftest.cc index e19b18bf523..5e1e65bc7c3 100644 --- a/chromium/base/threading/thread_perftest.cc +++ b/chromium/base/threading/thread_perftest.cc @@ -12,6 +12,7 @@ #include "base/command_line.h" #include "base/location.h" #include "base/memory/ptr_util.h" +#include "base/message_loop/message_loop_current.h" #include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" #include "base/synchronization/condition_variable.h" diff --git a/chromium/base/threading/thread_restrictions.h b/chromium/base/threading/thread_restrictions.h index 052978192ab..c93f1fcaec0 100644 --- a/chromium/base/threading/thread_restrictions.h +++ b/chromium/base/threading/thread_restrictions.h @@ -179,9 +179,6 @@ class HistoryReportJniBridge; namespace gpu { class GpuChannelHost; } -namespace leveldb { -class LevelDBMojoProxy; -} namespace leveldb_env { class DBTracker; } @@ -189,6 +186,7 @@ namespace media { class AudioInputDevice; class AudioOutputDevice; class BlockingUrlProtocol; +class PaintCanvasVideoRenderer; } namespace memory_instrumentation { class OSMetrics; @@ -196,6 +194,9 @@ class OSMetrics; namespace midi { class TaskService; // https://crbug.com/796830 } +namespace module_installer { +class ScopedAllowModulePakLoad; +} namespace mojo { class CoreLibraryInitializer; class SyncCallRestrictions; @@ -204,6 +205,7 @@ class ScopedIPCSupport; } } namespace printing { +class PrintJobWorker; class PrinterQuery; } namespace rlz_lib { @@ -262,6 +264,10 @@ class WebMainLoop; class WebSubThread; } +namespace weblayer { +class ProfileImpl; +} + namespace webrtc { class DesktopConfigurationMonitor; } @@ -349,11 +355,14 @@ class BASE_EXPORT ScopedAllowBlocking { friend class cronet::CronetPrefsManager; friend class cronet::CronetURLRequestContext; friend class memory_instrumentation::OSMetrics; + friend class module_installer::ScopedAllowModulePakLoad; friend class mojo::CoreLibraryInitializer; + friend class printing::PrintJobWorker; friend class resource_coordinator::TabManagerDelegate; // crbug.com/778703 friend class ui::MaterialDesignController; friend class web::WebSubThread; friend class StackSamplingProfiler; + friend class weblayer::ProfileImpl; ScopedAllowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF; ~ScopedAllowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF; @@ -407,7 +416,6 @@ class BASE_EXPORT ScopedAllowBaseSyncPrimitives { friend class functions::ExecScriptScopedAllowBaseSyncPrimitives; friend class history_report::HistoryReportJniBridge; friend class internal::TaskTracker; - friend class leveldb::LevelDBMojoProxy; friend class leveldb_env::DBTracker; friend class media::BlockingUrlProtocol; friend class mojo::core::ScopedIPCSupport; @@ -475,6 +483,7 @@ class BASE_EXPORT ScopedAllowBaseSyncPrimitivesOutsideBlockingScope { friend class content::SynchronousCompositorSyncCallBridge; friend class media::AudioInputDevice; friend class media::AudioOutputDevice; + friend class media::PaintCanvasVideoRenderer; friend class mojo::SyncCallRestrictions; friend class net::NetworkConfigWatcherMacThread; friend class viz::HostGpuMemoryBufferManager; diff --git a/chromium/base/threading/thread_task_runner_handle.cc b/chromium/base/threading/thread_task_runner_handle.cc index 27a3f84eee6..4a9ac88f61c 100644 --- a/chromium/base/threading/thread_task_runner_handle.cc +++ b/chromium/base/threading/thread_task_runner_handle.cc @@ -26,9 +26,10 @@ base::LazyInstance<base::ThreadLocalPointer<ThreadTaskRunnerHandle>>::Leaky const scoped_refptr<SingleThreadTaskRunner>& ThreadTaskRunnerHandle::Get() { const ThreadTaskRunnerHandle* current = thread_task_runner_tls.Pointer()->Get(); - CHECK(current) << "Error: This caller requires a single-threaded context " - "(i.e. the current task needs to run from a " - "SingleThreadTaskRunner)."; + CHECK(current) + << "Error: This caller requires a single-threaded context (i.e. the " + "current task needs to run from a SingleThreadTaskRunner). If you're " + "in a test refer to //docs/threading_and_tasks_testing.md."; return current->task_runner_; } diff --git a/chromium/base/threading/thread_unittest.cc b/chromium/base/threading/thread_unittest.cc index bdb57cc19fe..5f1722877ad 100644 --- a/chromium/base/threading/thread_unittest.cc +++ b/chromium/base/threading/thread_unittest.cc @@ -17,16 +17,21 @@ #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/synchronization/waitable_event.h" +#include "base/task/post_task.h" #include "base/task/sequence_manager/sequence_manager_impl.h" +#include "base/task/task_executor.h" +#include "base/test/bind_test_util.h" #include "base/test/gtest_util.h" #include "base/third_party/dynamic_annotations/dynamic_annotations.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" #include "build/build_config.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" using base::Thread; +using ::testing::NotNull; typedef PlatformTest ThreadTest; @@ -522,6 +527,44 @@ TEST_F(ThreadTest, FlushForTesting) { a.FlushForTesting(); } +TEST_F(ThreadTest, GetTaskExecutorForCurrentThread) { + Thread a("GetTaskExecutorForCurrentThread"); + ASSERT_TRUE(a.Start()); + + base::WaitableEvent event; + + a.task_runner()->PostTask( + FROM_HERE, base::BindLambdaForTesting([&]() { + EXPECT_THAT(base::GetTaskExecutorForCurrentThread(), NotNull()); + event.Signal(); + })); + + event.Wait(); + a.Stop(); +} + +TEST_F(ThreadTest, CurrentThread) { + Thread a("CurrentThread"); + ASSERT_TRUE(a.Start()); + + base::WaitableEvent event; + + a.task_runner()->PostTask( + FROM_HERE, base::BindLambdaForTesting([&]() { + EXPECT_EQ(a.task_runner(), + base::CreateSingleThreadTaskRunner({base::CurrentThread()})); + + // There's only a single task runner so base::TaskPriority is ignored. + EXPECT_EQ(a.task_runner(), base::CreateSingleThreadTaskRunner( + {base::CurrentThread(), + base::TaskPriority::BEST_EFFORT})); + event.Signal(); + })); + + event.Wait(); + a.Stop(); +} + namespace { class SequenceManagerThreadDelegate : public Thread::Delegate { |