inherit_client_priority_voter.cc 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/performance_manager/execution_context_priority/inherit_client_priority_voter.h"
  5. #include <utility>
  6. #include "base/auto_reset.h"
  7. #include "components/performance_manager/public/execution_context/execution_context.h"
  8. #include "components/performance_manager/public/execution_context/execution_context_registry.h"
  9. #include "components/performance_manager/public/graph/graph.h"
  10. namespace performance_manager {
  11. namespace execution_context_priority {
  12. namespace {
  13. const execution_context::ExecutionContext* GetExecutionContext(
  14. const FrameNode* frame_node) {
  15. return execution_context::ExecutionContextRegistry::GetFromGraph(
  16. frame_node->GetGraph())
  17. ->GetExecutionContextForFrameNode(frame_node);
  18. }
  19. const execution_context::ExecutionContext* GetExecutionContext(
  20. const WorkerNode* worker_node) {
  21. return execution_context::ExecutionContextRegistry::GetFromGraph(
  22. worker_node->GetGraph())
  23. ->GetExecutionContextForWorkerNode(worker_node);
  24. }
  25. } // namespace
  26. // InheritClientPriorityVoter ------------------------------------------
  27. // static
  28. const char InheritClientPriorityVoter::kPriorityInheritedReason[] =
  29. "Priority inherited.";
  30. InheritClientPriorityVoter::InheritClientPriorityVoter() = default;
  31. InheritClientPriorityVoter::~InheritClientPriorityVoter() = default;
  32. void InheritClientPriorityVoter::SetVotingChannel(
  33. VotingChannel voting_channel) {
  34. DCHECK(voting_channel.IsValid());
  35. max_vote_aggregator_.SetUpstreamVotingChannel(std::move(voting_channel));
  36. }
  37. void InheritClientPriorityVoter::OnFrameNodeAdded(const FrameNode* frame_node) {
  38. bool inserted = voting_channels_
  39. .emplace(GetExecutionContext(frame_node),
  40. max_vote_aggregator_.GetVotingChannel())
  41. .second;
  42. DCHECK(inserted);
  43. DCHECK(frame_node->GetChildWorkerNodes().empty());
  44. }
  45. void InheritClientPriorityVoter::OnBeforeFrameNodeRemoved(
  46. const FrameNode* frame_node) {
  47. DCHECK(frame_node->GetChildWorkerNodes().empty());
  48. size_t removed = voting_channels_.erase(GetExecutionContext(frame_node));
  49. DCHECK_EQ(removed, 1u);
  50. }
  51. void InheritClientPriorityVoter::OnPriorityAndReasonChanged(
  52. const FrameNode* frame_node,
  53. const PriorityAndReason& previous_value) {
  54. // The priority of a frame changed. All its children must inherit the new
  55. // priority.
  56. auto it = voting_channels_.find(GetExecutionContext(frame_node));
  57. // Unknown |frame_node|. Just ignore it until we get notified of its existence
  58. // via OnFrameNodeAdded(). This can happen because another voter received the
  59. // OnFrameNodeAdded() call first and thus was able to change its priority very
  60. // early.
  61. if (it == voting_channels_.end())
  62. return;
  63. auto& voting_channel = it->second;
  64. const Vote inherited_vote(frame_node->GetPriorityAndReason().priority(),
  65. kPriorityInheritedReason);
  66. for (const WorkerNode* child_worker_node :
  67. frame_node->GetChildWorkerNodes()) {
  68. const ExecutionContext* child_execution_context =
  69. GetExecutionContext(child_worker_node);
  70. voting_channel.ChangeVote(child_execution_context, inherited_vote);
  71. }
  72. }
  73. void InheritClientPriorityVoter::OnWorkerNodeAdded(
  74. const WorkerNode* worker_node) {
  75. bool inserted = voting_channels_
  76. .emplace(GetExecutionContext(worker_node),
  77. max_vote_aggregator_.GetVotingChannel())
  78. .second;
  79. DCHECK(inserted);
  80. DCHECK(worker_node->GetChildWorkers().empty());
  81. }
  82. void InheritClientPriorityVoter::OnBeforeWorkerNodeRemoved(
  83. const WorkerNode* worker_node) {
  84. DCHECK(worker_node->GetChildWorkers().empty());
  85. size_t removed = voting_channels_.erase(GetExecutionContext(worker_node));
  86. DCHECK_EQ(removed, 1u);
  87. }
  88. void InheritClientPriorityVoter::OnClientFrameAdded(
  89. const WorkerNode* worker_node,
  90. const FrameNode* client_frame_node) {
  91. // |worker_node| is now the child of |client_frame_node|. It must inherit its
  92. // priority.
  93. // Get the voting channel for the client.
  94. auto it = voting_channels_.find(GetExecutionContext(client_frame_node));
  95. DCHECK(it != voting_channels_.end());
  96. auto* voting_channel = &it->second;
  97. const Vote inherited_vote(
  98. client_frame_node->GetPriorityAndReason().priority(),
  99. kPriorityInheritedReason);
  100. voting_channel->SubmitVote(GetExecutionContext(worker_node), inherited_vote);
  101. }
  102. void InheritClientPriorityVoter::OnBeforeClientFrameRemoved(
  103. const WorkerNode* worker_node,
  104. const FrameNode* client_frame_node) {
  105. // |worker_node| is no longer the child of |client_frame_node|. The inherited
  106. // vote must be invalidated.
  107. // Get the voting channel for the client.
  108. auto it = voting_channels_.find(GetExecutionContext(client_frame_node));
  109. DCHECK(it != voting_channels_.end());
  110. auto* voting_channel = &it->second;
  111. voting_channel->InvalidateVote(GetExecutionContext(worker_node));
  112. }
  113. void InheritClientPriorityVoter::OnClientWorkerAdded(
  114. const WorkerNode* worker_node,
  115. const WorkerNode* client_worker_node) {
  116. // |worker_node| is now the child of |client_worker_node|. It must inherit its
  117. // priority.
  118. // Get the voting channel for the client.
  119. auto it = voting_channels_.find(GetExecutionContext(client_worker_node));
  120. DCHECK(it != voting_channels_.end());
  121. auto* voting_channel = &it->second;
  122. const Vote inherited_vote(
  123. client_worker_node->GetPriorityAndReason().priority(),
  124. kPriorityInheritedReason);
  125. voting_channel->SubmitVote(GetExecutionContext(worker_node), inherited_vote);
  126. }
  127. void InheritClientPriorityVoter::OnBeforeClientWorkerRemoved(
  128. const WorkerNode* worker_node,
  129. const WorkerNode* client_worker_node) {
  130. // |worker_node| is no longer the child of |client_worker_node|. The inherited
  131. // vote must be invalidated.
  132. // Get the voting channel for the client.
  133. auto it = voting_channels_.find(GetExecutionContext(client_worker_node));
  134. DCHECK(it != voting_channels_.end());
  135. auto* voting_channel = &it->second;
  136. voting_channel->InvalidateVote(GetExecutionContext(worker_node));
  137. }
  138. void InheritClientPriorityVoter::OnPriorityAndReasonChanged(
  139. const WorkerNode* worker_node,
  140. const PriorityAndReason& previous_value) {
  141. // The priority of a worker changed. All its children must inherit the new
  142. // priority.
  143. auto it = voting_channels_.find(GetExecutionContext(worker_node));
  144. // Unknown |worker_node|. Just ignore it until we get notified of its
  145. // existence via OnWorkerNodeAdded().
  146. if (it == voting_channels_.end())
  147. return;
  148. auto& voting_channel = it->second;
  149. const Vote inherited_vote(worker_node->GetPriorityAndReason().priority(),
  150. kPriorityInheritedReason);
  151. for (const WorkerNode* child_worker_node : worker_node->GetChildWorkers()) {
  152. const ExecutionContext* child_execution_context =
  153. GetExecutionContext(child_worker_node);
  154. voting_channel.ChangeVote(child_execution_context, inherited_vote);
  155. }
  156. }
  157. } // namespace execution_context_priority
  158. } // namespace performance_manager