xref: /aosp_15_r20/external/cronet/base/message_loop/message_pump.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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