Commit bb4ba82e authored by Nate Chapin's avatar Nate Chapin Committed by Commit Bot

Support WorkerSchedulers for nested workers

Currently, FrameSchedulerImpl keeps a set of throttling observers that
it notifies when throttling state changes. This includes each worker's
WorkerSchedulerProxy.

This CL moves throttling observers to the base class,
FrameOrWorkerScheduler, allowing each nested worker to register its
WorkerSchedulerProxy with its parent WorkerScheduler, so the
WorkerScheduler can then propagate throttling state to the nested
worker.

Bug: 829119
Change-Id: If005e3ec781b2fc0ecd3ba1ba73fa4b0e6ef1a0f
Reviewed-on: https://chromium-review.googlesource.com/994060Reviewed-by: default avatarPavel Feldman <pfeldman@chromium.org>
Reviewed-by: default avatarHiroki Nakagawa <nhiroki@chromium.org>
Reviewed-by: default avatarAlexander Timin <altimin@chromium.org>
Commit-Queue: Nate Chapin <japhet@chromium.org>
Cr-Commit-Position: refs/heads/master@{#562052}
parent 0dd64bcc
......@@ -42,7 +42,7 @@ class TaskTimeObserver;
namespace blink {
class FrameScheduler;
class FrameOrWorkerScheduler;
class ThreadScheduler;
// Always an integer value.
......@@ -53,13 +53,13 @@ struct BLINK_PLATFORM_EXPORT WebThreadCreationParams {
WebThreadCreationParams& SetThreadNameForTest(const char* name);
// Sets a scheduler for the frame which was responsible for the creation
// Sets a scheduler for the context which was responsible for the creation
// of this thread.
WebThreadCreationParams& SetFrameScheduler(FrameScheduler*);
WebThreadCreationParams& SetFrameOrWorkerScheduler(FrameOrWorkerScheduler*);
WebThreadType thread_type;
const char* name;
FrameScheduler* frame_scheduler; // NOT OWNED
FrameOrWorkerScheduler* frame_or_worker_scheduler; // NOT OWNED
base::Thread::Options thread_options;
};
......
......@@ -151,11 +151,6 @@ class EmptyFrameScheduler final : public FrameScheduler {
return Platform::Current()->MainThread()->GetTaskRunner();
}
std::unique_ptr<ThrottlingObserverHandle> AddThrottlingObserver(
ObserverType,
Observer*) override {
return nullptr;
}
void SetFrameVisible(bool) override {}
bool IsFrameVisible() const override { return false; }
bool IsPageVisible() const override { return false; }
......
......@@ -41,20 +41,18 @@
#include "third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
#include "third_party/blink/renderer/core/workers/worker_backing_thread.h"
#include "third_party/blink/renderer/platform/web_thread_supporting_gc.h"
namespace blink {
namespace {
FrameScheduler* GetFrameScheduler(ThreadableLoadingContext* loading_context) {
FrameOrWorkerScheduler* GetFrameOrWorkerScheduler(
ThreadableLoadingContext* loading_context) {
// |loading_context| can be null in unittests.
if (!loading_context)
return nullptr;
if (!loading_context->GetExecutionContext()->IsDocument())
return nullptr;
return ToDocument(loading_context->GetExecutionContext())
->GetFrame()
->GetFrameScheduler();
return loading_context->GetExecutionContext()->GetScheduler();
}
} // namespace
......@@ -72,7 +70,8 @@ DedicatedWorkerThread::DedicatedWorkerThread(
: WorkerThread(loading_context, worker_object_proxy),
worker_backing_thread_(WorkerBackingThread::Create(
WebThreadCreationParams(GetThreadType())
.SetFrameScheduler(GetFrameScheduler(loading_context)))),
.SetFrameOrWorkerScheduler(
GetFrameOrWorkerScheduler(loading_context)))),
worker_object_proxy_(worker_object_proxy) {}
DedicatedWorkerThread::~DedicatedWorkerThread() = default;
......
......@@ -53,7 +53,7 @@
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
#include "third_party/blink/renderer/platform/waitable_event.h"
#include "third_party/blink/renderer/platform/web_thread_supporting_gc.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
......@@ -418,7 +418,9 @@ void WorkerThread::InitializeSchedulerOnWorkerThread(
static_cast<scheduler::WebThreadImplForWorkerScheduler&>(
GetWorkerBackingThread().BackingThread().PlatformThread());
worker_scheduler_ = std::make_unique<scheduler::WorkerScheduler>(
web_thread_for_worker.GetNonMainThreadScheduler());
static_cast<scheduler::WorkerThreadScheduler*>(
web_thread_for_worker.GetNonMainThreadScheduler()),
web_thread_for_worker.worker_scheduler_proxy());
waitable_event->Signal();
}
......
......@@ -68,6 +68,7 @@ blink_platform_sources("scheduler") {
"child/worker_scheduler_proxy.h",
"child/worker_task_queue.cc",
"child/worker_task_queue.h",
"common/frame_or_worker_scheduler.cc",
"common/scheduler_helper.cc",
"common/scheduler_helper.h",
"common/thread_scheduler.cc",
......
......@@ -23,10 +23,10 @@ WebThreadImplForWorkerScheduler::WebThreadImplForWorkerScheduler(
const WebThreadCreationParams& params)
: thread_(new base::Thread(params.name ? params.name : std::string())),
thread_type_(params.thread_type),
worker_scheduler_proxy_(
params.frame_scheduler
? std::make_unique<WorkerSchedulerProxy>(params.frame_scheduler)
: nullptr) {
worker_scheduler_proxy_(params.frame_or_worker_scheduler
? std::make_unique<WorkerSchedulerProxy>(
params.frame_or_worker_scheduler)
: nullptr) {
bool started = thread_->StartWithOptions(params.thread_options);
CHECK(started);
thread_task_runner_ = thread_->task_runner();
......
......@@ -55,15 +55,18 @@ class PLATFORM_EXPORT WebThreadImplForWorkerScheduler
return non_main_thread_scheduler_.get();
}
scheduler::WorkerSchedulerProxy* worker_scheduler_proxy() const {
return worker_scheduler_proxy_.get();
}
protected:
virtual std::unique_ptr<NonMainThreadScheduler>
CreateNonMainThreadScheduler();
base::Thread* GetThread() const { return thread_.get(); }
scheduler::WorkerSchedulerProxy* worker_scheduler_proxy() const {
return worker_scheduler_proxy_.get();
}
// protected instead of private for unit tests.
scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner_;
private:
void AddTaskObserverInternal(
......@@ -78,7 +81,6 @@ class PLATFORM_EXPORT WebThreadImplForWorkerScheduler
const WebThreadType thread_type_;
std::unique_ptr<scheduler::WorkerSchedulerProxy> worker_scheduler_proxy_;
std::unique_ptr<scheduler::NonMainThreadScheduler> non_main_thread_scheduler_;
scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner_;
scoped_refptr<base::sequence_manager::TaskQueue> task_queue_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
scoped_refptr<scheduler::SingleThreadIdleTaskRunner> idle_task_runner_;
......
......@@ -5,24 +5,34 @@
#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
namespace blink {
namespace scheduler {
WorkerScheduler::WorkerScheduler(
NonMainThreadScheduler* non_main_thread_scheduler)
: default_task_queue_(non_main_thread_scheduler->CreateTaskRunner()),
throttleable_task_queue_(non_main_thread_scheduler->CreateTaskRunner()),
thread_scheduler_(non_main_thread_scheduler) {
WorkerScheduler::WorkerScheduler(WorkerThreadScheduler* worker_thread_scheduler,
WorkerSchedulerProxy* proxy)
: default_task_queue_(worker_thread_scheduler->CreateTaskRunner()),
throttleable_task_queue_(worker_thread_scheduler->CreateTaskRunner()),
thread_scheduler_(worker_thread_scheduler),
weak_factory_(this) {
thread_scheduler_->RegisterWorkerScheduler(this);
if (WakeUpBudgetPool* wake_up_budget_pool =
thread_scheduler_->wake_up_budget_pool()) {
wake_up_budget_pool->AddQueue(thread_scheduler_->GetTickClock()->NowTicks(),
throttleable_task_queue_.get());
}
// |proxy| can be nullptr in unit tests.
if (proxy)
proxy->OnWorkerSchedulerCreated(GetWeakPtr());
}
base::WeakPtr<WorkerScheduler> WorkerScheduler::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
WorkerScheduler::~WorkerScheduler() {
......@@ -36,6 +46,11 @@ WorkerScheduler::OnActiveConnectionCreated() {
return nullptr;
}
FrameOrWorkerScheduler::ThrottlingState
WorkerScheduler::CalculateThrottlingState(ObserverType) const {
return thread_scheduler_->throttling_state();
}
void WorkerScheduler::Dispose() {
if (TaskQueueThrottler* throttler =
thread_scheduler_->task_queue_throttler()) {
......@@ -117,10 +132,11 @@ scoped_refptr<base::SingleThreadTaskRunner> WorkerScheduler::GetTaskRunner(
}
void WorkerScheduler::OnThrottlingStateChanged(
FrameScheduler::ThrottlingState throttling_state) {
ThrottlingState throttling_state) {
if (throttling_state_ == throttling_state)
return;
throttling_state_ = throttling_state;
thread_scheduler_->OnThrottlingStateChanged(throttling_state);
if (TaskQueueThrottler* throttler =
thread_scheduler_->task_queue_throttler()) {
......@@ -130,6 +146,7 @@ void WorkerScheduler::OnThrottlingStateChanged(
throttler->DecreaseThrottleRefCount(throttleable_task_queue_.get());
}
}
NotifyThrottlingObservers();
}
scoped_refptr<base::sequence_manager::TaskQueue>
......
......@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_WORKER_SCHEDULER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_WORKER_SCHEDULER_H_
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
......@@ -15,7 +16,8 @@ namespace blink {
namespace scheduler {
class NonMainThreadScheduler;
class WorkerSchedulerProxy;
class WorkerThreadScheduler;
// A scheduler provides per-global-scope task queues. This is constructed when a
// global scope is created and destructed when it's closed.
......@@ -23,7 +25,8 @@ class NonMainThreadScheduler;
// Unless stated otherwise, all methods must be called on the worker thread.
class PLATFORM_EXPORT WorkerScheduler : public FrameOrWorkerScheduler {
public:
explicit WorkerScheduler(NonMainThreadScheduler* non_main_thread_scheduler);
WorkerScheduler(WorkerThreadScheduler* worker_thread_scheduler,
WorkerSchedulerProxy* proxy);
~WorkerScheduler() override;
std::unique_ptr<ActiveConnectionHandle> OnActiveConnectionCreated() override;
......@@ -37,25 +40,34 @@ class PLATFORM_EXPORT WorkerScheduler : public FrameOrWorkerScheduler {
// This must be called only from WorkerThread::GetTaskRunner().
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) const;
void OnThrottlingStateChanged(
FrameScheduler::ThrottlingState throtting_state);
WorkerThreadScheduler* GetWorkerThreadScheduler() const {
return thread_scheduler_;
}
void OnThrottlingStateChanged(ThrottlingState throttling_state);
ThrottlingState CalculateThrottlingState(ObserverType) const override;
protected:
scoped_refptr<base::sequence_manager::TaskQueue> DefaultTaskQueue();
scoped_refptr<base::sequence_manager::TaskQueue> ThrottleableTaskQueue();
private:
base::WeakPtr<WorkerScheduler> GetWeakPtr();
scoped_refptr<base::sequence_manager::TaskQueue> default_task_queue_;
scoped_refptr<base::sequence_manager::TaskQueue> throttleable_task_queue_;
FrameScheduler::ThrottlingState throttling_state_ =
FrameScheduler::ThrottlingState::kNotThrottled;
NonMainThreadScheduler* thread_scheduler_; // NOT OWNED
WorkerThreadScheduler* thread_scheduler_; // NOT OWNED
#if DCHECK_IS_ON()
bool is_disposed_ = false;
#endif
base::WeakPtrFactory<WorkerScheduler> weak_factory_;
};
} // namespace scheduler
......
......@@ -4,36 +4,41 @@
#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.h"
#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
namespace blink {
namespace scheduler {
WorkerSchedulerProxy::WorkerSchedulerProxy(FrameScheduler* frame_scheduler) {
throttling_observer_handle_ = frame_scheduler->AddThrottlingObserver(
FrameScheduler::ObserverType::kWorkerScheduler, this);
parent_frame_type_ = GetFrameOriginType(frame_scheduler);
WorkerSchedulerProxy::WorkerSchedulerProxy(FrameOrWorkerScheduler* scheduler) {
DCHECK(scheduler);
throttling_observer_handle_ = scheduler->AddThrottlingObserver(
FrameOrWorkerScheduler::ObserverType::kWorkerScheduler, this);
if (FrameScheduler* frame_scheduler = scheduler->ToFrameScheduler()) {
parent_frame_type_ = GetFrameOriginType(frame_scheduler);
}
}
WorkerSchedulerProxy::~WorkerSchedulerProxy() {
DCHECK(IsMainThread());
DETACH_FROM_THREAD(parent_thread_checker_);
}
void WorkerSchedulerProxy::OnWorkerSchedulerCreated(
base::WeakPtr<WorkerThreadScheduler> worker_scheduler) {
base::WeakPtr<WorkerScheduler> worker_scheduler) {
DCHECK(!IsMainThread())
<< "OnWorkerSchedulerCreated should be called from the worker thread";
DCHECK(!worker_scheduler_) << "OnWorkerSchedulerCreated is called twice";
DCHECK(worker_scheduler) << "WorkerScheduler is expected to exist";
worker_scheduler_ = std::move(worker_scheduler);
worker_thread_task_runner_ = worker_scheduler_->ControlTaskQueue();
worker_thread_task_runner_ =
worker_scheduler_->GetWorkerThreadScheduler()->ControlTaskQueue();
initialized_ = true;
}
void WorkerSchedulerProxy::OnThrottlingStateChanged(
FrameScheduler::ThrottlingState throttling_state) {
DCHECK(IsMainThread());
DCHECK_CALLED_ON_VALID_THREAD(parent_thread_checker_);
if (throttling_state_ == throttling_state)
return;
throttling_state_ = throttling_state;
......@@ -42,9 +47,8 @@ void WorkerSchedulerProxy::OnThrottlingStateChanged(
return;
worker_thread_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&WorkerThreadScheduler::OnThrottlingStateChanged,
worker_scheduler_, throttling_state));
FROM_HERE, base::BindOnce(&WorkerScheduler::OnThrottlingStateChanged,
worker_scheduler_, throttling_state));
}
} // namespace scheduler
......
......@@ -8,62 +8,69 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/scheduler/child/page_visibility_state.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace blink {
namespace scheduler {
class WorkerThreadScheduler;
class WorkerScheduler;
// Helper class for communication between frame scheduler (main thread) and
// worker scheduler (worker thread).
// Helper class for communication between parent scheduler (may be a frame
// scheduler on the main thread or another woker scheduler on a worker thread)
// and worker scheduler (worker thread).
//
// It's owned by DedicatedWorkerThread and is created and destroyed
// on the main thread. It's passed to WorkerScheduler during its construction.
// Given that DedicatedWorkerThread object outlives worker thread, this class
// outlives worker thread too.
class PLATFORM_EXPORT WorkerSchedulerProxy : public FrameScheduler::Observer {
// on the parent thread. It's passed to WorkerScheduler during its
// construction. Given that DedicatedWorkerThread object outlives worker thread,
// this class outlives worker thread too.
class PLATFORM_EXPORT WorkerSchedulerProxy
: public FrameOrWorkerScheduler::Observer {
public:
explicit WorkerSchedulerProxy(FrameScheduler* scheduler);
explicit WorkerSchedulerProxy(FrameOrWorkerScheduler* scheduler);
~WorkerSchedulerProxy() override;
void OnWorkerSchedulerCreated(
base::WeakPtr<WorkerThreadScheduler> worker_scheduler);
base::WeakPtr<WorkerScheduler> worker_scheduler);
void OnThrottlingStateChanged(
FrameScheduler::ThrottlingState throttling_state) override;
FrameOrWorkerScheduler::ThrottlingState throttling_state) override;
// Should be accessed only from the main thread or during init.
FrameScheduler::ThrottlingState throttling_state() const {
DCHECK(IsMainThread() || !initialized_);
// Accessed only during init.
FrameOrWorkerScheduler::ThrottlingState throttling_state() const {
DCHECK(!initialized_);
return throttling_state_;
}
FrameOriginType parent_frame_type() const {
DCHECK(IsMainThread() || !initialized_);
// Accessed only during init.
base::Optional<FrameOriginType> parent_frame_type() const {
DCHECK(!initialized_);
return parent_frame_type_;
}
private:
// Can be accessed only from the worker thread.
base::WeakPtr<WorkerThreadScheduler> worker_scheduler_;
base::WeakPtr<WorkerScheduler> worker_scheduler_;
// Const after init on the worker thread.
scoped_refptr<base::SingleThreadTaskRunner> worker_thread_task_runner_;
FrameScheduler::ThrottlingState throttling_state_ =
FrameScheduler::ThrottlingState::kNotThrottled;
FrameOrWorkerScheduler::ThrottlingState throttling_state_ =
FrameOrWorkerScheduler::ThrottlingState::kNotThrottled;
std::unique_ptr<FrameScheduler::ThrottlingObserverHandle>
std::unique_ptr<FrameOrWorkerScheduler::ThrottlingObserverHandle>
throttling_observer_handle_;
bool initialized_ = false;
FrameOriginType parent_frame_type_;
base::Optional<FrameOriginType> parent_frame_type_;
THREAD_CHECKER(parent_thread_checker_);
DISALLOW_COPY_AND_ASSIGN(WorkerSchedulerProxy);
};
......
......@@ -10,6 +10,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
#include "third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h"
......@@ -52,15 +53,37 @@ class WebThreadImplForWorkerSchedulerForTest
WaitableEvent* throtting_state_changed)
: WebThreadImplForWorkerScheduler(
WebThreadCreationParams(WebThreadType::kTestThread)
.SetFrameScheduler(frame_scheduler)),
.SetFrameOrWorkerScheduler(frame_scheduler)),
throtting_state_changed_(throtting_state_changed) {}
~WebThreadImplForWorkerSchedulerForTest() override {
base::WaitableEvent completion(
base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED);
thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&WebThreadImplForWorkerSchedulerForTest::
DisposeWorkerSchedulerOnThread,
base::Unretained(this), &completion));
completion.Wait();
}
void DisposeWorkerSchedulerOnThread(base::WaitableEvent* completion) {
DCHECK(thread_task_runner_->BelongsToCurrentThread());
if (worker_scheduler_) {
worker_scheduler_->Dispose();
worker_scheduler_ = nullptr;
}
completion->Signal();
}
std::unique_ptr<NonMainThreadScheduler> CreateNonMainThreadScheduler()
override {
auto scheduler = std::make_unique<WorkerThreadSchedulerForTest>(
base::sequence_manager::TaskQueueManager::TakeOverCurrentThread(),
worker_scheduler_proxy(), throtting_state_changed_);
scheduler_ = scheduler.get();
worker_scheduler_ = std::make_unique<scheduler::WorkerScheduler>(
scheduler_, worker_scheduler_proxy());
return scheduler;
}
......@@ -69,6 +92,7 @@ class WebThreadImplForWorkerSchedulerForTest
private:
WaitableEvent* throtting_state_changed_; // NOT OWNED
WorkerThreadSchedulerForTest* scheduler_ = nullptr; // NOT OWNED
std::unique_ptr<WorkerScheduler> worker_scheduler_ = nullptr;
};
std::unique_ptr<WebThreadImplForWorkerSchedulerForTest> CreateWorkerThread(
......
......@@ -65,7 +65,7 @@ class WorkerSchedulerForTest : public WorkerScheduler {
public:
explicit WorkerSchedulerForTest(
WorkerThreadSchedulerForTest* thread_scheduler)
: WorkerScheduler(thread_scheduler) {}
: WorkerScheduler(thread_scheduler, nullptr) {}
using WorkerScheduler::DefaultTaskQueue;
using WorkerScheduler::ThrottleableTaskQueue;
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
namespace blink {
// static
const char* FrameOrWorkerScheduler::ThrottlingStateToString(
ThrottlingState state) {
switch (state) {
case ThrottlingState::kNotThrottled:
return "not throttled";
case ThrottlingState::kHidden:
return "hidden";
case ThrottlingState::kThrottled:
return "throttled";
case ThrottlingState::kStopped:
return "frozen";
default:
NOTREACHED();
return nullptr;
}
}
FrameOrWorkerScheduler::ThrottlingObserverHandle::ThrottlingObserverHandle(
FrameOrWorkerScheduler* scheduler,
Observer* observer)
: scheduler_(scheduler->GetWeakPtr()), observer_(observer) {}
FrameOrWorkerScheduler::ThrottlingObserverHandle::~ThrottlingObserverHandle() {
if (scheduler_)
scheduler_->RemoveThrottlingObserver(observer_);
}
FrameOrWorkerScheduler::FrameOrWorkerScheduler() : weak_factory_(this) {}
FrameOrWorkerScheduler::~FrameOrWorkerScheduler() {
weak_factory_.InvalidateWeakPtrs();
}
std::unique_ptr<FrameOrWorkerScheduler::ThrottlingObserverHandle>
FrameOrWorkerScheduler::AddThrottlingObserver(ObserverType type,
Observer* observer) {
DCHECK(observer);
observer->OnThrottlingStateChanged(CalculateThrottlingState(type));
throttling_observers_[observer] = type;
return std::make_unique<ThrottlingObserverHandle>(this, observer);
}
void FrameOrWorkerScheduler::RemoveThrottlingObserver(Observer* observer) {
DCHECK(observer);
const auto found = throttling_observers_.find(observer);
DCHECK(throttling_observers_.end() != found);
throttling_observers_.erase(found);
}
void FrameOrWorkerScheduler::NotifyThrottlingObservers() {
for (const auto& observer : throttling_observers_) {
observer.first->OnThrottlingStateChanged(
CalculateThrottlingState(observer.second));
}
}
base::WeakPtr<FrameOrWorkerScheduler> FrameOrWorkerScheduler::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
} // namespace blink
......@@ -24,23 +24,6 @@
namespace blink {
// static
const char* FrameScheduler::ThrottlingStateToString(ThrottlingState state) {
switch (state) {
case ThrottlingState::kNotThrottled:
return "not throttled";
case ThrottlingState::kHidden:
return "hidden";
case ThrottlingState::kThrottled:
return "throttled";
case ThrottlingState::kStopped:
return "frozen";
default:
NOTREACHED();
return nullptr;
}
}
namespace scheduler {
using base::sequence_manager::TaskQueue;
......@@ -88,19 +71,10 @@ FrameSchedulerImpl::ActiveConnectionHandleImpl::ActiveConnectionHandleImpl(
}
FrameSchedulerImpl::ActiveConnectionHandleImpl::~ActiveConnectionHandleImpl() {
if (frame_scheduler_)
frame_scheduler_->DidCloseActiveConnection();
}
FrameSchedulerImpl::ThrottlingObserverHandleImpl::ThrottlingObserverHandleImpl(
FrameSchedulerImpl* frame_scheduler,
Observer* observer)
: frame_scheduler_(frame_scheduler->GetWeakPtr()), observer_(observer) {}
FrameSchedulerImpl::ThrottlingObserverHandleImpl::
~ThrottlingObserverHandleImpl() {
if (frame_scheduler_)
frame_scheduler_->RemoveThrottlingObserver(observer_);
if (frame_scheduler_) {
static_cast<FrameSchedulerImpl*>(frame_scheduler_.get())
->DidCloseActiveConnection();
}
}
FrameSchedulerImpl::FrameSchedulerImpl(
......@@ -158,8 +132,7 @@ FrameSchedulerImpl::FrameSchedulerImpl(
"FrameScheduler.KeepActive",
this,
&tracing_controller_,
KeepActiveStateToString),
weak_factory_(this) {}
KeepActiveStateToString) {}
namespace {
......@@ -175,8 +148,6 @@ void CleanUpQueue(MainThreadTaskQueue* queue) {
} // namespace
FrameSchedulerImpl::~FrameSchedulerImpl() {
weak_factory_.InvalidateWeakPtrs();
RemoveThrottleableQueueFromBackgroundCPUTimeBudgetPool();
CleanUpQueue(loading_task_queue_.get());
......@@ -219,22 +190,6 @@ void FrameSchedulerImpl::
throttleable_task_queue_.get());
}
std::unique_ptr<FrameScheduler::ThrottlingObserverHandle>
FrameSchedulerImpl::AddThrottlingObserver(ObserverType type,
Observer* observer) {
DCHECK(observer);
observer->OnThrottlingStateChanged(CalculateThrottlingState(type));
throttling_observers_[observer] = type;
return std::make_unique<ThrottlingObserverHandleImpl>(this, observer);
}
void FrameSchedulerImpl::RemoveThrottlingObserver(Observer* observer) {
DCHECK(observer);
const auto found = throttling_observers_.find(observer);
DCHECK(throttling_observers_.end() != found);
throttling_observers_.erase(found);
}
void FrameSchedulerImpl::SetFrameVisible(bool frame_visible) {
DCHECK(parent_page_scheduler_);
if (frame_visible_ == frame_visible)
......@@ -606,13 +561,6 @@ void FrameSchedulerImpl::UpdateQueuePolicy(
voter->SetQueueEnabled(!queue_paused && !queue_frozen);
}
void FrameSchedulerImpl::NotifyThrottlingObservers() {
for (const auto& observer : throttling_observers_) {
observer.first->OnThrottlingStateChanged(
CalculateThrottlingState(observer.second));
}
}
FrameScheduler::ThrottlingState FrameSchedulerImpl::CalculateThrottlingState(
ObserverType type) const {
// Detached frames are not throttled.
......@@ -675,10 +623,6 @@ void FrameSchedulerImpl::UpdateThrottling() {
}
}
base::WeakPtr<FrameSchedulerImpl> FrameSchedulerImpl::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
bool FrameSchedulerImpl::IsExemptFromBudgetBasedThrottling() const {
return has_active_connection();
}
......
......@@ -59,9 +59,6 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
~FrameSchedulerImpl() override;
// FrameScheduler implementation:
std::unique_ptr<ThrottlingObserverHandle> AddThrottlingObserver(
ObserverType,
Observer*) override;
void SetFrameVisible(bool frame_visible) override;
bool IsFrameVisible() const override;
bool IsPageVisible() const override;
......@@ -109,36 +106,21 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
~ActiveConnectionHandleImpl() override;
private:
base::WeakPtr<FrameSchedulerImpl> frame_scheduler_;
base::WeakPtr<FrameOrWorkerScheduler> frame_scheduler_;
DISALLOW_COPY_AND_ASSIGN(ActiveConnectionHandleImpl);
};
class ThrottlingObserverHandleImpl : public ThrottlingObserverHandle {
public:
ThrottlingObserverHandleImpl(FrameSchedulerImpl* frame_scheduler,
Observer* observer);
~ThrottlingObserverHandleImpl() override;
private:
base::WeakPtr<FrameSchedulerImpl> frame_scheduler_;
Observer* observer_;
DISALLOW_COPY_AND_ASSIGN(ThrottlingObserverHandleImpl);
};
void DetachFromPageScheduler();
void RemoveThrottleableQueueFromBackgroundCPUTimeBudgetPool();
void ApplyPolicyToThrottleableQueue();
bool ShouldThrottleTimers() const;
FrameScheduler::ThrottlingState CalculateThrottlingState(
ObserverType type) const;
void RemoveThrottlingObserver(Observer* observer);
ObserverType type) const override;
void UpdateQueuePolicy(
const scoped_refptr<MainThreadTaskQueue>& queue,
base::sequence_manager::TaskQueue::QueueEnabledVoter* voter);
void UpdateThrottling();
void NotifyThrottlingObservers();
void DidOpenActiveConnection();
void DidCloseActiveConnection();
......@@ -150,8 +132,6 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
scoped_refptr<base::sequence_manager::TaskQueue> PausableTaskQueue();
scoped_refptr<base::sequence_manager::TaskQueue> UnpausableTaskQueue();
base::WeakPtr<FrameSchedulerImpl> GetWeakPtr();
const FrameScheduler::FrameType frame_type_;
TraceableVariableController tracing_controller_;
......@@ -174,8 +154,6 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
MainThreadSchedulerImpl* main_thread_scheduler_; // NOT OWNED
PageSchedulerImpl* parent_page_scheduler_; // NOT OWNED
base::trace_event::BlameContext* blame_context_; // NOT OWNED
// Observers are not owned by the scheduler.
std::unordered_map<Observer*, ObserverType> throttling_observers_;
FrameScheduler::ThrottlingState throttling_state_;
TraceableState<bool, kTracingCategoryNameInfo> frame_visible_;
TraceableState<bool, kTracingCategoryNameInfo> frame_paused_;
......@@ -196,7 +174,6 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
page_visibility_for_tracing_;
TraceableState<bool, kTracingCategoryNameInfo> page_keep_active_for_tracing_;
base::WeakPtrFactory<FrameSchedulerImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(FrameSchedulerImpl);
};
......
......@@ -5,16 +5,62 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_FRAME_OR_WORKER_SCHEDULER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_FRAME_OR_WORKER_SCHEDULER_H_
#include <unordered_map>
#include "base/memory/weak_ptr.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
namespace blink {
class FrameScheduler;
// This is the base class of FrameScheduler and WorkerScheduler.
class FrameOrWorkerScheduler {
class PLATFORM_EXPORT FrameOrWorkerScheduler {
USING_FAST_MALLOC(FrameOrWorkerScheduler);
public:
virtual ~FrameOrWorkerScheduler() = default;
// Observer type that regulates conditions to invoke callbacks.
enum class ObserverType { kLoader, kWorkerScheduler };
// Represents throttling state.
// TODO(altimin): Move it into standalone LifecycleState.
enum class ThrottlingState {
// Frame is active and should not be throttled.
kNotThrottled,
// Frame has just been backgrounded and can be throttled non-aggressively.
kHidden,
// Frame spent some time in background and can be fully throttled.
kThrottled,
// Frame is stopped, no tasks associated with it can run.
kStopped,
};
static const char* ThrottlingStateToString(ThrottlingState state);
// Observer interface to receive scheduling policy change events.
class Observer {
public:
virtual ~Observer() = default;
// Notified when throttling state is changed. May be called consecutively
// with the same value.
virtual void OnThrottlingStateChanged(ThrottlingState) = 0;
};
class PLATFORM_EXPORT ThrottlingObserverHandle {
public:
ThrottlingObserverHandle(FrameOrWorkerScheduler* scheduler,
Observer* observer);
~ThrottlingObserverHandle();
private:
base::WeakPtr<FrameOrWorkerScheduler> scheduler_;
Observer* observer_;
DISALLOW_COPY_AND_ASSIGN(ThrottlingObserverHandle);
};
virtual ~FrameOrWorkerScheduler();
class ActiveConnectionHandle {
public:
......@@ -30,6 +76,34 @@ class FrameOrWorkerScheduler {
// this handle must be destroyed.
virtual std::unique_ptr<ActiveConnectionHandle>
OnActiveConnectionCreated() = 0;
// Adds an Observer instance to be notified on scheduling policy changed.
// When an Observer is added, the initial state will be notified synchronously
// through the Observer interface.
// A RAII handle is returned and observer is unregistered when the handle is
// destroyed.
std::unique_ptr<ThrottlingObserverHandle> AddThrottlingObserver(ObserverType,
Observer*);
virtual FrameScheduler* ToFrameScheduler() { return nullptr; }
protected:
FrameOrWorkerScheduler();
void NotifyThrottlingObservers();
virtual ThrottlingState CalculateThrottlingState(ObserverType) const {
return ThrottlingState::kNotThrottled;
}
base::WeakPtr<FrameOrWorkerScheduler> GetWeakPtr();
private:
void RemoveThrottlingObserver(Observer* observer);
// Observers are not owned by the scheduler.
std::unordered_map<Observer*, ObserverType> throttling_observers_;
base::WeakPtrFactory<FrameOrWorkerScheduler> weak_factory_;
};
} // namespace blink
......
......@@ -23,59 +23,12 @@ class FrameScheduler : public FrameOrWorkerScheduler {
public:
~FrameScheduler() override = default;
// Observer type that regulates conditions to invoke callbacks.
enum class ObserverType { kLoader, kWorkerScheduler };
// Represents throttling state.
// TODO(altimin): Move it into standalone LifecycleState.
enum class ThrottlingState {
// Frame is active and should not be throttled.
kNotThrottled,
// Frame has just been backgrounded and can be throttled non-aggressively.
kHidden,
// Frame spent some time in background and can be fully throttled.
kThrottled,
// Frame is stopped, no tasks associated with it can run.
kStopped,
};
PLATFORM_EXPORT static const char* ThrottlingStateToString(
ThrottlingState state);
// Represents the type of frame: main (top-level) vs not.
enum class FrameType {
kMainFrame,
kSubframe,
};
// Observer interface to receive scheduling policy change events.
class Observer {
public:
virtual ~Observer() = default;
// Notified when throttling state is changed. May be called consecutively
// with the same value.
virtual void OnThrottlingStateChanged(ThrottlingState) = 0;
};
class ThrottlingObserverHandle {
public:
ThrottlingObserverHandle() = default;
virtual ~ThrottlingObserverHandle() = default;
private:
DISALLOW_COPY_AND_ASSIGN(ThrottlingObserverHandle);
};
// Adds an Observer instance to be notified on scheduling policy changed.
// When an Observer is added, the initial state will be notified synchronously
// through the Observer interface.
// A RAII handle is returned and observer is unregistered when the handle is
// destroyed.
virtual std::unique_ptr<ThrottlingObserverHandle> AddThrottlingObserver(
ObserverType,
Observer*) = 0;
// The scheduler may throttle tasks associated with offscreen frames.
virtual void SetFrameVisible(bool) = 0;
virtual bool IsFrameVisible() const = 0;
......@@ -168,6 +121,8 @@ class FrameScheduler : public FrameOrWorkerScheduler {
// use GetPageScheduler()->IsExemptFromBudgetBasedThrottling for the status
// of the page.
virtual bool IsExemptFromBudgetBasedThrottling() const = 0;
FrameScheduler* ToFrameScheduler() override { return this; }
};
} // namespace blink
......
......@@ -104,11 +104,6 @@ class FakeFrameScheduler : public FrameScheduler {
};
// FrameScheduler implementation:
std::unique_ptr<ThrottlingObserverHandle> AddThrottlingObserver(
ObserverType,
Observer*) override {
return nullptr;
}
void SetFrameVisible(bool) override {}
bool IsFrameVisible() const override { return is_frame_visible_; }
bool IsPageVisible() const override { return is_page_visible_; }
......
......@@ -75,16 +75,13 @@ WorkerThreadScheduler::WorkerThreadScheduler(
worker_metrics_helper_(thread_type),
default_task_runner_(TaskQueueWithTaskType::Create(
helper_->DefaultWorkerTaskQueue(),
TaskType::kWorkerThreadTaskQueueDefault)),
weak_factory_(this) {
TaskType::kWorkerThreadTaskQueueDefault)) {
thread_start_time_ = helper_->NowTicks();
load_tracker_.Resume(thread_start_time_);
helper_->AddTaskTimeObserver(this);
if (proxy) {
worker_metrics_helper_.SetParentFrameType(proxy->parent_frame_type());
proxy->OnWorkerSchedulerCreated(GetWeakPtr());
}
if (proxy && proxy->parent_frame_type())
worker_metrics_helper_.SetParentFrameType(*proxy->parent_frame_type());
if (thread_type == WebThreadType::kDedicatedWorkerThread &&
base::FeatureList::IsEnabled(kDedicatedWorkerThrottling)) {
......@@ -237,10 +234,6 @@ scoped_refptr<WorkerTaskQueue> WorkerThreadScheduler::ControlTaskQueue() {
return helper_->ControlWorkerTaskQueue();
}
base::WeakPtr<WorkerThreadScheduler> WorkerThreadScheduler::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
void WorkerThreadScheduler::CreateTaskQueueThrottler() {
if (task_queue_throttler_)
return;
......
......@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_THREAD_SCHEDULER_H_
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/platform/web_thread_type.h"
......@@ -74,6 +73,12 @@ class PLATFORM_EXPORT WorkerThreadScheduler
virtual void OnThrottlingStateChanged(
FrameScheduler::ThrottlingState throttling_state);
FrameScheduler::ThrottlingState throttling_state() const {
return throttling_state_;
}
void RegisterWorkerScheduler(WorkerScheduler* worker_scheduler) override;
// Returns the control task queue. Tasks posted to this queue are executed
// with the highest priority. Care must be taken to avoid starvation of other
// task queues.
......@@ -92,19 +97,11 @@ class PLATFORM_EXPORT WorkerThreadScheduler
void OnIdlePeriodEnded() override {}
void OnPendingTasksChanged(bool new_state) override {}
FrameScheduler::ThrottlingState throttling_state() const {
return throttling_state_;
}
void RegisterWorkerScheduler(WorkerScheduler* worker_scheduler) override;
void CreateTaskQueueThrottler();
private:
void MaybeStartLongIdlePeriod();
base::WeakPtr<WorkerThreadScheduler> GetWeakPtr();
IdleHelper idle_helper_;
IdleCanceledDelayedTaskSweeper idle_canceled_delayed_task_sweeper_;
ThreadLoadTracker load_tracker_;
......@@ -119,8 +116,6 @@ class PLATFORM_EXPORT WorkerThreadScheduler
scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
base::WeakPtrFactory<WorkerThreadScheduler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(WorkerThreadScheduler);
};
......
......@@ -19,7 +19,7 @@ namespace blink {
WebThreadCreationParams::WebThreadCreationParams(WebThreadType thread_type)
: thread_type(thread_type),
name(GetNameForThreadType(thread_type)),
frame_scheduler(nullptr) {}
frame_or_worker_scheduler(nullptr) {}
WebThreadCreationParams& WebThreadCreationParams::SetThreadNameForTest(
const char* thread_name) {
......@@ -27,9 +27,9 @@ WebThreadCreationParams& WebThreadCreationParams::SetThreadNameForTest(
return *this;
}
WebThreadCreationParams& WebThreadCreationParams::SetFrameScheduler(
FrameScheduler* scheduler) {
frame_scheduler = scheduler;
WebThreadCreationParams& WebThreadCreationParams::SetFrameOrWorkerScheduler(
FrameOrWorkerScheduler* scheduler) {
frame_or_worker_scheduler = scheduler;
return *this;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment