max_vote_aggregator.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Copyright 2019 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/max_vote_aggregator.h"
  5. #include <algorithm>
  6. #include <tuple>
  7. namespace performance_manager {
  8. namespace execution_context_priority {
  9. MaxVoteAggregator::MaxVoteAggregator() = default;
  10. MaxVoteAggregator::~MaxVoteAggregator() = default;
  11. VotingChannel MaxVoteAggregator::GetVotingChannel() {
  12. return voting_channel_factory_.BuildVotingChannel();
  13. }
  14. void MaxVoteAggregator::SetUpstreamVotingChannel(VotingChannel channel) {
  15. channel_ = std::move(channel);
  16. }
  17. void MaxVoteAggregator::OnVoteSubmitted(
  18. VoterId voter_id,
  19. const ExecutionContext* execution_context,
  20. const Vote& vote) {
  21. DCHECK(channel_.IsValid());
  22. // Create the VoteData for this execution context, if necessary.
  23. VoteData& vote_data = vote_data_map_[execution_context];
  24. // Remember the previous top vote before adding the new vote. There could be
  25. // none if this is the first vote submitted for |execution_context|.
  26. absl::optional<Vote> old_top_vote;
  27. if (!vote_data.IsEmpty())
  28. old_top_vote = vote_data.GetTopVote();
  29. vote_data.AddVote(voter_id, vote, next_vote_id_++);
  30. // If there was no previous top vote, the vote must be submitted.
  31. if (!old_top_vote) {
  32. channel_.SubmitVote(execution_context, vote);
  33. return;
  34. }
  35. // Since there is a previous top vote, it must be modified if the top vote
  36. // changed.
  37. const Vote new_top_vote = vote_data.GetTopVote();
  38. if (old_top_vote.value() != new_top_vote)
  39. channel_.ChangeVote(execution_context, new_top_vote);
  40. }
  41. void MaxVoteAggregator::OnVoteChanged(VoterId voter_id,
  42. const ExecutionContext* execution_context,
  43. const Vote& new_vote) {
  44. // The VoteData for this execution context is guaranteed to exist.
  45. VoteData& vote_data = GetVoteData(execution_context)->second;
  46. // Remember the previous top vote before updating the vote for this
  47. // |voter_id|.
  48. const Vote old_top_vote = vote_data.GetTopVote();
  49. vote_data.UpdateVote(voter_id, new_vote);
  50. // If the top vote changed, the upstream vote must also be changed.
  51. const Vote new_top_vote = vote_data.GetTopVote();
  52. if (old_top_vote != new_top_vote)
  53. channel_.ChangeVote(execution_context, new_top_vote);
  54. }
  55. void MaxVoteAggregator::OnVoteInvalidated(
  56. VoterId voter_id,
  57. const ExecutionContext* execution_context) {
  58. // The VoteData for this execution context is guaranteed to exist.
  59. auto it = GetVoteData(execution_context);
  60. VoteData& vote_data = it->second;
  61. // Remember the previous top vote before removing the vote for this
  62. // |voter_id|.
  63. const Vote old_top_vote = vote_data.GetTopVote();
  64. vote_data.RemoveVote(voter_id);
  65. // In case the last vote for |execution_context| was invalidated, the upstream
  66. // vote must also be invalidated.
  67. if (vote_data.IsEmpty()) {
  68. channel_.InvalidateVote(execution_context);
  69. // Clean up the VoteData for |execution_context| since it is empty.
  70. vote_data_map_.erase(it);
  71. return;
  72. }
  73. // If the top vote changed, the upstream vote must also be changed.
  74. const Vote new_top_vote = vote_data.GetTopVote();
  75. if (old_top_vote != new_top_vote)
  76. channel_.ChangeVote(execution_context, new_top_vote);
  77. }
  78. MaxVoteAggregator::StampedVote::StampedVote() = default;
  79. MaxVoteAggregator::StampedVote::StampedVote(const Vote& vote, uint32_t vote_id)
  80. : vote_(vote), vote_id_(vote_id) {}
  81. MaxVoteAggregator::StampedVote::StampedVote(StampedVote&&) = default;
  82. MaxVoteAggregator::StampedVote::~StampedVote() = default;
  83. MaxVoteAggregator::VoteDataMap::iterator MaxVoteAggregator::GetVoteData(
  84. const ExecutionContext* execution_context) {
  85. auto it = vote_data_map_.find(execution_context);
  86. DCHECK(it != vote_data_map_.end());
  87. return it;
  88. }
  89. MaxVoteAggregator::VoteData::VoteData() = default;
  90. MaxVoteAggregator::VoteData::VoteData(VoteData&& rhs) = default;
  91. MaxVoteAggregator::VoteData& MaxVoteAggregator::VoteData::operator=(
  92. VoteData&& rhs) = default;
  93. MaxVoteAggregator::VoteData::~VoteData() = default;
  94. void MaxVoteAggregator::VoteData::AddVote(VoterId voter_id,
  95. const Vote& vote,
  96. uint32_t vote_id) {
  97. auto it = votes_.emplace(vote, vote_id);
  98. bool inserted = heap_handles_.emplace(voter_id, it->handle()).second;
  99. DCHECK(inserted);
  100. }
  101. void MaxVoteAggregator::VoteData::UpdateVote(VoterId voter_id,
  102. const Vote& new_vote) {
  103. auto it = heap_handles_.find(voter_id);
  104. DCHECK(it != heap_handles_.end());
  105. base::HeapHandle* heap_handle = it->second;
  106. votes_.Modify(*heap_handle, [&new_vote](StampedVote& element) {
  107. element.SetVote(new_vote);
  108. });
  109. }
  110. void MaxVoteAggregator::VoteData::RemoveVote(VoterId voter_id) {
  111. auto it = heap_handles_.find(voter_id);
  112. DCHECK(it != heap_handles_.end());
  113. base::HeapHandle* heap_handle = it->second;
  114. heap_handles_.erase(it);
  115. votes_.erase(*heap_handle);
  116. }
  117. const Vote& MaxVoteAggregator::VoteData::GetTopVote() const {
  118. return votes_.top().vote();
  119. }
  120. } // namespace execution_context_priority
  121. } // namespace performance_manager