| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "platform/scheduler/renderer/renderer_scheduler_impl.h" | 5 #include "platform/scheduler/renderer/renderer_scheduler_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/debug/stack_trace.h" | 8 #include "base/debug/stack_trace.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 idle_helper_(&helper_, | 94 idle_helper_(&helper_, |
| 95 this, | 95 this, |
| 96 "renderer.scheduler", | 96 "renderer.scheduler", |
| 97 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), | 97 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 98 "RendererSchedulerIdlePeriod", | 98 "RendererSchedulerIdlePeriod", |
| 99 base::TimeDelta()), | 99 base::TimeDelta()), |
| 100 idle_canceled_delayed_task_sweeper_("renderer.scheduler", | 100 idle_canceled_delayed_task_sweeper_("renderer.scheduler", |
| 101 &helper_, | 101 &helper_, |
| 102 idle_helper_.IdleTaskRunner()), | 102 idle_helper_.IdleTaskRunner()), |
| 103 render_widget_scheduler_signals_(this), | 103 render_widget_scheduler_signals_(this), |
| 104 control_task_runner_(helper_.ControlTaskRunner()), | 104 control_task_runner_(helper_.ControlTaskQueue()), |
| 105 compositor_task_runner_( | 105 compositor_task_runner_( |
| 106 helper_.NewTaskQueue(TaskQueue::Spec(TaskQueue::QueueType::COMPOSITOR) | 106 helper_.NewTaskQueue(TaskQueue::Spec(TaskQueue::QueueType::COMPOSITOR) |
| 107 .SetShouldMonitorQuiescence(true))), | 107 .SetShouldMonitorQuiescence(true))), |
| 108 compositor_task_runner_enabled_voter_( | 108 compositor_task_runner_enabled_voter_( |
| 109 compositor_task_runner_->CreateQueueEnabledVoter()), | 109 compositor_task_runner_->CreateQueueEnabledVoter()), |
| 110 delayed_update_policy_runner_( | 110 delayed_update_policy_runner_( |
| 111 base::Bind(&RendererSchedulerImpl::UpdatePolicy, | 111 base::Bind(&RendererSchedulerImpl::UpdatePolicy, |
| 112 base::Unretained(this)), | 112 base::Unretained(this)), |
| 113 helper_.ControlTaskRunner()), | 113 helper_.ControlTaskQueue()), |
| 114 seqlock_queueing_time_estimator_( | 114 seqlock_queueing_time_estimator_( |
| 115 QueueingTimeEstimator(this, base::TimeDelta::FromSeconds(1))), | 115 QueueingTimeEstimator(this, base::TimeDelta::FromSeconds(1))), |
| 116 main_thread_only_(this, | 116 main_thread_only_(this, |
| 117 compositor_task_runner_, | 117 compositor_task_runner_, |
| 118 helper_.scheduler_tqm_delegate().get(), | 118 helper_.scheduler_tqm_delegate().get(), |
| 119 helper_.scheduler_tqm_delegate()->NowTicks()), | 119 helper_.scheduler_tqm_delegate()->NowTicks()), |
| 120 policy_may_need_update_(&any_thread_lock_), | 120 policy_may_need_update_(&any_thread_lock_), |
| 121 weak_factory_(this) { | 121 weak_factory_(this) { |
| 122 task_queue_throttler_.reset( | 122 task_queue_throttler_.reset( |
| 123 new TaskQueueThrottler(this, "renderer.scheduler")); | 123 new TaskQueueThrottler(this, "renderer.scheduler")); |
| 124 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, | 124 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, |
| 125 weak_factory_.GetWeakPtr()); | 125 weak_factory_.GetWeakPtr()); |
| 126 end_renderer_hidden_idle_period_closure_.Reset(base::Bind( | 126 end_renderer_hidden_idle_period_closure_.Reset(base::Bind( |
| 127 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); | 127 &RendererSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr())); |
| 128 | 128 |
| 129 suspend_timers_when_backgrounded_closure_.Reset( | 129 suspend_timers_when_backgrounded_closure_.Reset( |
| 130 base::Bind(&RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded, | 130 base::Bind(&RendererSchedulerImpl::SuspendTimerQueueWhenBackgrounded, |
| 131 weak_factory_.GetWeakPtr())); | 131 weak_factory_.GetWeakPtr())); |
| 132 | 132 |
| 133 default_loading_task_runner_ = | 133 default_loading_task_runner_ = |
| 134 NewLoadingTaskRunner(TaskQueue::QueueType::DEFAULT_LOADING); | 134 NewLoadingTaskQueue(TaskQueue::QueueType::DEFAULT_LOADING); |
| 135 default_timer_task_runner_ = | 135 default_timer_task_runner_ = |
| 136 NewTimerTaskRunner(TaskQueue::QueueType::DEFAULT_TIMER); | 136 NewTimerTaskQueue(TaskQueue::QueueType::DEFAULT_TIMER); |
| 137 | 137 |
| 138 TRACE_EVENT_OBJECT_CREATED_WITH_ID( | 138 TRACE_EVENT_OBJECT_CREATED_WITH_ID( |
| 139 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", | 139 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler", |
| 140 this); | 140 this); |
| 141 | 141 |
| 142 helper_.SetObserver(this); | 142 helper_.SetObserver(this); |
| 143 helper_.AddTaskTimeObserver(this); | 143 helper_.AddTaskTimeObserver(this); |
| 144 | 144 |
| 145 // Register a tracing state observer unless we're running in a test without a | 145 // Register a tracing state observer unless we're running in a test without a |
| 146 // task runner. Note that it's safe to remove a non-existent observer. | 146 // task runner. Note that it's safe to remove a non-existent observer. |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 helper_.Shutdown(); | 257 helper_.Shutdown(); |
| 258 idle_helper_.Shutdown(); | 258 idle_helper_.Shutdown(); |
| 259 GetMainThreadOnly().was_shutdown = true; | 259 GetMainThreadOnly().was_shutdown = true; |
| 260 GetMainThreadOnly().rail_mode_observer = nullptr; | 260 GetMainThreadOnly().rail_mode_observer = nullptr; |
| 261 } | 261 } |
| 262 | 262 |
| 263 std::unique_ptr<blink::WebThread> RendererSchedulerImpl::CreateMainThread() { | 263 std::unique_ptr<blink::WebThread> RendererSchedulerImpl::CreateMainThread() { |
| 264 return base::MakeUnique<WebThreadImplForRendererScheduler>(this); | 264 return base::MakeUnique<WebThreadImplForRendererScheduler>(this); |
| 265 } | 265 } |
| 266 | 266 |
| 267 scoped_refptr<TaskQueue> RendererSchedulerImpl::DefaultTaskRunner() { | 267 scoped_refptr<base::SingleThreadTaskRunner> |
| 268 return helper_.DefaultTaskRunner(); | 268 RendererSchedulerImpl::DefaultTaskRunner() { |
| 269 return helper_.DefaultTaskQueue(); |
| 269 } | 270 } |
| 270 | 271 |
| 271 scoped_refptr<TaskQueue> RendererSchedulerImpl::CompositorTaskRunner() { | 272 scoped_refptr<base::SingleThreadTaskRunner> |
| 273 RendererSchedulerImpl::CompositorTaskRunner() { |
| 272 helper_.CheckOnValidThread(); | 274 helper_.CheckOnValidThread(); |
| 273 return compositor_task_runner_; | 275 return compositor_task_runner_; |
| 274 } | 276 } |
| 275 | 277 |
| 276 scoped_refptr<SingleThreadIdleTaskRunner> | 278 scoped_refptr<SingleThreadIdleTaskRunner> |
| 277 RendererSchedulerImpl::IdleTaskRunner() { | 279 RendererSchedulerImpl::IdleTaskRunner() { |
| 278 return idle_helper_.IdleTaskRunner(); | 280 return idle_helper_.IdleTaskRunner(); |
| 279 } | 281 } |
| 280 | 282 |
| 281 scoped_refptr<TaskQueue> RendererSchedulerImpl::LoadingTaskRunner() { | 283 scoped_refptr<base::SingleThreadTaskRunner> |
| 284 RendererSchedulerImpl::LoadingTaskRunner() { |
| 282 helper_.CheckOnValidThread(); | 285 helper_.CheckOnValidThread(); |
| 283 return default_loading_task_runner_; | 286 return default_loading_task_runner_; |
| 284 } | 287 } |
| 285 | 288 |
| 286 scoped_refptr<TaskQueue> RendererSchedulerImpl::TimerTaskRunner() { | 289 scoped_refptr<base::SingleThreadTaskRunner> |
| 290 RendererSchedulerImpl::TimerTaskRunner() { |
| 287 helper_.CheckOnValidThread(); | 291 helper_.CheckOnValidThread(); |
| 288 return default_timer_task_runner_; | 292 return default_timer_task_runner_; |
| 289 } | 293 } |
| 290 | 294 |
| 291 scoped_refptr<TaskQueue> RendererSchedulerImpl::ControlTaskRunner() { | 295 scoped_refptr<TaskQueue> RendererSchedulerImpl::DefaultTaskQueue() { |
| 292 helper_.CheckOnValidThread(); | 296 return helper_.DefaultTaskQueue(); |
| 293 return helper_.ControlTaskRunner(); | |
| 294 } | 297 } |
| 295 | 298 |
| 296 scoped_refptr<TaskQueue> RendererSchedulerImpl::NewLoadingTaskRunner( | 299 scoped_refptr<TaskQueue> RendererSchedulerImpl::CompositorTaskQueue() { |
| 300 helper_.CheckOnValidThread(); |
| 301 return compositor_task_runner_; |
| 302 } |
| 303 |
| 304 scoped_refptr<TaskQueue> RendererSchedulerImpl::LoadingTaskQueue() { |
| 305 helper_.CheckOnValidThread(); |
| 306 return default_loading_task_runner_; |
| 307 } |
| 308 |
| 309 scoped_refptr<TaskQueue> RendererSchedulerImpl::TimerTaskQueue() { |
| 310 helper_.CheckOnValidThread(); |
| 311 return default_timer_task_runner_; |
| 312 } |
| 313 |
| 314 scoped_refptr<TaskQueue> RendererSchedulerImpl::ControlTaskQueue() { |
| 315 helper_.CheckOnValidThread(); |
| 316 return helper_.ControlTaskQueue(); |
| 317 } |
| 318 |
| 319 scoped_refptr<TaskQueue> RendererSchedulerImpl::NewLoadingTaskQueue( |
| 297 TaskQueue::QueueType queue_type) { | 320 TaskQueue::QueueType queue_type) { |
| 298 helper_.CheckOnValidThread(); | 321 helper_.CheckOnValidThread(); |
| 299 scoped_refptr<TaskQueue> loading_task_queue(helper_.NewTaskQueue( | 322 scoped_refptr<TaskQueue> loading_task_queue(helper_.NewTaskQueue( |
| 300 TaskQueue::Spec(queue_type) | 323 TaskQueue::Spec(queue_type) |
| 301 .SetShouldMonitorQuiescence(true) | 324 .SetShouldMonitorQuiescence(true) |
| 302 .SetTimeDomain(GetMainThreadOnly().use_virtual_time | 325 .SetTimeDomain(GetMainThreadOnly().use_virtual_time |
| 303 ? GetVirtualTimeDomain() | 326 ? GetVirtualTimeDomain() |
| 304 : nullptr))); | 327 : nullptr))); |
| 305 auto insert_result = loading_task_runners_.insert(std::make_pair( | 328 auto insert_result = loading_task_runners_.insert(std::make_pair( |
| 306 loading_task_queue, loading_task_queue->CreateQueueEnabledVoter())); | 329 loading_task_queue, loading_task_queue->CreateQueueEnabledVoter())); |
| 307 insert_result.first->second->SetQueueEnabled( | 330 insert_result.first->second->SetQueueEnabled( |
| 308 GetMainThreadOnly().current_policy.loading_queue_policy.is_enabled); | 331 GetMainThreadOnly().current_policy.loading_queue_policy.is_enabled); |
| 309 loading_task_queue->SetQueuePriority( | 332 loading_task_queue->SetQueuePriority( |
| 310 GetMainThreadOnly().current_policy.loading_queue_policy.priority); | 333 GetMainThreadOnly().current_policy.loading_queue_policy.priority); |
| 311 if (GetMainThreadOnly() | 334 if (GetMainThreadOnly() |
| 312 .current_policy.loading_queue_policy.time_domain_type == | 335 .current_policy.loading_queue_policy.time_domain_type == |
| 313 TimeDomainType::THROTTLED) { | 336 TimeDomainType::THROTTLED) { |
| 314 task_queue_throttler_->IncreaseThrottleRefCount(loading_task_queue.get()); | 337 task_queue_throttler_->IncreaseThrottleRefCount(loading_task_queue.get()); |
| 315 } | 338 } |
| 316 loading_task_queue->AddTaskObserver( | 339 loading_task_queue->AddTaskObserver( |
| 317 &GetMainThreadOnly().loading_task_cost_estimator); | 340 &GetMainThreadOnly().loading_task_cost_estimator); |
| 318 return loading_task_queue; | 341 return loading_task_queue; |
| 319 } | 342 } |
| 320 | 343 |
| 321 scoped_refptr<TaskQueue> RendererSchedulerImpl::NewTimerTaskRunner( | 344 scoped_refptr<TaskQueue> RendererSchedulerImpl::NewTimerTaskQueue( |
| 322 TaskQueue::QueueType queue_type) { | 345 TaskQueue::QueueType queue_type) { |
| 323 helper_.CheckOnValidThread(); | 346 helper_.CheckOnValidThread(); |
| 324 // TODO(alexclarke): Consider using ApplyTaskQueuePolicy() for brevity. | 347 // TODO(alexclarke): Consider using ApplyTaskQueuePolicy() for brevity. |
| 325 scoped_refptr<TaskQueue> timer_task_queue(helper_.NewTaskQueue( | 348 scoped_refptr<TaskQueue> timer_task_queue(helper_.NewTaskQueue( |
| 326 TaskQueue::Spec(queue_type) | 349 TaskQueue::Spec(queue_type) |
| 327 .SetShouldMonitorQuiescence(true) | 350 .SetShouldMonitorQuiescence(true) |
| 328 .SetShouldReportWhenExecutionBlocked(true) | 351 .SetShouldReportWhenExecutionBlocked(true) |
| 329 .SetTimeDomain(GetMainThreadOnly().use_virtual_time | 352 .SetTimeDomain(GetMainThreadOnly().use_virtual_time |
| 330 ? GetVirtualTimeDomain() | 353 ? GetVirtualTimeDomain() |
| 331 : nullptr))); | 354 : nullptr))); |
| 332 auto insert_result = timer_task_runners_.insert(std::make_pair( | 355 auto insert_result = timer_task_runners_.insert(std::make_pair( |
| 333 timer_task_queue, timer_task_queue->CreateQueueEnabledVoter())); | 356 timer_task_queue, timer_task_queue->CreateQueueEnabledVoter())); |
| 334 insert_result.first->second->SetQueueEnabled( | 357 insert_result.first->second->SetQueueEnabled( |
| 335 GetMainThreadOnly().current_policy.timer_queue_policy.is_enabled); | 358 GetMainThreadOnly().current_policy.timer_queue_policy.is_enabled); |
| 336 timer_task_queue->SetQueuePriority( | 359 timer_task_queue->SetQueuePriority( |
| 337 GetMainThreadOnly().current_policy.timer_queue_policy.priority); | 360 GetMainThreadOnly().current_policy.timer_queue_policy.priority); |
| 338 if (GetMainThreadOnly().current_policy.timer_queue_policy.time_domain_type == | 361 if (GetMainThreadOnly().current_policy.timer_queue_policy.time_domain_type == |
| 339 TimeDomainType::THROTTLED) { | 362 TimeDomainType::THROTTLED) { |
| 340 task_queue_throttler_->IncreaseThrottleRefCount(timer_task_queue.get()); | 363 task_queue_throttler_->IncreaseThrottleRefCount(timer_task_queue.get()); |
| 341 } | 364 } |
| 342 timer_task_queue->AddTaskObserver( | 365 timer_task_queue->AddTaskObserver( |
| 343 &GetMainThreadOnly().timer_task_cost_estimator); | 366 &GetMainThreadOnly().timer_task_cost_estimator); |
| 344 return timer_task_queue; | 367 return timer_task_queue; |
| 345 } | 368 } |
| 346 | 369 |
| 347 scoped_refptr<TaskQueue> RendererSchedulerImpl::NewUnthrottledTaskRunner( | 370 scoped_refptr<TaskQueue> RendererSchedulerImpl::NewUnthrottledTaskQueue( |
| 348 TaskQueue::QueueType queue_type) { | 371 TaskQueue::QueueType queue_type) { |
| 349 helper_.CheckOnValidThread(); | 372 helper_.CheckOnValidThread(); |
| 350 scoped_refptr<TaskQueue> unthrottled_task_queue(helper_.NewTaskQueue( | 373 scoped_refptr<TaskQueue> unthrottled_task_queue(helper_.NewTaskQueue( |
| 351 TaskQueue::Spec(queue_type) | 374 TaskQueue::Spec(queue_type) |
| 352 .SetShouldMonitorQuiescence(true) | 375 .SetShouldMonitorQuiescence(true) |
| 353 .SetTimeDomain(GetMainThreadOnly().use_virtual_time | 376 .SetTimeDomain(GetMainThreadOnly().use_virtual_time |
| 354 ? GetVirtualTimeDomain() | 377 ? GetVirtualTimeDomain() |
| 355 : nullptr))); | 378 : nullptr))); |
| 356 unthrottled_task_runners_.insert(unthrottled_task_queue); | 379 unthrottled_task_runners_.insert(unthrottled_task_queue); |
| 357 return unthrottled_task_queue; | 380 return unthrottled_task_queue; |
| (...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 ApplyTaskQueuePolicy(pair.first.get(), pair.second.get(), | 1181 ApplyTaskQueuePolicy(pair.first.get(), pair.second.get(), |
| 1159 GetMainThreadOnly().current_policy.timer_queue_policy, | 1182 GetMainThreadOnly().current_policy.timer_queue_policy, |
| 1160 new_policy.timer_queue_policy); | 1183 new_policy.timer_queue_policy); |
| 1161 } | 1184 } |
| 1162 GetMainThreadOnly().have_reported_blocking_intervention_in_current_policy = | 1185 GetMainThreadOnly().have_reported_blocking_intervention_in_current_policy = |
| 1163 false; | 1186 false; |
| 1164 | 1187 |
| 1165 // TODO(alexclarke): We shouldn't have to prioritize the default queue, but it | 1188 // TODO(alexclarke): We shouldn't have to prioritize the default queue, but it |
| 1166 // appears to be necessary since the order of loading tasks and IPCs (which | 1189 // appears to be necessary since the order of loading tasks and IPCs (which |
| 1167 // are mostly dispatched on the default queue) need to be preserved. | 1190 // are mostly dispatched on the default queue) need to be preserved. |
| 1168 ApplyTaskQueuePolicy(helper_.DefaultTaskRunner().get(), nullptr, | 1191 ApplyTaskQueuePolicy(helper_.DefaultTaskQueue().get(), nullptr, |
| 1169 GetMainThreadOnly().current_policy.default_queue_policy, | 1192 GetMainThreadOnly().current_policy.default_queue_policy, |
| 1170 new_policy.default_queue_policy); | 1193 new_policy.default_queue_policy); |
| 1171 if (GetMainThreadOnly().rail_mode_observer && | 1194 if (GetMainThreadOnly().rail_mode_observer && |
| 1172 new_policy.rail_mode != GetMainThreadOnly().current_policy.rail_mode) { | 1195 new_policy.rail_mode != GetMainThreadOnly().current_policy.rail_mode) { |
| 1173 GetMainThreadOnly().rail_mode_observer->OnRAILModeChanged( | 1196 GetMainThreadOnly().rail_mode_observer->OnRAILModeChanged( |
| 1174 new_policy.rail_mode); | 1197 new_policy.rail_mode); |
| 1175 } | 1198 } |
| 1176 | 1199 |
| 1177 if (new_policy.should_disable_throttling != | 1200 if (new_policy.should_disable_throttling != |
| 1178 GetMainThreadOnly().current_policy.should_disable_throttling) { | 1201 GetMainThreadOnly().current_policy.should_disable_throttling) { |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1628 | 1651 |
| 1629 void RendererSchedulerImpl::SetTopLevelBlameContext( | 1652 void RendererSchedulerImpl::SetTopLevelBlameContext( |
| 1630 base::trace_event::BlameContext* blame_context) { | 1653 base::trace_event::BlameContext* blame_context) { |
| 1631 // Any task that runs in the default task runners belongs to the context of | 1654 // Any task that runs in the default task runners belongs to the context of |
| 1632 // all frames (as opposed to a particular frame). Note that the task itself | 1655 // all frames (as opposed to a particular frame). Note that the task itself |
| 1633 // may still enter a more specific blame context if necessary. | 1656 // may still enter a more specific blame context if necessary. |
| 1634 // | 1657 // |
| 1635 // Per-frame task runners (loading, timers, etc.) are configured with a more | 1658 // Per-frame task runners (loading, timers, etc.) are configured with a more |
| 1636 // specific blame context by WebFrameSchedulerImpl. | 1659 // specific blame context by WebFrameSchedulerImpl. |
| 1637 control_task_runner_->SetBlameContext(blame_context); | 1660 control_task_runner_->SetBlameContext(blame_context); |
| 1638 DefaultTaskRunner()->SetBlameContext(blame_context); | 1661 DefaultTaskQueue()->SetBlameContext(blame_context); |
| 1639 default_loading_task_runner_->SetBlameContext(blame_context); | 1662 default_loading_task_runner_->SetBlameContext(blame_context); |
| 1640 default_timer_task_runner_->SetBlameContext(blame_context); | 1663 default_timer_task_runner_->SetBlameContext(blame_context); |
| 1641 compositor_task_runner_->SetBlameContext(blame_context); | 1664 compositor_task_runner_->SetBlameContext(blame_context); |
| 1642 idle_helper_.IdleTaskRunner()->SetBlameContext(blame_context); | 1665 idle_helper_.IdleTaskRunner()->SetBlameContext(blame_context); |
| 1643 } | 1666 } |
| 1644 | 1667 |
| 1645 void RendererSchedulerImpl::SetRAILModeObserver(RAILModeObserver* observer) { | 1668 void RendererSchedulerImpl::SetRAILModeObserver(RAILModeObserver* observer) { |
| 1646 GetMainThreadOnly().rail_mode_observer = observer; | 1669 GetMainThreadOnly().rail_mode_observer = observer; |
| 1647 } | 1670 } |
| 1648 | 1671 |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1930 case TimeDomainType::VIRTUAL: | 1953 case TimeDomainType::VIRTUAL: |
| 1931 return "virtual"; | 1954 return "virtual"; |
| 1932 default: | 1955 default: |
| 1933 NOTREACHED(); | 1956 NOTREACHED(); |
| 1934 return nullptr; | 1957 return nullptr; |
| 1935 } | 1958 } |
| 1936 } | 1959 } |
| 1937 | 1960 |
| 1938 } // namespace scheduler | 1961 } // namespace scheduler |
| 1939 } // namespace blink | 1962 } // namespace blink |
| OLD | NEW |