freezing_vote_aggregator.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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. #ifndef COMPONENTS_PERFORMANCE_MANAGER_FREEZING_FREEZING_VOTE_AGGREGATOR_H_
  5. #define COMPONENTS_PERFORMANCE_MANAGER_FREEZING_FREEZING_VOTE_AGGREGATOR_H_
  6. #include "base/compiler_specific.h"
  7. #include "base/containers/circular_deque.h"
  8. #include "base/containers/flat_map.h"
  9. #include "components/performance_manager/public/freezing/freezing.h"
  10. #include "components/performance_manager/public/graph/graph_registered.h"
  11. #include "components/performance_manager/public/graph/node_data_describer.h"
  12. #include "components/performance_manager/public/voting/voting.h"
  13. namespace performance_manager {
  14. class FreezingVoteDecorator;
  15. class PageNode;
  16. namespace freezing {
  17. // An aggregator for freezing votes. It upstreams an aggregated vote to an
  18. // upstream channel every time the freezing decision changes for a PageNode. It
  19. // allows freezing of a given PageNode upon reception of one or several
  20. // kCanFreeze vote for this node. Any kCannotFreeze vote received will have
  21. // priority over the kCanFreeze votes and will prevent the PageNode from being
  22. // frozen.
  23. //
  24. // This is a GraphRegistered object, once created this instance can be
  25. // retrieved via:
  26. // graph()->GetRegisteredObjectAs<freezing::FreezingVoteAggregator>();
  27. class FreezingVoteAggregator final
  28. : public FreezingVoteObserver,
  29. public NodeDataDescriberDefaultImpl,
  30. public GraphRegisteredImpl<FreezingVoteAggregator> {
  31. public:
  32. FreezingVoteAggregator(const FreezingVoteAggregator& rhs) = delete;
  33. FreezingVoteAggregator& operator=(const FreezingVoteAggregator& rhs) = delete;
  34. ~FreezingVoteAggregator() override;
  35. // Issues a voting channel (effectively registered a voter).
  36. FreezingVotingChannel GetVotingChannel();
  37. // Sets the upstream voting channel. Should only be called once.
  38. void SetUpstreamVotingChannel(FreezingVotingChannel&& channel);
  39. // FreezingVoteObserver implementation:
  40. void OnVoteSubmitted(FreezingVoterId voter_id,
  41. const PageNode* page_node,
  42. const FreezingVote& vote) override;
  43. void OnVoteChanged(FreezingVoterId voter_id,
  44. const PageNode* page_node,
  45. const FreezingVote& new_vote) override;
  46. void OnVoteInvalidated(FreezingVoterId voter_id,
  47. const PageNode* page_node) override;
  48. void RegisterNodeDataDescriber(Graph* graph);
  49. void UnregisterNodeDataDescriber(Graph* graph);
  50. // NodeDataDescriber implementation:
  51. base::Value DescribePageNodeData(const PageNode* node) const override;
  52. private:
  53. friend class performance_manager::FreezingVoteDecorator;
  54. friend class FreezingVoteAggregatorTest;
  55. friend class FreezingVoteAggregatorTestAccess;
  56. // Private constructor, in practice the FreezingVoteDecorator is responsible
  57. // for maintaining the lifetime of this object.
  58. FreezingVoteAggregator();
  59. // Contains the freezing votes for a given PageNode.
  60. class FreezingVoteData {
  61. public:
  62. // The consequence that adding, removing or updating a vote has on the
  63. // upstreamed vote. The caller is responsible for calling UpstreamVote or
  64. // invalidating the vote (by destroying the instance of this class that owns
  65. // it).
  66. enum class UpstreamVoteImpact {
  67. // The upstream vote has changed. UpstreamVote should be called.
  68. kUpstreamVoteChanged,
  69. // The upstream vote has been removed and should be invalidated.
  70. kUpstreamVoteRemoved,
  71. // The operation had no impact on the upstreamed vote.
  72. kUpstreamVoteUnchanged,
  73. };
  74. FreezingVoteData();
  75. FreezingVoteData(FreezingVoteData&&);
  76. FreezingVoteData& operator=(FreezingVoteData&&);
  77. FreezingVoteData(const FreezingVoteData& rhs) = delete;
  78. FreezingVoteData& operator=(const FreezingVoteData& rhs) = delete;
  79. ~FreezingVoteData();
  80. // Adds a new vote.
  81. void AddVote(FreezingVoterId voter_id, const FreezingVote& vote);
  82. // Updates an existing vote.
  83. void UpdateVote(FreezingVoterId voter_id, const FreezingVote& new_vote);
  84. // Removes an existing vote
  85. void RemoveVote(FreezingVoterId voter_id);
  86. // Upstreams the vote for this vote data, using the given voting |channel|.
  87. void UpstreamVote(const PageNode* page_node,
  88. FreezingVotingChannel* channel);
  89. bool IsEmpty() { return votes_.empty(); }
  90. // Returns the chosen vote. Invalid to call if IsEmpty() is true.
  91. const FreezingVote& GetChosenVote();
  92. // Helper for FreezingVoteAggregator::DescribePageNodeData.
  93. void DescribeVotes(base::Value* ret) const;
  94. private:
  95. friend class FreezingVoteAggregatorTestAccess;
  96. // The current set of votes.
  97. using VotesDeque =
  98. base::circular_deque<std::pair<FreezingVoterId, FreezingVote>>;
  99. const VotesDeque& GetVotesForTesting() { return votes_; }
  100. // Returns the iterator of |voter_id| in |votes_|. |voter_id| is expected
  101. // to be in the deque, this is enforced by a DCHECK.
  102. VotesDeque::iterator FindVote(FreezingVoterId voter_id);
  103. void AddVoteToDeque(FreezingVoterId voter_id, const FreezingVote& vote);
  104. // kCannotFreeze votes are always at the beginning of the deque.
  105. VotesDeque votes_;
  106. };
  107. using VoteDataMap = base::flat_map<const PageNode*, FreezingVoteData>;
  108. // Looks up the VoteData associated with the provided |page_node|. The data is
  109. // expected to already exist (enforced by a DCHECK).
  110. VoteDataMap::iterator GetVoteData(const PageNode* page_node);
  111. // A map that associates a PageNode with a FreezingVoteData structure.
  112. VoteDataMap vote_data_map_;
  113. // The channel for upstreaming our votes.
  114. FreezingVotingChannel channel_;
  115. // Provides FreezingVotingChannels to our input voters.
  116. FreezingVotingChannelFactory freezing_voting_channel_factory_{this};
  117. };
  118. } // namespace freezing
  119. } // namespace performance_manager
  120. #endif // COMPONENTS_PERFORMANCE_MANAGER_FREEZING_FREEZING_VOTE_AGGREGATOR_H_