1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
base / task / sequence_manager / thread_controller_impl.h [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_TASK_SEQUENCE_MANAGER_THREAD_CONTROLLER_IMPL_H_
#define BASE_TASK_SEQUENCE_MANAGER_THREAD_CONTROLLER_IMPL_H_
#include <memory>
#include "base/base_export.h"
#include "base/cancelable_callback.h"
#include "base/compiler_specific.h"
#include "base/dcheck_is_on.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/sequence_checker.h"
#include "base/task/common/task_annotator.h"
#include "base/task/sequence_manager/thread_controller.h"
#include "base/task/sequence_manager/work_deduplicator.h"
#include "base/task/single_thread_task_runner.h"
#include "build/build_config.h"
namespace base {
namespace sequence_manager {
namespace internal {
class SequenceManagerImpl;
// This is the interface between a SequenceManager which sits on top of an
// underlying SequenceManagerImpl or SingleThreadTaskRunner. Currently it's only
// used for workers in blink although we'd intend to migrate those to
// ThreadControllerWithMessagePumpImpl (https://crbug.com/948051). Long term we
// intend to use this for sequence funneling.
class BASE_EXPORT ThreadControllerImpl : public ThreadController,
public RunLoop::NestingObserver {
public:
ThreadControllerImpl(const ThreadControllerImpl&) = delete;
ThreadControllerImpl& operator=(const ThreadControllerImpl&) = delete;
~ThreadControllerImpl() override;
// TODO(crbug.com/40620995): replace |funneled_sequence_manager| with
// |funneled_task_runner| when we sort out the workers
static std::unique_ptr<ThreadControllerImpl> Create(
SequenceManagerImpl* funneled_sequence_manager,
const TickClock* time_source);
// ThreadController:
void SetWorkBatchSize(int work_batch_size) override;
void WillQueueTask(PendingTask* pending_task) override;
void ScheduleWork() override;
void BindToCurrentThread(std::unique_ptr<MessagePump> message_pump) override;
void SetNextDelayedDoWork(LazyNow* lazy_now,
std::optional<WakeUp> wake_up) override;
void SetSequencedTaskSource(SequencedTaskSource* sequence) override;
bool RunsTasksInCurrentSequence() override;
void SetDefaultTaskRunner(scoped_refptr<SingleThreadTaskRunner>) override;
scoped_refptr<SingleThreadTaskRunner> GetDefaultTaskRunner() override;
void RestoreDefaultTaskRunner() override;
void AddNestingObserver(RunLoop::NestingObserver* observer) override;
void RemoveNestingObserver(RunLoop::NestingObserver* observer) override;
void SetTaskExecutionAllowedInNativeNestedLoop(bool allowed) override;
bool IsTaskExecutionAllowed() const override;
MessagePump* GetBoundMessagePump() const override;
#if BUILDFLAG(IS_IOS) || BUILDFLAG(IS_ANDROID)
void AttachToMessagePump() override;
#endif
#if BUILDFLAG(IS_IOS)
void DetachFromMessagePump() override;
#endif
void PrioritizeYieldingToNative(base::TimeTicks prioritize_until) override;
bool ShouldQuitRunLoopWhenIdle() override;
// RunLoop::NestingObserver:
void OnBeginNestedRunLoop() override;
void OnExitNestedRunLoop() override;
protected:
ThreadControllerImpl(SequenceManagerImpl* sequence_manager,
scoped_refptr<SingleThreadTaskRunner> task_runner,
const TickClock* time_source);
const raw_ptr<SequenceManagerImpl> funneled_sequence_manager_;
const scoped_refptr<SingleThreadTaskRunner> task_runner_;
raw_ptr<RunLoop::NestingObserver> nesting_observer_ = nullptr;
private:
enum class WorkType { kImmediate, kDelayed };
void DoWork(WorkType work_type);
// TODO(scheduler-dev): Maybe fold this into the main class and use
// thread annotations.
struct MainSequenceOnly {
MainSequenceOnly();
~MainSequenceOnly();
int work_batch_size_ = 1;
TimeTicks next_delayed_do_work = TimeTicks::Max();
};
MainSequenceOnly main_sequence_only_;
MainSequenceOnly& main_sequence_only() LIFETIME_BOUND {
DCHECK_CALLED_ON_VALID_SEQUENCE(associated_thread_->sequence_checker);
return main_sequence_only_;
}
const MainSequenceOnly& main_sequence_only() const LIFETIME_BOUND {
DCHECK_CALLED_ON_VALID_SEQUENCE(associated_thread_->sequence_checker);
return main_sequence_only_;
}
scoped_refptr<SingleThreadTaskRunner> message_loop_task_runner_;
RepeatingClosure immediate_do_work_closure_;
RepeatingClosure delayed_do_work_closure_;
CancelableRepeatingClosure cancelable_delayed_do_work_closure_;
raw_ptr<SequencedTaskSource> sequence_ = nullptr; // Not owned.
TaskAnnotator task_annotator_;
WorkDeduplicator work_deduplicator_;
#if DCHECK_IS_ON()
bool default_task_runner_set_ = false;
#endif
WeakPtrFactory<ThreadControllerImpl> weak_factory_{this};
};
} // namespace internal
} // namespace sequence_manager
} // namespace base
#endif // BASE_TASK_SEQUENCE_MANAGER_THREAD_CONTROLLER_IMPL_H_