blob: b00e881e7f04fb7fc53e91fbf61b8acef4e7a6a4 [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_GRAPH_H_
#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_GRAPH_H_
#include <cstdint>
#include <memory>
#include <unordered_set>
#include "base/dcheck_is_on.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/observer_list_types.h"
#include "base/scoped_observation_traits.h"
#include "base/sequence_checker.h"
#include "components/performance_manager/public/graph/node_set_view.h"
namespace ukm {
class UkmRecorder;
} // namespace ukm
namespace performance_manager {
class GraphOwned;
class GraphRegistered;
class FrameNode;
class FrameNodeObserver;
class NodeDataDescriberRegistry;
class PageNode;
class PageNodeObserver;
class ProcessNode;
class ProcessNodeObserver;
class SystemNode;
class SystemNodeObserver;
class WorkerNode;
class WorkerNodeObserver;
template <typename DerivedType>
class GraphRegisteredImpl;
// Represents a graph of the nodes representing a single browser. Maintains a
// set of nodes that can be retrieved in different ways, some indexed. Keeps
// a list of observers that are notified of node addition and removal.
class Graph {
public:
using NodeSet = std::unordered_set<const Node*>;
template <class NodeViewPtr>
using NodeSetView = NodeSetView<NodeSet, NodeViewPtr>;
Graph();
Graph(const Graph&) = delete;
Graph& operator=(const Graph&) = delete;
virtual ~Graph();
// Adds an |observer| on the graph. It is safe for observers to stay
// registered on the graph at the time of its death.
virtual void AddFrameNodeObserver(FrameNodeObserver* observer) = 0;
virtual void AddPageNodeObserver(PageNodeObserver* observer) = 0;
virtual void AddProcessNodeObserver(ProcessNodeObserver* observer) = 0;
virtual void AddSystemNodeObserver(SystemNodeObserver* observer) = 0;
virtual void AddWorkerNodeObserver(WorkerNodeObserver* observer) = 0;
// Removes an |observer| from the graph.
virtual void RemoveFrameNodeObserver(FrameNodeObserver* observer) = 0;
virtual void RemovePageNodeObserver(PageNodeObserver* observer) = 0;
virtual void RemoveProcessNodeObserver(ProcessNodeObserver* observer) = 0;
virtual void RemoveSystemNodeObserver(SystemNodeObserver* observer) = 0;
virtual void RemoveWorkerNodeObserver(WorkerNodeObserver* observer) = 0;
// For convenience, allows you to pass ownership of an object to the graph.
// Useful for attaching observers that will live with the graph until it dies.
// If you can name the object you can also take it back via "TakeFromGraph".
virtual void PassToGraphImpl(std::unique_ptr<GraphOwned> graph_owned) = 0;
virtual std::unique_ptr<GraphOwned> TakeFromGraph(
GraphOwned* graph_owned) = 0;
// Templated PassToGraph helper that also returns a pointer to the object,
// which makes it easy to use PassToGraph in constructors.
template <typename DerivedType>
DerivedType* PassToGraph(std::unique_ptr<DerivedType> graph_owned) {
DerivedType* object = graph_owned.get();
PassToGraphImpl(std::move(graph_owned));
return object;
}
// A TakeFromGraph helper for taking back the ownership of a GraphOwned
// subclass.
template <typename DerivedType>
std::unique_ptr<DerivedType> TakeFromGraphAs(DerivedType* graph_owned) {
return base::WrapUnique(
static_cast<DerivedType*>(TakeFromGraph(graph_owned).release()));
}
// Registers an object with this graph. It is expected that no more than one
// object of a given type is registered at a given moment, and that all
// registered objects are unregistered before graph tear-down.
virtual void RegisterObject(GraphRegistered* object) = 0;
// Unregisters the provided |object|, which must previously have been
// registered with "RegisterObject". It is expected that all registered
// objects are unregistered before graph tear-down.
virtual void UnregisterObject(GraphRegistered* object) = 0;
// Returns the registered object of the given type, nullptr if none has been
// registered.
template <typename DerivedType>
DerivedType* GetRegisteredObjectAs() {
// Be sure to access the TypeId provided by GraphRegisteredImpl, in case
// this class has other TypeId implementations.
GraphRegistered* object =
GetRegisteredObject(GraphRegisteredImpl<DerivedType>::TypeId());
return static_cast<DerivedType*>(object);
}
// Returns the single system node.
virtual const SystemNode* GetSystemNode() const = 0;
// Returns a collection of all known nodes of the given type.
virtual NodeSetView<const ProcessNode*> GetAllProcessNodes() const = 0;
virtual NodeSetView<const FrameNode*> GetAllFrameNodes() const = 0;
virtual NodeSetView<const PageNode*> GetAllPageNodes() const = 0;
virtual NodeSetView<const WorkerNode*> GetAllWorkerNodes() const = 0;
// Returns true if the graph only contains the default nodes.
virtual bool HasOnlySystemNode() const = 0;
// Returns the associated UKM recorder if it is defined.
virtual ukm::UkmRecorder* GetUkmRecorder() const = 0;
// Returns the data describer registry.
virtual NodeDataDescriberRegistry* GetNodeDataDescriberRegistry() const = 0;
// The following functions are implementation detail and should not need to be
// used by external clients. They provide the ability to safely downcast to
// the underlying implementation.
virtual uintptr_t GetImplType() const = 0;
virtual const void* GetImpl() const = 0;
// Allows code that is not explicitly aware of the Graph sequence to determine
// if they are in fact on the right sequence. Prefer to use the
// DCHECK_ON_GRAPH_SEQUENCE macro.
#if DCHECK_IS_ON()
virtual bool IsOnGraphSequence() const = 0;
#endif
private:
// Retrieves the object with the given |type_id|, returning nullptr if none
// exists. Clients must use the GetRegisteredObjectAs wrapper instead.
virtual GraphRegistered* GetRegisteredObject(uintptr_t type_id) = 0;
};
#if DCHECK_IS_ON()
#define DCHECK_ON_GRAPH_SEQUENCE(graph) DCHECK(graph->IsOnGraphSequence())
#else
// Compiles to a nop, and will eat ostream input.
#define DCHECK_ON_GRAPH_SEQUENCE(graph) DCHECK(true)
#endif
// Helper class for passing ownership of objects to a graph.
class GraphOwned {
public:
GraphOwned();
GraphOwned(const GraphOwned&) = delete;
GraphOwned& operator=(const GraphOwned&) = delete;
virtual ~GraphOwned();
// Called when the object is passed into the graph.
virtual void OnPassedToGraph(Graph* graph) = 0;
// Called when the object is removed from the graph, either via an explicit
// call to Graph::TakeFromGraph, or prior to the Graph being destroyed.
virtual void OnTakenFromGraph(Graph* graph) = 0;
// Returns a pointer to the owning Graph. The will return nullptr before
// OnPassedToGraph() and after OnTakenFromGraph(), and a valid pointer at all
// other times.
Graph* GetOwningGraph() const;
private:
// GraphImpl is allowed to call PassToGraphImpl and TakeFromGraphImpl.
friend class GraphImpl;
// GraphOwnedAndRegistered overrides PassToGraphImpl and TakeFromGraphImpl.
template <typename SelfType>
friend class GraphOwnedAndRegistered;
// Only friends can override these. The default implementations just call
// OnPassedToGraph() and OnTakenFromGraph(). Helper classes like
// GraphOwnedAndRegistered can override these to add actions, while their
// subclasses continue to override OnPassedToGraph and OnTakenFromGraph
// without having to remember to call the inherited methods.
virtual void PassToGraphImpl(Graph* graph);
virtual void TakeFromGraphImpl(Graph* graph);
SEQUENCE_CHECKER(sequence_checker_);
// Pointer back to the owning graph.
raw_ptr<Graph> graph_ GUARDED_BY_CONTEXT(sequence_checker_) = nullptr;
};
// A default implementation of GraphOwned.
class GraphOwnedDefaultImpl : public GraphOwned {
public:
GraphOwnedDefaultImpl();
GraphOwnedDefaultImpl(const GraphOwnedDefaultImpl&) = delete;
GraphOwnedDefaultImpl& operator=(const GraphOwnedDefaultImpl&) = delete;
~GraphOwnedDefaultImpl() override;
// GraphOwned implementation:
void OnPassedToGraph(Graph* graph) override {}
void OnTakenFromGraph(Graph* graph) override {}
};
} // namespace performance_manager
namespace base {
// Specialize ScopedObservation to invoke the correct add and remove methods for
// each node observer type. These must be in the same namespace as
// base::ScopedObservationTraits.
template <>
struct ScopedObservationTraits<performance_manager::Graph,
performance_manager::FrameNodeObserver> {
static void AddObserver(performance_manager::Graph* graph,
performance_manager::FrameNodeObserver* observer) {
graph->AddFrameNodeObserver(observer);
}
static void RemoveObserver(performance_manager::Graph* graph,
performance_manager::FrameNodeObserver* observer) {
graph->RemoveFrameNodeObserver(observer);
}
};
template <>
struct ScopedObservationTraits<performance_manager::Graph,
performance_manager::PageNodeObserver> {
static void AddObserver(performance_manager::Graph* graph,
performance_manager::PageNodeObserver* observer) {
graph->AddPageNodeObserver(observer);
}
static void RemoveObserver(performance_manager::Graph* graph,
performance_manager::PageNodeObserver* observer) {
graph->RemovePageNodeObserver(observer);
}
};
template <>
struct ScopedObservationTraits<performance_manager::Graph,
performance_manager::ProcessNodeObserver> {
static void AddObserver(performance_manager::Graph* graph,
performance_manager::ProcessNodeObserver* observer) {
graph->AddProcessNodeObserver(observer);
}
static void RemoveObserver(
performance_manager::Graph* graph,
performance_manager::ProcessNodeObserver* observer) {
graph->RemoveProcessNodeObserver(observer);
}
};
template <>
struct ScopedObservationTraits<performance_manager::Graph,
performance_manager::SystemNodeObserver> {
static void AddObserver(performance_manager::Graph* graph,
performance_manager::SystemNodeObserver* observer) {
graph->AddSystemNodeObserver(observer);
}
static void RemoveObserver(
performance_manager::Graph* graph,
performance_manager::SystemNodeObserver* observer) {
graph->RemoveSystemNodeObserver(observer);
}
};
template <>
struct ScopedObservationTraits<performance_manager::Graph,
performance_manager::WorkerNodeObserver> {
static void AddObserver(performance_manager::Graph* graph,
performance_manager::WorkerNodeObserver* observer) {
graph->AddWorkerNodeObserver(observer);
}
static void RemoveObserver(
performance_manager::Graph* graph,
performance_manager::WorkerNodeObserver* observer) {
graph->RemoveWorkerNodeObserver(observer);
}
};
} // namespace base
#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_GRAPH_H_