Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(435)

Unified Diff: components/scheduler/renderer/renderer_scheduler_impl.cc

Issue 1177753003: Refactor RendererSchedulerImpl to improve thread safety. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Moved compositor_thread_checker_ into CompositorThreadOnly Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/scheduler/renderer/renderer_scheduler_impl.cc
diff --git a/components/scheduler/renderer/renderer_scheduler_impl.cc b/components/scheduler/renderer/renderer_scheduler_impl.cc
index 0e0c705df594bf93c799c81b54aae1f386152e14..1d49c3f5c2a035d39e4961a5cefa230ff6f9e5f6 100644
--- a/components/scheduler/renderer/renderer_scheduler_impl.cc
+++ b/components/scheduler/renderer/renderer_scheduler_impl.cc
@@ -36,16 +36,7 @@ RendererSchedulerImpl::RendererSchedulerImpl(
base::Bind(&RendererSchedulerImpl::UpdatePolicy,
base::Unretained(this)),
helper_.ControlTaskRunner()),
- current_policy_(Policy::NORMAL),
- renderer_hidden_(false),
- was_shutdown_(false),
- pending_main_thread_input_event_count_(0),
- awaiting_touch_start_response_(false),
- begin_main_frame_on_critical_path_(false),
- last_input_type_(blink::WebInputEvent::Undefined),
- policy_may_need_update_(&incoming_signals_lock_),
- timer_queue_suspend_count_(0),
- in_idle_period_(false),
+ policy_may_need_update_(&any_thread_lock_),
weak_factory_(this) {
update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy,
weak_factory_.GetWeakPtr());
@@ -68,12 +59,33 @@ RendererSchedulerImpl::~RendererSchedulerImpl() {
// Ensure the renderer scheduler was shut down explicitly, because otherwise
// we could end up having stale pointers to the Blink heap which has been
// terminated by this point.
- DCHECK(was_shutdown_);
+ DCHECK(MainThreadOnly().was_shutdown_);
+}
+
+RendererSchedulerImpl::MainThreadOnly::MainThreadOnly()
+ : current_policy_(Policy::NORMAL),
+ timer_queue_suspend_count_(0),
+ renderer_hidden_(false),
+ was_shutdown_(false),
+ in_idle_period_(false),
+ begin_main_frame_on_critical_path_(false) {
+}
+
+RendererSchedulerImpl::AnyThread::AnyThread()
+ : pending_main_thread_input_event_count_(0),
+ awaiting_touch_start_response_(false) {
+}
+
+RendererSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly()
+ : last_input_type_(blink::WebInputEvent::Undefined) {
+}
+
+RendererSchedulerImpl::CompositorThreadOnly::~CompositorThreadOnly() {
}
void RendererSchedulerImpl::Shutdown() {
helper_.Shutdown();
- was_shutdown_ = true;
+ MainThreadOnly().was_shutdown_ = true;
}
scoped_refptr<base::SingleThreadTaskRunner>
@@ -126,8 +138,9 @@ void RendererSchedulerImpl::WillBeginFrame(const cc::BeginFrameArgs& args) {
return;
EndIdlePeriod();
- estimated_next_frame_begin_ = args.frame_time + args.interval;
- begin_main_frame_on_critical_path_ = args.on_critical_path;
+ MainThreadOnly().estimated_next_frame_begin_ =
+ args.frame_time + args.interval;
+ MainThreadOnly().begin_main_frame_on_critical_path_ = args.on_critical_path;
}
void RendererSchedulerImpl::DidCommitFrameToCompositor() {
@@ -138,12 +151,12 @@ void RendererSchedulerImpl::DidCommitFrameToCompositor() {
return;
base::TimeTicks now(helper_.Now());
- if (now < estimated_next_frame_begin_) {
+ if (now < MainThreadOnly().estimated_next_frame_begin_) {
// TODO(rmcilroy): Consider reducing the idle period based on the runtime of
// the next pending delayed tasks (as currently done in for long idle times)
idle_helper_.StartIdlePeriod(
IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, now,
- estimated_next_frame_begin_);
+ MainThreadOnly().estimated_next_frame_begin_);
}
}
@@ -161,7 +174,7 @@ void RendererSchedulerImpl::OnRendererHidden() {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
"RendererSchedulerImpl::OnRendererHidden");
helper_.CheckOnValidThread();
- if (helper_.IsShutdown() || renderer_hidden_)
+ if (helper_.IsShutdown() || MainThreadOnly().renderer_hidden_)
return;
idle_helper_.EnableLongIdlePeriod();
@@ -173,7 +186,7 @@ void RendererSchedulerImpl::OnRendererHidden() {
control_task_runner_->PostDelayedTask(
FROM_HERE, end_renderer_hidden_idle_period_closure_.callback(),
end_idle_when_hidden_delay);
- renderer_hidden_ = true;
+ MainThreadOnly().renderer_hidden_ = true;
TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler",
@@ -184,11 +197,11 @@ void RendererSchedulerImpl::OnRendererVisible() {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
"RendererSchedulerImpl::OnRendererVisible");
helper_.CheckOnValidThread();
- if (helper_.IsShutdown() || !renderer_hidden_)
+ if (helper_.IsShutdown() || !MainThreadOnly().renderer_hidden_)
return;
end_renderer_hidden_idle_period_closure_.Cancel();
- renderer_hidden_ = false;
+ MainThreadOnly().renderer_hidden_ = false;
EndIdlePeriod();
TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
@@ -246,15 +259,16 @@ void RendererSchedulerImpl::DidAnimateForInputOnCompositorThread() {
void RendererSchedulerImpl::UpdateForInputEventOnCompositorThread(
blink::WebInputEvent::Type type,
InputEventState input_event_state) {
- base::AutoLock lock(incoming_signals_lock_);
+ base::AutoLock lock(any_thread_lock_);
base::TimeTicks now = helper_.Now();
bool was_in_compositor_priority = InputSignalsSuggestCompositorPriority(now);
- bool was_awaiting_touch_start_response_ = awaiting_touch_start_response_;
+ bool was_awaiting_touch_start_response =
+ AnyThread().awaiting_touch_start_response_;
if (type) {
switch (type) {
case blink::WebInputEvent::TouchStart:
- awaiting_touch_start_response_ = true;
+ AnyThread().awaiting_touch_start_response_ = true;
break;
case blink::WebInputEvent::TouchMove:
@@ -263,9 +277,10 @@ void RendererSchedulerImpl::UpdateForInputEventOnCompositorThread(
// response prioritization is no longer necessary. Otherwise, the
// initial touchmove should preserve the touchstart response pending
// state.
- if (awaiting_touch_start_response_ &&
- last_input_type_ == blink::WebInputEvent::TouchMove) {
- awaiting_touch_start_response_ = false;
+ if (AnyThread().awaiting_touch_start_response_ &&
+ CompositorThreadOnly().last_input_type_ ==
+ blink::WebInputEvent::TouchMove) {
+ AnyThread().awaiting_touch_start_response_ = false;
}
break;
@@ -278,21 +293,22 @@ void RendererSchedulerImpl::UpdateForInputEventOnCompositorThread(
break;
default:
- awaiting_touch_start_response_ = false;
+ AnyThread().awaiting_touch_start_response_ = false;
break;
}
}
// Avoid unnecessary policy updates, while in compositor priority.
if (!was_in_compositor_priority ||
- was_awaiting_touch_start_response_ != awaiting_touch_start_response_) {
+ was_awaiting_touch_start_response !=
+ AnyThread().awaiting_touch_start_response_) {
EnsureUrgentPolicyUpdatePostedOnMainThread(FROM_HERE);
}
- last_input_signal_time_ = now;
- last_input_type_ = type;
+ AnyThread().last_input_signal_time_ = now;
+ CompositorThreadOnly().last_input_type_ = type;
if (input_event_state == InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD)
- pending_main_thread_input_event_count_++;
+ AnyThread().pending_main_thread_input_event_count_++;
}
void RendererSchedulerImpl::DidHandleInputEventOnMainThread(
@@ -301,10 +317,10 @@ void RendererSchedulerImpl::DidHandleInputEventOnMainThread(
"RendererSchedulerImpl::DidHandleInputEventOnMainThread");
helper_.CheckOnValidThread();
if (ShouldPrioritizeInputEvent(web_input_event)) {
- base::AutoLock lock(incoming_signals_lock_);
- last_input_signal_time_ = helper_.Now();
- if (pending_main_thread_input_event_count_ > 0)
- pending_main_thread_input_event_count_--;
+ base::AutoLock lock(any_thread_lock_);
+ AnyThread().last_input_signal_time_ = helper_.Now();
+ if (AnyThread().pending_main_thread_input_event_count_ > 0)
+ AnyThread().pending_main_thread_input_event_count_--;
}
}
@@ -316,8 +332,8 @@ bool RendererSchedulerImpl::IsHighPriorityWorkAnticipated() {
MaybeUpdatePolicy();
// The touchstart and compositor policies indicate a strong likelihood of
// high-priority work in the near future.
- return SchedulerPolicy() == Policy::COMPOSITOR_PRIORITY ||
- SchedulerPolicy() == Policy::TOUCHSTART_PRIORITY;
+ return MainThreadOnly().current_policy_ == Policy::COMPOSITOR_PRIORITY ||
+ MainThreadOnly().current_policy_ == Policy::TOUCHSTART_PRIORITY;
}
bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() {
@@ -331,7 +347,7 @@ bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() {
// Note: even though the control queue is higher priority we don't yield for
// it since these tasks are not user-provided work and they are only intended
// to run before the next task, not interrupt the tasks.
- switch (SchedulerPolicy()) {
+ switch (MainThreadOnly().current_policy_) {
case Policy::NORMAL:
return false;
@@ -352,11 +368,6 @@ base::TimeTicks RendererSchedulerImpl::CurrentIdleTaskDeadlineForTesting()
return idle_helper_.CurrentIdleTaskDeadline();
}
-RendererSchedulerImpl::Policy RendererSchedulerImpl::SchedulerPolicy() const {
- helper_.CheckOnValidThread();
- return current_policy_;
-}
-
void RendererSchedulerImpl::MaybeUpdatePolicy() {
helper_.CheckOnValidThread();
if (policy_may_need_update_.IsSet()) {
@@ -368,7 +379,7 @@ void RendererSchedulerImpl::EnsureUrgentPolicyUpdatePostedOnMainThread(
const tracked_objects::Location& from_here) {
// TODO(scheduler-dev): Check that this method isn't called from the main
// thread.
- incoming_signals_lock_.AssertAcquired();
+ any_thread_lock_.AssertAcquired();
if (!policy_may_need_update_.IsSet()) {
policy_may_need_update_.SetWhileLocked(true);
control_task_runner_->PostTask(from_here, update_policy_closure_);
@@ -376,18 +387,18 @@ void RendererSchedulerImpl::EnsureUrgentPolicyUpdatePostedOnMainThread(
}
void RendererSchedulerImpl::UpdatePolicy() {
- base::AutoLock lock(incoming_signals_lock_);
+ base::AutoLock lock(any_thread_lock_);
UpdatePolicyLocked(UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED);
}
void RendererSchedulerImpl::ForceUpdatePolicy() {
- base::AutoLock lock(incoming_signals_lock_);
+ base::AutoLock lock(any_thread_lock_);
UpdatePolicyLocked(UpdateType::FORCE_UPDATE);
}
void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
helper_.CheckOnValidThread();
- incoming_signals_lock_.AssertAcquired();
+ any_thread_lock_.AssertAcquired();
if (helper_.IsShutdown())
return;
@@ -397,15 +408,16 @@ void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
base::TimeDelta new_policy_duration;
Policy new_policy = ComputeNewPolicy(now, &new_policy_duration);
if (new_policy_duration > base::TimeDelta()) {
- current_policy_expiration_time_ = now + new_policy_duration;
+ MainThreadOnly().current_policy_expiration_time_ =
+ now + new_policy_duration;
delayed_update_policy_runner_.SetDeadline(FROM_HERE, new_policy_duration,
now);
} else {
- current_policy_expiration_time_ = base::TimeTicks();
+ MainThreadOnly().current_policy_expiration_time_ = base::TimeTicks();
}
if (update_type == UpdateType::MAY_EARLY_OUT_IF_POLICY_UNCHANGED &&
- new_policy == current_policy_)
+ new_policy == MainThreadOnly().current_policy_)
return;
bool policy_disables_timers = false;
@@ -435,7 +447,8 @@ void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
default:
NOTREACHED();
}
- if (timer_queue_suspend_count_ != 0 || policy_disables_timers) {
+ if (MainThreadOnly().timer_queue_suspend_count_ != 0 ||
+ policy_disables_timers) {
helper_.DisableQueue(TIMER_TASK_QUEUE);
} else {
helper_.SetQueuePriority(TIMER_TASK_QUEUE,
@@ -445,13 +458,13 @@ void RendererSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
if (new_policy != Policy::TOUCHSTART_PRIORITY)
DCHECK(helper_.IsQueueEnabled(LOADING_TASK_QUEUE));
- current_policy_ = new_policy;
+ MainThreadOnly().current_policy_ = new_policy;
TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "RendererScheduler",
this, AsValueLocked(now));
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
- "RendererScheduler.policy", current_policy_);
+ "RendererScheduler.policy", MainThreadOnly().current_policy_);
}
bool RendererSchedulerImpl::InputSignalsSuggestCompositorPriority(
@@ -471,32 +484,34 @@ bool RendererSchedulerImpl::InputSignalsSuggestCompositorPriority(
RendererSchedulerImpl::Policy RendererSchedulerImpl::ComputeNewPolicy(
base::TimeTicks now,
base::TimeDelta* new_policy_duration) const {
- incoming_signals_lock_.AssertAcquired();
+ any_thread_lock_.AssertAcquired();
*new_policy_duration = TimeLeftInInputEscalatedPolicy(now);
if (*new_policy_duration == base::TimeDelta())
return Policy::NORMAL;
- return awaiting_touch_start_response_ ? Policy::TOUCHSTART_PRIORITY
- : Policy::COMPOSITOR_PRIORITY;
+ return AnyThread().awaiting_touch_start_response_
+ ? Policy::TOUCHSTART_PRIORITY
+ : Policy::COMPOSITOR_PRIORITY;
}
base::TimeDelta RendererSchedulerImpl::TimeLeftInInputEscalatedPolicy(
base::TimeTicks now) const {
- incoming_signals_lock_.AssertAcquired();
+ any_thread_lock_.AssertAcquired();
base::TimeDelta escalated_priority_duration =
base::TimeDelta::FromMilliseconds(kPriorityEscalationAfterInputMillis);
// If the input event is still pending, go into input prioritized policy
// and check again later.
- if (pending_main_thread_input_event_count_ > 0)
+ if (AnyThread().pending_main_thread_input_event_count_ > 0)
return escalated_priority_duration;
- if (last_input_signal_time_.is_null() ||
- last_input_signal_time_ + escalated_priority_duration < now) {
+ if (AnyThread().last_input_signal_time_.is_null() ||
+ AnyThread().last_input_signal_time_ + escalated_priority_duration < now) {
return base::TimeDelta();
}
- return last_input_signal_time_ + escalated_priority_duration - now;
+ return AnyThread().last_input_signal_time_ + escalated_priority_duration -
+ now;
}
bool RendererSchedulerImpl::CanEnterLongIdlePeriod(
@@ -505,10 +520,11 @@ bool RendererSchedulerImpl::CanEnterLongIdlePeriod(
helper_.CheckOnValidThread();
MaybeUpdatePolicy();
- if (SchedulerPolicy() == Policy::TOUCHSTART_PRIORITY) {
+ if (MainThreadOnly().current_policy_ == Policy::TOUCHSTART_PRIORITY) {
// Don't start a long idle task in touch start priority, try again when
// the policy is scheduled to end.
- *next_long_idle_period_delay_out = current_policy_expiration_time_ - now;
+ *next_long_idle_period_delay_out =
+ MainThreadOnly().current_policy_expiration_time_ - now;
return false;
}
return true;
@@ -519,16 +535,14 @@ SchedulerHelper* RendererSchedulerImpl::GetSchedulerHelperForTesting() {
}
void RendererSchedulerImpl::SuspendTimerQueue() {
- helper_.CheckOnValidThread();
- timer_queue_suspend_count_++;
+ MainThreadOnly().timer_queue_suspend_count_++;
ForceUpdatePolicy();
DCHECK(!helper_.IsQueueEnabled(TIMER_TASK_QUEUE));
}
void RendererSchedulerImpl::ResumeTimerQueue() {
- helper_.CheckOnValidThread();
- timer_queue_suspend_count_--;
- DCHECK_GE(timer_queue_suspend_count_, 0);
+ MainThreadOnly().timer_queue_suspend_count_--;
+ DCHECK_GE(MainThreadOnly().timer_queue_suspend_count_, 0);
ForceUpdatePolicy();
}
@@ -566,50 +580,51 @@ const char* RendererSchedulerImpl::PolicyToString(Policy policy) {
scoped_refptr<base::trace_event::ConvertableToTraceFormat>
RendererSchedulerImpl::AsValue(base::TimeTicks optional_now) const {
- base::AutoLock lock(incoming_signals_lock_);
+ base::AutoLock lock(any_thread_lock_);
return AsValueLocked(optional_now);
}
scoped_refptr<base::trace_event::ConvertableToTraceFormat>
RendererSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const {
helper_.CheckOnValidThread();
- incoming_signals_lock_.AssertAcquired();
+ any_thread_lock_.AssertAcquired();
if (optional_now.is_null())
optional_now = helper_.Now();
scoped_refptr<base::trace_event::TracedValue> state =
new base::trace_event::TracedValue();
- state->SetString("current_policy", PolicyToString(current_policy_));
+ state->SetString("current_policy",
+ PolicyToString(MainThreadOnly().current_policy_));
state->SetString("idle_period_state",
IdleHelper::IdlePeriodStateToString(
idle_helper_.SchedulerIdlePeriodState()));
- state->SetBoolean("renderer_hidden", renderer_hidden_);
+ state->SetBoolean("renderer_hidden", MainThreadOnly().renderer_hidden_);
state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF());
- state->SetDouble(
- "last_input_signal_time",
- (last_input_signal_time_ - base::TimeTicks()).InMillisecondsF());
+ state->SetDouble("last_input_signal_time",
+ (AnyThread().last_input_signal_time_ - base::TimeTicks())
+ .InMillisecondsF());
state->SetInteger("pending_main_thread_input_event_count",
- pending_main_thread_input_event_count_);
+ AnyThread().pending_main_thread_input_event_count_);
state->SetBoolean("awaiting_touch_start_response",
- awaiting_touch_start_response_);
+ AnyThread().awaiting_touch_start_response_);
state->SetBoolean("begin_main_frame_on_critical_path",
- begin_main_frame_on_critical_path_);
- state->SetDouble(
- "estimated_next_frame_begin",
- (estimated_next_frame_begin_ - base::TimeTicks()).InMillisecondsF());
- state->SetBoolean("in_idle_period", in_idle_period_);
+ MainThreadOnly().begin_main_frame_on_critical_path_);
+ state->SetDouble("estimated_next_frame_begin",
+ (MainThreadOnly().estimated_next_frame_begin_ -
+ base::TimeTicks()).InMillisecondsF());
+ state->SetBoolean("in_idle_period", MainThreadOnly().in_idle_period_);
return state;
}
void RendererSchedulerImpl::OnIdlePeriodStarted() {
- in_idle_period_ = true;
+ MainThreadOnly().in_idle_period_ = true;
// TODO(alexclarke): Force update the policy
}
void RendererSchedulerImpl::OnIdlePeriodEnded() {
- in_idle_period_ = false;
+ MainThreadOnly().in_idle_period_ = false;
// TODO(alexclarke): Force update the policy
}

Powered by Google App Engine
This is Rietveld 408576698