Commit c11ab802 authored by Alex Clarke's avatar Alex Clarke Committed by Commit Bot

Allow SequenceManager's construction before the MessageLoop

This will be needed by the BrowserUIThreadScheduler.

Bug: 863341, 872372
Change-Id: Ic4db17372553b70ee1e41b4f654a0fa50fb9c72c
Reviewed-on: https://chromium-review.googlesource.com/1221308Reviewed-by: default avatarSami Kyöstilä <skyostil@chromium.org>
Commit-Queue: Alex Clarke <alexclarke@chromium.org>
Cr-Commit-Position: refs/heads/master@{#590676}
parent 3f755e2b
......@@ -58,6 +58,12 @@ class SequenceManager {
// performs this initialization automatically.
virtual void BindToCurrentThread() = 0;
// Finishes the initialization for a SequenceManager created via
// CreateUnboundSequenceManager(nullptr). Must not be called in any other
// circumstances. Note it's assumed |message_loop| outlives the
// SequenceManager.
virtual void BindToMessageLoop(MessageLoop* message_loop) = 0;
// Initializes the SequenceManager on the bound thread. Should only be called
// once and only after the ThreadController's dependencies were initialized.
// Note that CreateSequenceManagerOnCurrentThread() performs this
......
......@@ -148,6 +148,12 @@ std::unique_ptr<SequenceManagerImpl> SequenceManagerImpl::CreateUnbound(
message_loop, DefaultTickClock::GetInstance())));
}
void SequenceManagerImpl::BindToMessageLoop(MessageLoop* message_loop) {
controller_->SetMessageLoop(message_loop);
BindToCurrentThread();
CompleteInitializationOnBoundThread();
}
void SequenceManagerImpl::BindToCurrentThread() {
associated_thread_->BindToCurrentThread();
}
......
......@@ -98,6 +98,7 @@ class BASE_EXPORT SequenceManagerImpl
// SequenceManager implementation:
void BindToCurrentThread() override;
void BindToMessageLoop(MessageLoop* message_loop) override;
void CompleteInitializationOnBoundThread() override;
void SetObserver(Observer* observer) override;
void AddTaskObserver(MessageLoop::TaskObserver* task_observer) override;
......
......@@ -3343,6 +3343,31 @@ TEST_P(SequenceManagerTestWithCustomInitialization, OffThreadInitialization) {
thread.Stop();
}
TEST_P(SequenceManagerTestWithCustomInitialization,
SequenceManagerCreatedBeforeMessageLoop) {
std::unique_ptr<SequenceManager> manager =
CreateUnboundSequenceManager(nullptr);
scoped_refptr<TaskQueue> default_task_queue =
manager->CreateTaskQueue<TestTaskQueue>(TaskQueue::Spec("default"));
EXPECT_THAT(default_task_queue.get(), testing::NotNull());
std::unique_ptr<MessageLoop> message_loop(new MessageLoop());
manager->BindToMessageLoop(message_loop.get());
// Check that task posting works.
std::vector<EnqueueOrder> run_order;
default_task_queue->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
default_task_queue->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
default_task_queue->PostTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order));
RunLoop().RunUntilIdle();
EXPECT_THAT(run_order, ElementsAre(1u, 2u, 3u));
// We must release the SequenceManager before the MessageLoop because
// SequenceManager assumes the MessageLoop outlives it.
manager.reset();
}
} // namespace sequence_manager_impl_unittest
} // namespace internal
} // namespace sequence_manager
......
......@@ -13,6 +13,7 @@
namespace base {
class MessageLoop;
class TickClock;
struct PendingTask;
......@@ -67,6 +68,10 @@ class ThreadController {
// Has no effect on some platforms.
virtual void SetTimerSlack(TimerSlack timer_slack) = 0;
// Completes delayed initialization of a ThreadControllers created with a null
// MessageLoop. May only be called once.
virtual void SetMessageLoop(MessageLoop* message_loop) = 0;
// TODO(altimin): Get rid of the methods below.
// These methods exist due to current integration of SequenceManager
// with MessageLoop.
......
......@@ -51,7 +51,8 @@ std::unique_ptr<ThreadControllerImpl> ThreadControllerImpl::Create(
MessageLoop* message_loop,
const TickClock* time_source) {
return WrapUnique(new ThreadControllerImpl(
message_loop, message_loop->task_runner(), time_source));
message_loop, message_loop ? message_loop->task_runner() : nullptr,
time_source));
}
void ThreadControllerImpl::SetSequencedTaskSource(
......@@ -136,6 +137,9 @@ const TickClock* ThreadControllerImpl::GetClock() {
void ThreadControllerImpl::SetDefaultTaskRunner(
scoped_refptr<SingleThreadTaskRunner> task_runner) {
#if DCHECK_IS_ON()
default_task_runner_set_ = true;
#endif
if (!message_loop_)
return;
message_loop_->SetTaskRunner(task_runner);
......@@ -147,6 +151,17 @@ void ThreadControllerImpl::RestoreDefaultTaskRunner() {
message_loop_->SetTaskRunner(message_loop_task_runner_);
}
void ThreadControllerImpl::SetMessageLoop(MessageLoop* message_loop) {
DCHECK(!message_loop_);
DCHECK(message_loop);
#if DCHECK_IS_ON()
DCHECK(!default_task_runner_set_) << "This would undo SetDefaultTaskRunner";
#endif
message_loop_ = message_loop;
task_runner_ = message_loop->task_runner();
message_loop_task_runner_ = message_loop->task_runner();
}
void ThreadControllerImpl::WillQueueTask(PendingTask* pending_task) {
task_annotator_.WillQueueTask("SequenceManager::PostTask", pending_task);
}
......
......@@ -40,6 +40,7 @@ class BASE_EXPORT ThreadControllerImpl : public ThreadController,
void SetWorkBatchSize(int work_batch_size) override;
void WillQueueTask(PendingTask* pending_task) override;
void ScheduleWork() override;
void SetMessageLoop(MessageLoop* message_loop) override;
void SetNextDelayedDoWork(LazyNow* lazy_now, TimeTicks run_time) override;
void SetSequencedTaskSource(SequencedTaskSource* sequence) override;
void SetTimerSlack(TimerSlack timer_slack) override;
......@@ -124,6 +125,10 @@ class BASE_EXPORT ThreadControllerImpl : public ThreadController,
SequencedTaskSource* sequence_ = nullptr; // Not owned.
debug::TaskAnnotator task_annotator_;
#if DCHECK_IS_ON()
bool default_task_runner_set_ = false;
#endif
WeakPtrFactory<ThreadControllerImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ThreadControllerImpl);
......
......@@ -43,6 +43,12 @@ void ThreadControllerWithMessagePumpImpl::SetSequencedTaskSource(
main_thread_only().task_source = task_source;
}
void ThreadControllerWithMessagePumpImpl::SetMessageLoop(
MessageLoop* message_loop) {
NOTREACHED()
<< "ThreadControllerWithMessagePumpImpl doesn't support MessageLoops";
}
void ThreadControllerWithMessagePumpImpl::SetWorkBatchSize(
int work_batch_size) {
DCHECK_GE(work_batch_size, 1);
......
......@@ -34,6 +34,7 @@ class BASE_EXPORT ThreadControllerWithMessagePumpImpl
// ThreadController implementation:
void SetSequencedTaskSource(SequencedTaskSource* task_source) override;
void SetMessageLoop(MessageLoop* message_loop) override;
void SetWorkBatchSize(int work_batch_size) override;
void WillQueueTask(PendingTask* pending_task) override;
void ScheduleWork() override;
......
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