Commit 70cf1d08 authored by Chris Hamilton's avatar Chris Hamilton Committed by Commit Bot

[PM] Lift NodeAttachedData to public interface.

This adds opaque ToNodeBase functionality to public node types allowing
the NodeAttachedData implementation to avoid specialization for each
known public node type.

BUG=958115

Change-Id: Ib19c07319d43205560fd4086a919abee30cab5d6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1597694
Commit-Queue: Chris Hamilton <chrisha@chromium.org>
Reviewed-by: default avatarSigurður Ásgeirsson <siggi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#657740}
parent 48bf40bd
......@@ -1114,6 +1114,7 @@ jumbo_split_static_library("browser") {
"performance_manager/performance_manager_tab_helper.h",
"performance_manager/public/graph/frame_node.h",
"performance_manager/public/graph/graph.h",
"performance_manager/public/graph/node_attached_data.h",
"performance_manager/public/graph/page_node.h",
"performance_manager/public/graph/process_node.h",
"performance_manager/public/graph/system_node.h",
......
......@@ -43,7 +43,7 @@ class ProcessNodeImpl;
// another process!) and commits, the frame will be swapped with the previously
// active frame.
class FrameNodeImpl
: public FrameNode,
: public PublicNodeImpl<FrameNodeImpl, FrameNode>,
public CoordinationUnitInterface<
FrameNodeImpl,
resource_coordinator::mojom::DocumentCoordinationUnit,
......@@ -62,7 +62,7 @@ class FrameNodeImpl
const base::UnguessableToken& dev_tools_token);
~FrameNodeImpl() override;
// FrameNode implementation.
// resource_coordinator::mojom::DocumentCoordinationUnit implementation.
void SetNetworkAlmostIdle(bool idle) override;
void SetLifecycleState(
resource_coordinator::mojom::LifecycleState state) override;
......
......@@ -36,6 +36,13 @@ class FrameNodeImplTest : public GraphTestHarness {
} // namespace
TEST_F(FrameNodeImplTest, GetIndexingKey) {
auto process = CreateNode<ProcessNodeImpl>();
auto page = CreateNode<PageNodeImpl>();
auto frame = CreateNode<FrameNodeImpl>(process.get(), page.get());
EXPECT_EQ(frame->GetIndexingKey(), static_cast<const NodeBase*>(frame.get()));
}
TEST_F(FrameNodeImplTest, AddFrameHierarchyBasic) {
auto process = CreateNode<ProcessNodeImpl>();
auto page = CreateNode<PageNodeImpl>();
......
......@@ -102,7 +102,7 @@ class GraphImpl : public Graph {
ukm::UkmRecorder* ukm_recorder_ = nullptr;
// User data storage for the graph.
friend class NodeAttachedData;
friend class NodeAttachedDataMapHelper;
using NodeAttachedDataKey = std::pair<const NodeBase*, const void*>;
using NodeAttachedDataMap =
std::map<NodeAttachedDataKey, std::unique_ptr<NodeAttachedData>>;
......
......@@ -16,30 +16,35 @@ NodeAttachedData::NodeAttachedData() = default;
NodeAttachedData::~NodeAttachedData() = default;
// static
void NodeAttachedData::AttachInMap(const NodeBase* node,
std::unique_ptr<NodeAttachedData> data) {
GraphImpl::NodeAttachedDataKey data_key = std::make_pair(node, data->key());
void NodeAttachedDataMapHelper::AttachInMap(
const NodeBase* node,
std::unique_ptr<NodeAttachedData> data) {
DCHECK(node->graph()->NodeInGraph(node));
GraphImpl::NodeAttachedDataKey data_key =
std::make_pair(node, data->GetKey());
auto& map = node->graph()->node_attached_data_map_;
DCHECK(!base::ContainsKey(map, data_key));
map[data_key] = std::move(data);
}
// static
NodeAttachedData* NodeAttachedData::GetFromMap(const NodeBase* node,
const void* key) {
NodeAttachedData* NodeAttachedDataMapHelper::GetFromMap(const NodeBase* node,
const void* key) {
DCHECK(node->graph()->NodeInGraph(node));
GraphImpl::NodeAttachedDataKey data_key = std::make_pair(node, key);
auto& map = node->graph()->node_attached_data_map_;
auto it = map.find(data_key);
if (it == map.end())
return nullptr;
DCHECK_EQ(key, it->second->key());
DCHECK_EQ(key, it->second->GetKey());
return it->second.get();
}
// static
std::unique_ptr<NodeAttachedData> NodeAttachedData::DetachFromMap(
std::unique_ptr<NodeAttachedData> NodeAttachedDataMapHelper::DetachFromMap(
const NodeBase* node,
const void* key) {
DCHECK(node->graph()->NodeInGraph(node));
GraphImpl::NodeAttachedDataKey data_key = std::make_pair(node, key);
auto& map = node->graph()->node_attached_data_map_;
auto it = map.find(data_key);
......
......@@ -9,49 +9,12 @@
#include "base/logging.h"
#include "base/macros.h"
#include "chrome/browser/performance_manager/graph/node_type.h"
#include "chrome/browser/performance_manager/public/graph/node_attached_data.h"
namespace performance_manager {
class NodeBase;
// Abstract base class used for attaching user data to nodes in the graph.
// Implementations should derive from NodeAttachedDataImpl. See
// node_attached_data_impl.h for details.
class NodeAttachedData {
public:
NodeAttachedData();
virtual ~NodeAttachedData();
// Returns the 'key' associated with this type of NodeAttachedData. This needs
// to be unique per data type or bad things happen.
virtual const void* key() const = 0;
protected:
friend class NodeAttachedDataTest;
// For creating / retrieving / destroying data that is stored in a global map
// owned by the graph. These are not intended to be used directly, rather
// they are invoked by the typed helper functions provided via
// NodeAttachedDataImpl.
// Attaches the provided |data| to the provided |node|. This should only be
// called if the data does not exist (GetFromMap returns nullptr), and will
// DCHECK otherwise. This should also only be called if |data| can be attached
// to the given node type (also enforced by a DCHECK).
static void AttachInMap(const NodeBase* node,
std::unique_ptr<NodeAttachedData> data);
// Retrieves the data associated with the provided |node| and |key|. This
// returns nullptr if no data exists.
static NodeAttachedData* GetFromMap(const NodeBase* node, const void* key);
// Detaches the data associated with the provided |node| and |key|. It is
// harmless to call this when no data exists.
static std::unique_ptr<NodeAttachedData> DetachFromMap(const NodeBase* node,
const void* key);
};
// Helper class for providing internal storage of a NodeAttachedData
// implementation directly in a node. The storage is provided as a raw buffer of
// bytes which is initialized externally by the NodeAttachedDataImpl via a
......@@ -98,6 +61,68 @@ class InternalNodeAttachedDataStorage {
DISALLOW_COPY_AND_ASSIGN(InternalNodeAttachedDataStorage);
};
// Provides access for setting/getting data in the map based storage. Not
// intended to be used directly, but rather by (External)NodeAttachedDataImpl.
class NodeAttachedDataMapHelper {
public:
// Attaches the provided |data| to the provided |node|. This should only be
// called if the data does not exist (GetFromMap returns nullptr), and will
// DCHECK otherwise.
static void AttachInMap(const NodeBase* node,
std::unique_ptr<NodeAttachedData> data);
// Retrieves the data associated with the provided |node| and |key|. This
// returns nullptr if no data exists.
static NodeAttachedData* GetFromMap(const NodeBase* node, const void* key);
// Detaches the data associated with the provided |node| and |key|. It is
// harmless to call this when no data exists.
static std::unique_ptr<NodeAttachedData> DetachFromMap(const NodeBase* node,
const void* key);
};
// Implementation of ExternalNodeAttachedDataImpl, which is declared in the
// corresponding public header. This helps keep the public headers as clean as
// possible.
// static
template <typename UserDataType>
constexpr int ExternalNodeAttachedDataImpl<UserDataType>::kUserDataKey;
template <typename UserDataType>
template <typename NodeType>
UserDataType* ExternalNodeAttachedDataImpl<UserDataType>::GetOrCreate(
const NodeType* node) {
if (auto* data = Get(node))
return data;
std::unique_ptr<UserDataType> data = std::make_unique<UserDataType>(node);
auto* raw_data = data.get();
auto* base = reinterpret_cast<const NodeBase*>(node->GetIndexingKey());
NodeAttachedDataMapHelper::AttachInMap(base, std::move(data));
return raw_data;
}
template <typename UserDataType>
template <typename NodeType>
UserDataType* ExternalNodeAttachedDataImpl<UserDataType>::Get(
const NodeType* node) {
auto* base = reinterpret_cast<const NodeBase*>(node->GetIndexingKey());
auto* data = NodeAttachedDataMapHelper::GetFromMap(base, UserDataKey());
if (!data)
return nullptr;
DCHECK_EQ(UserDataKey(), data->GetKey());
return static_cast<UserDataType*>(data);
}
template <typename UserDataType>
template <typename NodeType>
bool ExternalNodeAttachedDataImpl<UserDataType>::Destroy(const NodeType* node) {
auto* base = reinterpret_cast<const NodeBase*>(node->GetIndexingKey());
std::unique_ptr<NodeAttachedData> data =
NodeAttachedDataMapHelper::DetachFromMap(base, UserDataKey());
return data.get();
}
} // namespace performance_manager
#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_NODE_ATTACHED_DATA_H_
......@@ -190,7 +190,7 @@ class NodeAttachedDataImpl : public NodeAttachedData {
static const void* UserDataKey() { return &DataType::kUserDataKey; }
// NodeAttachedData implementation:
const void* key() const override { return UserDataKey(); }
const void* GetKey() const override { return UserDataKey(); }
private:
// Uses implicit conversion of the traits to get the appropriate mixin class
......@@ -266,15 +266,11 @@ template <typename NodeType>
DataType*
NodeAttachedDataImpl<DataType>::NodeAttachedDataInMap<NodeType>::GetOrCreate(
const NodeType* node) {
NodeAttachedData* base_data =
NodeAttachedData::GetFromMap(node, DataType::UserDataKey());
if (base_data) {
DCHECK_EQ(DataType::UserDataKey(), base_data->key());
return static_cast<DataType*>(base_data);
}
std::unique_ptr<DataType> data = base::WrapUnique(new DataType(node));
if (auto* data = Get(node))
return data;
std::unique_ptr<DataType> data = std::make_unique<DataType>(node);
DataType* raw_data = data.get();
NodeAttachedData::AttachInMap(node, std::move(data));
NodeAttachedDataMapHelper::AttachInMap(node, std::move(data));
return raw_data;
}
......@@ -283,8 +279,9 @@ template <typename DataType>
template <typename NodeType>
DataType* NodeAttachedDataImpl<DataType>::NodeAttachedDataInMap<NodeType>::Get(
const NodeType* node) {
auto* data = NodeAttachedData::GetFromMap(node, DataType::UserDataKey());
DCHECK(!data || DataType::UserDataKey() == data->key());
auto* data =
NodeAttachedDataMapHelper::GetFromMap(node, DataType::UserDataKey());
DCHECK(!data || DataType::UserDataKey() == data->GetKey());
return static_cast<DataType*>(data);
}
......@@ -294,7 +291,7 @@ template <typename NodeType>
bool NodeAttachedDataImpl<DataType>::NodeAttachedDataInMap<NodeType>::Destroy(
const NodeType* node) {
std::unique_ptr<NodeAttachedData> data =
NodeAttachedData::DetachFromMap(node, DataType::UserDataKey());
NodeAttachedDataMapHelper::DetachFromMap(node, DataType::UserDataKey());
return data.get();
}
......@@ -308,8 +305,8 @@ DataType* NodeAttachedDataImpl<DataType>::NodeAttachedDataOwnedByNodeType<
std::unique_ptr<NodeAttachedData>* storage =
DataType::GetUniquePtrStorage(const_cast<NodeType*>(node));
if (!storage->get())
*storage = base::WrapUnique(new DataType(node));
DCHECK_EQ(DataType::UserDataKey(), storage->get()->key());
*storage = std::make_unique<DataType>(node);
DCHECK_EQ(DataType::UserDataKey(), storage->get()->GetKey());
return static_cast<DataType*>(storage->get());
}
......@@ -322,7 +319,7 @@ NodeAttachedDataImpl<DataType>::NodeAttachedDataOwnedByNodeType<NodeType>::Get(
std::unique_ptr<NodeAttachedData>* storage =
DataType::GetUniquePtrStorage(const_cast<NodeType*>(node));
if (storage->get())
DCHECK_EQ(DataType::UserDataKey(), storage->get()->key());
DCHECK_EQ(DataType::UserDataKey(), storage->get()->GetKey());
return static_cast<DataType*>(storage->get());
}
......@@ -353,7 +350,7 @@ DataType* NodeAttachedDataImpl<DataType>::NodeAttachedDataInternalOnNodeType<
NodeAttachedData* data = new (storage->buffer()) DataType(node);
InternalNodeAttachedDataStorageAccess::Set(storage, data);
}
DCHECK_EQ(DataType::UserDataKey(), storage->Get()->key());
DCHECK_EQ(DataType::UserDataKey(), storage->Get()->GetKey());
return static_cast<DataType*>(storage->Get());
}
......@@ -365,7 +362,7 @@ DataType* NodeAttachedDataImpl<DataType>::NodeAttachedDataInternalOnNodeType<
InternalNodeAttachedDataStorage<sizeof(DataType)>* storage =
DataType::GetInternalStorage(const_cast<NodeType*>(node));
if (storage->Get())
DCHECK_EQ(DataType::UserDataKey(), storage->Get()->key());
DCHECK_EQ(DataType::UserDataKey(), storage->Get()->GetKey());
return static_cast<DataType*>(storage->Get());
}
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/performance_manager/graph/node_attached_data.h"
#include "chrome/browser/performance_manager/public/graph/node_attached_data.h"
#include <utility>
......@@ -92,6 +92,16 @@ class FooData : public NodeAttachedDataImpl<FooData> {
DISALLOW_COPY_AND_ASSIGN(FooData);
};
// An implementation of map-stored user-data using the public interface.
class BarData : public ExternalNodeAttachedDataImpl<BarData> {
public:
explicit BarData(const PageNode* page_node) : page_node_(page_node) {}
~BarData() override = default;
const PageNode* page_node_ = nullptr;
};
} // namespace
class NodeAttachedDataTest : public GraphTestHarness {
......@@ -101,26 +111,26 @@ class NodeAttachedDataTest : public GraphTestHarness {
static void AttachInMap(const NodeBase* node,
std::unique_ptr<NodeAttachedData> data) {
return NodeAttachedData::AttachInMap(node, std::move(data));
return NodeAttachedDataMapHelper::AttachInMap(node, std::move(data));
}
// Retrieves the data associated with the provided |node| and |key|. This
// returns nullptr if no data exists.
static NodeAttachedData* GetFromMap(const NodeBase* node, const void* key) {
return NodeAttachedData::GetFromMap(node, key);
return NodeAttachedDataMapHelper::GetFromMap(node, key);
}
// Detaches the data associated with the provided |node| and |key|. It is
// harmless to call this when no data exists.
static std::unique_ptr<NodeAttachedData> DetachFromMap(const NodeBase* node,
const void* key) {
return NodeAttachedData::DetachFromMap(node, key);
return NodeAttachedDataMapHelper::DetachFromMap(node, key);
}
};
TEST_F(NodeAttachedDataTest, UserDataKey) {
std::unique_ptr<NodeAttachedData> data = std::make_unique<DummyData>();
EXPECT_EQ(data->key(), DummyData::UserDataKey());
EXPECT_EQ(data->GetKey(), DummyData::UserDataKey());
}
TEST_F(NodeAttachedDataTest, RawAttachDetach) {
......@@ -135,19 +145,19 @@ TEST_F(NodeAttachedDataTest, RawAttachDetach) {
// No data yet exists.
EXPECT_EQ(0u, graph()->GetNodeAttachedDataCountForTesting(nullptr, nullptr));
EXPECT_EQ(kNull, GetFromMap(page_node, raw_data->key()));
EXPECT_EQ(kNull, GetFromMap(page_node, raw_data->GetKey()));
// Attach the data and look it up again.
AttachInMap(page_node, std::move(data));
EXPECT_EQ(1u, graph()->GetNodeAttachedDataCountForTesting(nullptr, nullptr));
EXPECT_EQ(raw_base, GetFromMap(page_node, raw_data->key()));
EXPECT_EQ(raw_base, GetFromMap(page_node, raw_data->GetKey()));
// Detach the data.
std::unique_ptr<NodeAttachedData> base_data =
DetachFromMap(page_node, raw_data->key());
DetachFromMap(page_node, raw_data->GetKey());
EXPECT_EQ(0u, graph()->GetNodeAttachedDataCountForTesting(nullptr, nullptr));
EXPECT_EQ(raw_base, base_data.get());
EXPECT_EQ(kNull, GetFromMap(page_node, raw_data->key()));
EXPECT_EQ(kNull, GetFromMap(page_node, raw_data->GetKey()));
}
TEST_F(NodeAttachedDataTest, TypedAttachDetach) {
......@@ -253,4 +263,28 @@ TEST_F(NodeAttachedDataTest, NodeInternalStorage) {
EXPECT_FALSE(FooData::Get(&dummy_node));
}
TEST_F(NodeAttachedDataTest, PublicNodeAttachedData) {
MockSinglePageInSingleProcessGraph mock_graph(graph());
PageNodeImpl* page_node_impl = mock_graph.page.get();
const PageNode* page_node = page_node_impl;
EXPECT_EQ(0u, graph()->GetNodeAttachedDataCountForTesting(nullptr, nullptr));
BarData* bar_data = BarData::Get(page_node);
EXPECT_FALSE(bar_data);
bar_data = BarData::GetOrCreate(page_node);
EXPECT_TRUE(bar_data);
EXPECT_EQ(1u, graph()->GetNodeAttachedDataCountForTesting(nullptr, nullptr));
EXPECT_EQ(1u, graph()->GetNodeAttachedDataCountForTesting(
page_node_impl, bar_data->GetKey()));
EXPECT_EQ(page_node, bar_data->page_node_);
EXPECT_EQ(bar_data, BarData::Get(page_node));
EXPECT_TRUE(BarData::Destroy(page_node));
EXPECT_EQ(0u, graph()->GetNodeAttachedDataCountForTesting(nullptr, nullptr));
EXPECT_FALSE(BarData::Destroy(page_node));
EXPECT_FALSE(BarData::Get(page_node));
}
} // namespace performance_manager
......@@ -14,6 +14,7 @@
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
#include "chrome/browser/performance_manager/graph/graph_impl.h"
#include "chrome/browser/performance_manager/graph/node_type.h"
#include "chrome/browser/performance_manager/graph/properties.h"
#include "chrome/browser/performance_manager/observers/graph_observer.h"
......@@ -24,8 +25,6 @@
namespace performance_manager {
class GraphImpl;
// NodeBase implements shared functionality among different types of graph
// nodes. A specific type of graph node will derive from this class and can
// override shared functionality when needed.
......@@ -81,6 +80,23 @@ class NodeBase {
DISALLOW_COPY_AND_ASSIGN(NodeBase);
};
// Helper for implementing the common bits of |PublicNodeClass|.
template <class NodeImplClass, class PublicNodeClass>
class PublicNodeImpl : public PublicNodeClass {
public:
// Partial implementation of PublicNodeClass:
Graph* GetGraph() const override {
return static_cast<const NodeImplClass*>(this)->graph();
}
const void* GetIndexingKey() const override {
// By contract the indexing key is actually a NodeBase pointer. This allows
// quick and safe casting from a public node type to the corresponding
// internal node type.
return static_cast<const NodeBase*>(
static_cast<const NodeImplClass*>(this));
}
};
template <class NodeImplClass>
class TypedNodeBase : public NodeBase {
public:
......
......@@ -24,7 +24,8 @@ namespace performance_manager {
class FrameNodeImpl;
class ProcessNodeImpl;
class PageNodeImpl : public PageNode, public TypedNodeBase<PageNodeImpl> {
class PageNodeImpl : public PublicNodeImpl<PageNodeImpl, PageNode>,
public TypedNodeBase<PageNodeImpl> {
public:
using LifecycleState = resource_coordinator::mojom::LifecycleState;
......
......@@ -38,6 +38,12 @@ class PageNodeImplTest : public GraphTestHarness {
} // namespace
TEST_F(PageNodeImplTest, GetIndexingKey) {
auto page = CreateNode<PageNodeImpl>();
EXPECT_EQ(page->GetIndexingKey(),
static_cast<const void*>(static_cast<const NodeBase*>(page.get())));
}
TEST_F(PageNodeImplTest, AddFrameBasic) {
auto process_node = CreateNode<ProcessNodeImpl>();
auto page_node = CreateNode<PageNodeImpl>();
......
......@@ -32,7 +32,7 @@ class FrameNodeImpl;
// 3. Process died or falied to start, have exit status.
// 4. Back to 2.
class ProcessNodeImpl
: public ProcessNode,
: public PublicNodeImpl<ProcessNodeImpl, ProcessNode>,
public CoordinationUnitInterface<
ProcessNodeImpl,
resource_coordinator::mojom::ProcessCoordinationUnit,
......
......@@ -19,6 +19,13 @@ class ProcessNodeImplTest : public GraphTestHarness {};
} // namespace
TEST_F(ProcessNodeImplTest, GetIndexingKey) {
auto process = CreateNode<ProcessNodeImpl>();
EXPECT_EQ(
process->GetIndexingKey(),
static_cast<const void*>(static_cast<const NodeBase*>(process.get())));
}
TEST_F(ProcessNodeImplTest, MeasureCPUUsage) {
auto process_node = CreateNode<ProcessNodeImpl>();
process_node->SetCPUUsage(1.0);
......
......@@ -46,7 +46,8 @@ struct ProcessResourceMeasurementBatch {
std::vector<ProcessResourceMeasurement> measurements;
};
class SystemNodeImpl : public SystemNode, public TypedNodeBase<SystemNodeImpl> {
class SystemNodeImpl : public PublicNodeImpl<SystemNodeImpl, SystemNode>,
public TypedNodeBase<SystemNodeImpl> {
public:
static constexpr NodeTypeEnum Type() { return NodeTypeEnum::kSystem; }
......
......@@ -79,6 +79,13 @@ std::unique_ptr<ProcessResourceMeasurementBatch> CreateMeasurementBatch(
} // namespace
TEST_F(SystemNodeImplTest, GetIndexingKey) {
MockMultiplePagesWithMultipleProcessesGraph mock_graph(graph());
auto& sys = mock_graph.system;
EXPECT_EQ(sys->GetIndexingKey(),
static_cast<const void*>(static_cast<const NodeBase*>(sys.get())));
}
TEST_F(SystemNodeImplTest, DistributeMeasurementBatch) {
SystemAndProcessObserver observer;
MockMultiplePagesWithMultipleProcessesGraph mock_graph(graph());
......
......@@ -9,6 +9,8 @@
namespace performance_manager {
class Graph;
// Frame nodes form a tree structure, each FrameNode at most has one parent that
// is a FrameNode. Conceptually, a frame corresponds to a
// content::RenderFrameHost in the browser, and a content::RenderFrameImpl /
......@@ -36,6 +38,13 @@ class FrameNode {
FrameNode();
virtual ~FrameNode();
// Returns the graph to which this node belongs.
virtual Graph* GetGraph() const = 0;
// Returns the private key which is used for indexing this object in the
// graph. This is an opaque pointer strictly used for implementation.
virtual const void* GetIndexingKey() const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(FrameNode);
};
......
// Copyright 2019 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 CHROME_BROWSER_PERFORMANCE_MANAGER_PUBLIC_GRAPH_NODE_ATTACHED_DATA_H_
#define CHROME_BROWSER_PERFORMANCE_MANAGER_PUBLIC_GRAPH_NODE_ATTACHED_DATA_H_
#include <memory>
#include "base/macros.h"
namespace performance_manager {
// NodeAttachedData allows external observers of the graph to store data that is
// associated with a graph node, providing lifetime management as a service.
//
// External (to performance_manager) implementations of NodeAttachedData should
// derive from ExternalNodeAttachedDataImpl. For internal implementations refer
// to NodeAttachedDataImpl and see node_attached_data_impl.h.
class NodeAttachedData {
public:
NodeAttachedData();
virtual ~NodeAttachedData();
// Returns the 'key' associated with this type of NodeAttachedData. This needs
// to be unique per data type or bad things happen.
virtual const void* GetKey() const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(NodeAttachedData);
};
// Implements NodeAttachedData for a given UserDataType.
//
// In order for a UserDataType to be attached to a node of type |NodeType| it
// must have a constructor of the form "UserDataType(const NodeType* node)".
template <typename UserDataType>
class ExternalNodeAttachedDataImpl : public NodeAttachedData {
public:
ExternalNodeAttachedDataImpl() = default;
~ExternalNodeAttachedDataImpl() override = default;
// NodeAttachedData implementation:
const void* GetKey() const override { return &kUserDataKey; }
// Gets the user data for the given |node|, creating it if it doesn't yet
// exist.
template <typename NodeType>
static UserDataType* GetOrCreate(const NodeType* node);
// Gets the user data for the given |node|, returning nullptr if it doesn't
// exist.
template <typename NodeType>
static UserDataType* Get(const NodeType* node);
// Destroys the user data associated with the given node, returning true
// on success or false if the user data did not exist to begin with.
template <typename NodeType>
static bool Destroy(const NodeType* node);
private:
static constexpr int kUserDataKey = 0;
static const void* UserDataKey() { return &kUserDataKey; }
DISALLOW_COPY_AND_ASSIGN(ExternalNodeAttachedDataImpl);
};
} // namespace performance_manager
// This drags in the implementation of ExternalNodeAttachedDataImpl.
#include "chrome/browser/performance_manager/graph/node_attached_data.h"
#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_PUBLIC_GRAPH_NODE_ATTACHED_DATA_H_
......@@ -9,6 +9,8 @@
namespace performance_manager {
class Graph;
// A PageNode represents the root of a FrameTree, or equivalently a WebContents.
// These may correspond to normal tabs, WebViews, Portals, Chrome Apps or
// Extensions.
......@@ -17,6 +19,13 @@ class PageNode {
PageNode();
virtual ~PageNode();
// Returns the graph to which this node belongs.
virtual Graph* GetGraph() const = 0;
// Returns the private key which is used for indexing this object in the
// graph. This is an opaque pointer strictly used for implementation.
virtual const void* GetIndexingKey() const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(PageNode);
};
......
......@@ -9,6 +9,8 @@
namespace performance_manager {
class Graph;
// A process node follows the lifetime of a RenderProcessHost.
// It may reference zero or one processes at a time, but during its lifetime, it
// may reference more than one process. This can happen if the associated
......@@ -24,6 +26,13 @@ class ProcessNode {
ProcessNode();
virtual ~ProcessNode();
// Returns the graph to which this node belongs.
virtual Graph* GetGraph() const = 0;
// Returns the private key which is used for indexing this object in the
// graph. This is an opaque pointer strictly used for implementation.
virtual const void* GetIndexingKey() const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(ProcessNode);
};
......
......@@ -9,6 +9,8 @@
namespace performance_manager {
class Graph;
// The SystemNode represents system-wide state. There is at most one system node
// in a graph.
class SystemNode {
......@@ -16,6 +18,13 @@ class SystemNode {
SystemNode();
virtual ~SystemNode();
// Returns the graph to which this node belongs.
virtual Graph* GetGraph() const = 0;
// Returns the private key which is used for indexing this object in the
// graph. This is an opaque pointer strictly used for implementation.
virtual const void* GetIndexingKey() const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(SystemNode);
};
......
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