1*6777b538SAndroid Build Coastguard Worker // Copyright 2010 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/message_loop/message_pump.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
8*6777b538SAndroid Build Coastguard Worker #include "base/message_loop/message_pump_default.h"
9*6777b538SAndroid Build Coastguard Worker #include "base/message_loop/message_pump_for_io.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/message_loop/message_pump_for_ui.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/task/task_features.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
14*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
15*6777b538SAndroid Build Coastguard Worker
16*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
17*6777b538SAndroid Build Coastguard Worker #include "base/message_loop/message_pump_apple.h"
18*6777b538SAndroid Build Coastguard Worker #endif
19*6777b538SAndroid Build Coastguard Worker
20*6777b538SAndroid Build Coastguard Worker namespace base {
21*6777b538SAndroid Build Coastguard Worker
22*6777b538SAndroid Build Coastguard Worker namespace {
23*6777b538SAndroid Build Coastguard Worker
24*6777b538SAndroid Build Coastguard Worker constexpr uint64_t kAlignWakeUpsMask = 1;
25*6777b538SAndroid Build Coastguard Worker constexpr uint64_t kLeewayOffset = 1;
26*6777b538SAndroid Build Coastguard Worker
PackAlignWakeUpsAndLeeway(bool align_wake_ups,TimeDelta leeway)27*6777b538SAndroid Build Coastguard Worker constexpr uint64_t PackAlignWakeUpsAndLeeway(bool align_wake_ups,
28*6777b538SAndroid Build Coastguard Worker TimeDelta leeway) {
29*6777b538SAndroid Build Coastguard Worker return (static_cast<uint64_t>(leeway.InMilliseconds()) << kLeewayOffset) |
30*6777b538SAndroid Build Coastguard Worker (align_wake_ups ? kAlignWakeUpsMask : 0);
31*6777b538SAndroid Build Coastguard Worker }
32*6777b538SAndroid Build Coastguard Worker
33*6777b538SAndroid Build Coastguard Worker // This stores the current state of |kAlignWakeUps| and leeway. The last bit
34*6777b538SAndroid Build Coastguard Worker // represents if |kAlignWakeUps| is enabled, and the other bits represent the
35*6777b538SAndroid Build Coastguard Worker // leeway value applied to delayed tasks in milliseconds. An atomic is used here
36*6777b538SAndroid Build Coastguard Worker // because the value is queried from multiple threads.
37*6777b538SAndroid Build Coastguard Worker std::atomic<uint64_t> g_align_wake_ups_and_leeway =
38*6777b538SAndroid Build Coastguard Worker PackAlignWakeUpsAndLeeway(false, kDefaultLeeway);
39*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
40*6777b538SAndroid Build Coastguard Worker bool g_explicit_high_resolution_timer_win = true;
41*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_WIN)
42*6777b538SAndroid Build Coastguard Worker
43*6777b538SAndroid Build Coastguard Worker MessagePump::MessagePumpFactory* message_pump_for_ui_factory_ = nullptr;
44*6777b538SAndroid Build Coastguard Worker
45*6777b538SAndroid Build Coastguard Worker } // namespace
46*6777b538SAndroid Build Coastguard Worker
47*6777b538SAndroid Build Coastguard Worker MessagePump::MessagePump() = default;
48*6777b538SAndroid Build Coastguard Worker
49*6777b538SAndroid Build Coastguard Worker MessagePump::~MessagePump() = default;
50*6777b538SAndroid Build Coastguard Worker
HandleNestedNativeLoopWithApplicationTasks(bool application_tasks_desired)51*6777b538SAndroid Build Coastguard Worker bool MessagePump::HandleNestedNativeLoopWithApplicationTasks(
52*6777b538SAndroid Build Coastguard Worker bool application_tasks_desired) {
53*6777b538SAndroid Build Coastguard Worker return false;
54*6777b538SAndroid Build Coastguard Worker }
55*6777b538SAndroid Build Coastguard Worker
56*6777b538SAndroid Build Coastguard Worker // static
OverrideMessagePumpForUIFactory(MessagePumpFactory * factory)57*6777b538SAndroid Build Coastguard Worker void MessagePump::OverrideMessagePumpForUIFactory(MessagePumpFactory* factory) {
58*6777b538SAndroid Build Coastguard Worker DCHECK(!message_pump_for_ui_factory_);
59*6777b538SAndroid Build Coastguard Worker message_pump_for_ui_factory_ = factory;
60*6777b538SAndroid Build Coastguard Worker }
61*6777b538SAndroid Build Coastguard Worker
62*6777b538SAndroid Build Coastguard Worker // static
IsMessagePumpForUIFactoryOveridden()63*6777b538SAndroid Build Coastguard Worker bool MessagePump::IsMessagePumpForUIFactoryOveridden() {
64*6777b538SAndroid Build Coastguard Worker return message_pump_for_ui_factory_ != nullptr;
65*6777b538SAndroid Build Coastguard Worker }
66*6777b538SAndroid Build Coastguard Worker
67*6777b538SAndroid Build Coastguard Worker // static
Create(MessagePumpType type)68*6777b538SAndroid Build Coastguard Worker std::unique_ptr<MessagePump> MessagePump::Create(MessagePumpType type) {
69*6777b538SAndroid Build Coastguard Worker switch (type) {
70*6777b538SAndroid Build Coastguard Worker case MessagePumpType::UI:
71*6777b538SAndroid Build Coastguard Worker if (message_pump_for_ui_factory_)
72*6777b538SAndroid Build Coastguard Worker return message_pump_for_ui_factory_();
73*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
74*6777b538SAndroid Build Coastguard Worker return message_pump_apple::Create();
75*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_NACL) || BUILDFLAG(IS_AIX)
76*6777b538SAndroid Build Coastguard Worker // Currently NaCl and AIX don't have a UI MessagePump.
77*6777b538SAndroid Build Coastguard Worker // TODO(abarth): Figure out if we need this.
78*6777b538SAndroid Build Coastguard Worker NOTREACHED();
79*6777b538SAndroid Build Coastguard Worker return nullptr;
80*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_ANDROID)
81*6777b538SAndroid Build Coastguard Worker {
82*6777b538SAndroid Build Coastguard Worker auto message_pump = std::make_unique<MessagePumpAndroid>();
83*6777b538SAndroid Build Coastguard Worker message_pump->set_is_type_ui(true);
84*6777b538SAndroid Build Coastguard Worker return message_pump;
85*6777b538SAndroid Build Coastguard Worker }
86*6777b538SAndroid Build Coastguard Worker #else
87*6777b538SAndroid Build Coastguard Worker return std::make_unique<MessagePumpForUI>();
88*6777b538SAndroid Build Coastguard Worker #endif
89*6777b538SAndroid Build Coastguard Worker
90*6777b538SAndroid Build Coastguard Worker case MessagePumpType::IO:
91*6777b538SAndroid Build Coastguard Worker return std::make_unique<MessagePumpForIO>();
92*6777b538SAndroid Build Coastguard Worker
93*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
94*6777b538SAndroid Build Coastguard Worker case MessagePumpType::JAVA:
95*6777b538SAndroid Build Coastguard Worker return std::make_unique<MessagePumpAndroid>();
96*6777b538SAndroid Build Coastguard Worker #endif
97*6777b538SAndroid Build Coastguard Worker
98*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
99*6777b538SAndroid Build Coastguard Worker case MessagePumpType::NS_RUNLOOP:
100*6777b538SAndroid Build Coastguard Worker return std::make_unique<MessagePumpNSRunLoop>();
101*6777b538SAndroid Build Coastguard Worker #endif
102*6777b538SAndroid Build Coastguard Worker
103*6777b538SAndroid Build Coastguard Worker case MessagePumpType::CUSTOM:
104*6777b538SAndroid Build Coastguard Worker NOTREACHED();
105*6777b538SAndroid Build Coastguard Worker return nullptr;
106*6777b538SAndroid Build Coastguard Worker
107*6777b538SAndroid Build Coastguard Worker case MessagePumpType::DEFAULT:
108*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_IOS)
109*6777b538SAndroid Build Coastguard Worker // On iOS, a native runloop is always required to pump system work.
110*6777b538SAndroid Build Coastguard Worker return std::make_unique<MessagePumpCFRunLoop>();
111*6777b538SAndroid Build Coastguard Worker #else
112*6777b538SAndroid Build Coastguard Worker return std::make_unique<MessagePumpDefault>();
113*6777b538SAndroid Build Coastguard Worker #endif
114*6777b538SAndroid Build Coastguard Worker }
115*6777b538SAndroid Build Coastguard Worker }
116*6777b538SAndroid Build Coastguard Worker
117*6777b538SAndroid Build Coastguard Worker // static
InitializeFeatures()118*6777b538SAndroid Build Coastguard Worker void MessagePump::InitializeFeatures() {
119*6777b538SAndroid Build Coastguard Worker ResetAlignWakeUpsState();
120*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
121*6777b538SAndroid Build Coastguard Worker g_explicit_high_resolution_timer_win =
122*6777b538SAndroid Build Coastguard Worker FeatureList::IsEnabled(kExplicitHighResolutionTimerWin);
123*6777b538SAndroid Build Coastguard Worker MessagePumpWin::InitializeFeatures();
124*6777b538SAndroid Build Coastguard Worker #endif
125*6777b538SAndroid Build Coastguard Worker }
126*6777b538SAndroid Build Coastguard Worker
127*6777b538SAndroid Build Coastguard Worker // static
OverrideAlignWakeUpsState(bool enabled,TimeDelta leeway)128*6777b538SAndroid Build Coastguard Worker void MessagePump::OverrideAlignWakeUpsState(bool enabled, TimeDelta leeway) {
129*6777b538SAndroid Build Coastguard Worker g_align_wake_ups_and_leeway.store(PackAlignWakeUpsAndLeeway(enabled, leeway),
130*6777b538SAndroid Build Coastguard Worker std::memory_order_relaxed);
131*6777b538SAndroid Build Coastguard Worker }
132*6777b538SAndroid Build Coastguard Worker
133*6777b538SAndroid Build Coastguard Worker // static
ResetAlignWakeUpsState()134*6777b538SAndroid Build Coastguard Worker void MessagePump::ResetAlignWakeUpsState() {
135*6777b538SAndroid Build Coastguard Worker OverrideAlignWakeUpsState(FeatureList::IsEnabled(kAlignWakeUps),
136*6777b538SAndroid Build Coastguard Worker kTaskLeewayParam.Get());
137*6777b538SAndroid Build Coastguard Worker }
138*6777b538SAndroid Build Coastguard Worker
139*6777b538SAndroid Build Coastguard Worker // static
GetAlignWakeUpsEnabled()140*6777b538SAndroid Build Coastguard Worker bool MessagePump::GetAlignWakeUpsEnabled() {
141*6777b538SAndroid Build Coastguard Worker return g_align_wake_ups_and_leeway.load(std::memory_order_relaxed) &
142*6777b538SAndroid Build Coastguard Worker kAlignWakeUpsMask;
143*6777b538SAndroid Build Coastguard Worker }
144*6777b538SAndroid Build Coastguard Worker
145*6777b538SAndroid Build Coastguard Worker // static
GetLeewayIgnoringThreadOverride()146*6777b538SAndroid Build Coastguard Worker TimeDelta MessagePump::GetLeewayIgnoringThreadOverride() {
147*6777b538SAndroid Build Coastguard Worker return Milliseconds(
148*6777b538SAndroid Build Coastguard Worker g_align_wake_ups_and_leeway.load(std::memory_order_relaxed) >>
149*6777b538SAndroid Build Coastguard Worker kLeewayOffset);
150*6777b538SAndroid Build Coastguard Worker }
151*6777b538SAndroid Build Coastguard Worker
152*6777b538SAndroid Build Coastguard Worker // static
GetLeewayForCurrentThread()153*6777b538SAndroid Build Coastguard Worker TimeDelta MessagePump::GetLeewayForCurrentThread() {
154*6777b538SAndroid Build Coastguard Worker // For some threads, there might be an override of the leeway, so check it
155*6777b538SAndroid Build Coastguard Worker // first.
156*6777b538SAndroid Build Coastguard Worker auto leeway_override = PlatformThread::GetThreadLeewayOverride();
157*6777b538SAndroid Build Coastguard Worker if (leeway_override.has_value()) {
158*6777b538SAndroid Build Coastguard Worker return leeway_override.value();
159*6777b538SAndroid Build Coastguard Worker }
160*6777b538SAndroid Build Coastguard Worker return GetLeewayIgnoringThreadOverride();
161*6777b538SAndroid Build Coastguard Worker }
162*6777b538SAndroid Build Coastguard Worker
AdjustDelayedRunTime(TimeTicks earliest_time,TimeTicks run_time,TimeTicks latest_time)163*6777b538SAndroid Build Coastguard Worker TimeTicks MessagePump::AdjustDelayedRunTime(TimeTicks earliest_time,
164*6777b538SAndroid Build Coastguard Worker TimeTicks run_time,
165*6777b538SAndroid Build Coastguard Worker TimeTicks latest_time) {
166*6777b538SAndroid Build Coastguard Worker // Windows relies on the low resolution timer rather than manual wake up
167*6777b538SAndroid Build Coastguard Worker // alignment when the leeway is less than the OS default timer resolution.
168*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
169*6777b538SAndroid Build Coastguard Worker if (g_explicit_high_resolution_timer_win &&
170*6777b538SAndroid Build Coastguard Worker GetLeewayForCurrentThread() <=
171*6777b538SAndroid Build Coastguard Worker Milliseconds(Time::kMinLowResolutionThresholdMs)) {
172*6777b538SAndroid Build Coastguard Worker return earliest_time;
173*6777b538SAndroid Build Coastguard Worker }
174*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_WIN)
175*6777b538SAndroid Build Coastguard Worker if (GetAlignWakeUpsEnabled()) {
176*6777b538SAndroid Build Coastguard Worker TimeTicks aligned_run_time = earliest_time.SnappedToNextTick(
177*6777b538SAndroid Build Coastguard Worker TimeTicks(), GetLeewayForCurrentThread());
178*6777b538SAndroid Build Coastguard Worker return std::min(aligned_run_time, latest_time);
179*6777b538SAndroid Build Coastguard Worker }
180*6777b538SAndroid Build Coastguard Worker return run_time;
181*6777b538SAndroid Build Coastguard Worker }
182*6777b538SAndroid Build Coastguard Worker
183*6777b538SAndroid Build Coastguard Worker } // namespace base
184