// 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. #ifndef CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_WATCHER_H_ #define CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_WATCHER_H_ #include #include "base/power_monitor/power_observer.h" #include "content/browser/scheduler/responsiveness/metric_source.h" namespace content { namespace responsiveness { class Calculator; class CONTENT_EXPORT Watcher : public base::RefCounted, public MetricSource::Delegate, public base::PowerObserver { public: Watcher(); void SetUp(); void Destroy(); protected: friend class base::RefCounted; // Exposed for tests. virtual std::unique_ptr CreateCalculator(); virtual std::unique_ptr CreateMetricSource(); ~Watcher() override; // Delegate interface implementation. void SetUpOnIOThread() override; void TearDownOnUIThread() override; void TearDownOnIOThread() override; void WillRunTaskOnUIThread(const base::PendingTask* task, bool was_blocked_or_low_priority) override; void DidRunTaskOnUIThread(const base::PendingTask* task) override; void WillRunTaskOnIOThread(const base::PendingTask* task, bool was_blocked_or_low_priority) override; void DidRunTaskOnIOThread(const base::PendingTask* task) override; void WillRunEventOnUIThread(const void* opaque_identifier) override; void DidRunEventOnUIThread(const void* opaque_identifier) override; // base::PowerObserver interface implementation. The PowerObserver // notifications are asynchronously callbacks on their registration sequence // and may be delayed if there is a long queue of pending tasks to be // executed. void OnSuspend() override; void OnResume() override; private: FRIEND_TEST_ALL_PREFIXES(ResponsivenessWatcherTest, TaskForwarding); FRIEND_TEST_ALL_PREFIXES(ResponsivenessWatcherTest, TaskNesting); FRIEND_TEST_ALL_PREFIXES(ResponsivenessWatcherTest, NativeEvents); FRIEND_TEST_ALL_PREFIXES(ResponsivenessWatcherTest, BlockedOrLowPriorityTask); FRIEND_TEST_ALL_PREFIXES(ResponsivenessWatcherTest, DelayedTask); // Metadata for currently running tasks and events is needed to track whether // or not they caused reentrancy. struct Metadata { explicit Metadata(const void* identifier, bool was_blocked_or_low_priority, base::TimeTicks execution_start_time); // An opaque identifier for the task or event. const void* const identifier; // Whether the task was at some point in a queue that was blocked or low // priority. const bool was_blocked_or_low_priority; // The time at which the task or event started running. const base::TimeTicks execution_start_time; // Whether the task or event has caused reentrancy. bool caused_reentrancy = false; }; // This is called when |metric_source_| finishes destruction. void FinishDestroyMetricSource(); // Common implementations for the thread-specific methods. void WillRunTask(const base::PendingTask* task, bool was_blocked_or_low_priority, std::vector* currently_running_metadata); // |callback| will either be synchronously invoked, or else never invoked. using TaskOrEventFinishedCallback = base::OnceCallback< void(base::TimeTicks, base::TimeTicks, base::TimeTicks)>; void DidRunTask(const base::PendingTask* task, std::vector* currently_running_metadata, int* mismatched_task_identifiers, TaskOrEventFinishedCallback callback); // The source that emits responsiveness events. std::unique_ptr metric_source_; // The following members are all affine to the UI thread. std::unique_ptr calculator_; // Metadata for currently running tasks and events on the UI thread. std::vector currently_running_metadata_ui_; // Task identifiers should only be mismatched once, since the Watcher may // register itself during a Task execution, and thus doesn't capture the // initial WillRunTask() callback. int mismatched_task_identifiers_ui_ = 0; // Event identifiers should be mismatched at most once, since the Watcher may // register itself during an event execution, and thus doesn't capture the // initial WillRunEventOnUIThread callback. int mismatched_event_identifiers_ui_ = 0; // The following members are all affine to the IO thread. std::vector currently_running_metadata_io_; int mismatched_task_identifiers_io_ = 0; // The implementation of this class guarantees that |calculator_io_| will be // non-nullptr and point to a valid object any time it is used on the IO // thread. To ensure this, the first task that this class posts onto the IO // thread sets |calculator_io_|. On destruction, this class first tears down // all consumers of |calculator_io_|, and then clears the member and destroys // Calculator. Calculator* calculator_io_ = nullptr; }; } // namespace responsiveness } // namespace content #endif // CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_WATCHER_H_