| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 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 | |
| 5 #include "net/spdy/http2_priority_dependencies.h" | |
| 6 #include "net/spdy/platform/api/spdy_estimate_memory_usage.h" | |
| 7 | |
| 8 namespace net { | |
| 9 | |
| 10 Http2PriorityDependencies::Http2PriorityDependencies() {} | |
| 11 | |
| 12 Http2PriorityDependencies::~Http2PriorityDependencies() {} | |
| 13 | |
| 14 void Http2PriorityDependencies::OnStreamCreation( | |
| 15 SpdyStreamId id, | |
| 16 SpdyPriority priority, | |
| 17 SpdyStreamId* dependent_stream_id, | |
| 18 bool* exclusive) { | |
| 19 DCHECK(entry_by_stream_id_.find(id) == entry_by_stream_id_.end()); | |
| 20 | |
| 21 *dependent_stream_id = 0ul; | |
| 22 *exclusive = true; | |
| 23 | |
| 24 // Dependent on the lowest-priority stream that has a priority >= |priority|. | |
| 25 IdList::iterator parent; | |
| 26 if (PriorityLowerBound(priority, &parent)) { | |
| 27 *dependent_stream_id = parent->first; | |
| 28 } | |
| 29 | |
| 30 id_priority_lists_[priority].push_back(std::make_pair(id, priority)); | |
| 31 IdList::iterator it = id_priority_lists_[priority].end(); | |
| 32 --it; | |
| 33 entry_by_stream_id_[id] = it; | |
| 34 } | |
| 35 | |
| 36 bool Http2PriorityDependencies::PriorityLowerBound(SpdyPriority priority, | |
| 37 IdList::iterator* bound) { | |
| 38 for (int i = priority; i >= kV3HighestPriority; --i) { | |
| 39 if (!id_priority_lists_[i].empty()) { | |
| 40 *bound = id_priority_lists_[i].end(); | |
| 41 --(*bound); | |
| 42 return true; | |
| 43 } | |
| 44 } | |
| 45 return false; | |
| 46 } | |
| 47 | |
| 48 bool Http2PriorityDependencies::ParentOfStream(SpdyStreamId id, | |
| 49 IdList::iterator* parent) { | |
| 50 EntryMap::iterator entry = entry_by_stream_id_.find(id); | |
| 51 DCHECK(entry != entry_by_stream_id_.end()); | |
| 52 | |
| 53 SpdyPriority priority = entry->second->second; | |
| 54 IdList::iterator curr = entry->second; | |
| 55 if (curr != id_priority_lists_[priority].begin()) { | |
| 56 *parent = curr; | |
| 57 --(*parent); | |
| 58 return true; | |
| 59 } | |
| 60 | |
| 61 // |id| is at the head of its priority list, so its parent is the last | |
| 62 // entry of the next-highest priority band. | |
| 63 if (priority == kV3HighestPriority) { | |
| 64 return false; | |
| 65 } | |
| 66 return PriorityLowerBound(priority - 1, parent); | |
| 67 } | |
| 68 | |
| 69 bool Http2PriorityDependencies::ChildOfStream(SpdyStreamId id, | |
| 70 IdList::iterator* child) { | |
| 71 EntryMap::iterator entry = entry_by_stream_id_.find(id); | |
| 72 DCHECK(entry != entry_by_stream_id_.end()); | |
| 73 | |
| 74 SpdyPriority priority = entry->second->second; | |
| 75 *child = entry->second; | |
| 76 ++(*child); | |
| 77 if (*child != id_priority_lists_[priority].end()) { | |
| 78 return true; | |
| 79 } | |
| 80 | |
| 81 // |id| is at the end of its priority list, so its child is the stream | |
| 82 // at the front of the next-lowest priority band. | |
| 83 for (int i = priority + 1; i <= kV3LowestPriority; ++i) { | |
| 84 if (!id_priority_lists_[i].empty()) { | |
| 85 *child = id_priority_lists_[i].begin(); | |
| 86 return true; | |
| 87 } | |
| 88 } | |
| 89 | |
| 90 return false; | |
| 91 } | |
| 92 | |
| 93 std::vector<Http2PriorityDependencies::DependencyUpdate> | |
| 94 Http2PriorityDependencies::OnStreamUpdate(SpdyStreamId id, | |
| 95 SpdyPriority new_priority) { | |
| 96 std::vector<DependencyUpdate> result; | |
| 97 result.reserve(2); | |
| 98 | |
| 99 EntryMap::iterator curr_entry = entry_by_stream_id_.find(id); | |
| 100 SpdyPriority old_priority = curr_entry->second->second; | |
| 101 if (old_priority == new_priority) { | |
| 102 return result; | |
| 103 } | |
| 104 | |
| 105 IdList::iterator old_parent; | |
| 106 bool old_has_parent = ParentOfStream(id, &old_parent); | |
| 107 | |
| 108 IdList::iterator new_parent; | |
| 109 bool new_has_parent = PriorityLowerBound(new_priority, &new_parent); | |
| 110 | |
| 111 // If we move |id| from MEDIUM to LOW, where HIGH = {other_id}, MEDIUM = {id}, | |
| 112 // and LOW = {}, then PriorityLowerBound(new_priority) is |id|. In this corner | |
| 113 // case, |id| does not change parents. | |
| 114 if (new_has_parent && new_parent->first == id) { | |
| 115 new_has_parent = old_has_parent; | |
| 116 new_parent = old_parent; | |
| 117 } | |
| 118 | |
| 119 // If the parent has changed, we generate dependency updates. | |
| 120 if ((old_has_parent != new_has_parent) || | |
| 121 (old_has_parent && old_parent->first != new_parent->first)) { | |
| 122 // If |id| has a child, then that child moves to be dependent on | |
| 123 // |old_parent|. | |
| 124 IdList::iterator old_child; | |
| 125 if (ChildOfStream(id, &old_child)) { | |
| 126 if (old_has_parent) { | |
| 127 result.push_back({old_child->first, old_parent->first, true}); | |
| 128 } else { | |
| 129 result.push_back({old_child->first, 0, true}); | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 // |id| moves to be dependent on |new_parent|. | |
| 134 if (new_has_parent) { | |
| 135 result.push_back({id, new_parent->first, true}); | |
| 136 } else { | |
| 137 result.push_back({id, 0, true}); | |
| 138 } | |
| 139 } | |
| 140 | |
| 141 // Move to the new priority. | |
| 142 EntryMap::iterator old = entry_by_stream_id_.find(id); | |
| 143 id_priority_lists_[old->second->second].erase(old->second); | |
| 144 id_priority_lists_[new_priority].push_back(std::make_pair(id, new_priority)); | |
| 145 IdList::iterator it = id_priority_lists_[new_priority].end(); | |
| 146 --it; | |
| 147 entry_by_stream_id_[id] = it; | |
| 148 | |
| 149 return result; | |
| 150 } | |
| 151 | |
| 152 void Http2PriorityDependencies::OnStreamDestruction(SpdyStreamId id) { | |
| 153 EntryMap::iterator emit = entry_by_stream_id_.find(id); | |
| 154 DCHECK(emit != entry_by_stream_id_.end()); | |
| 155 | |
| 156 IdList::iterator it = emit->second; | |
| 157 id_priority_lists_[it->second].erase(it); | |
| 158 entry_by_stream_id_.erase(emit); | |
| 159 } | |
| 160 | |
| 161 size_t Http2PriorityDependencies::EstimateMemoryUsage() const { | |
| 162 return SpdyEstimateMemoryUsage(id_priority_lists_); | |
| 163 // TODO(xunjieli): https://crbug.com/690015. Include |entry_by_stream_id_| | |
| 164 // when memory_usage_estimator.h supports std::list::iterator. | |
| 165 } | |
| 166 | |
| 167 } // namespace net | |
| OLD | NEW |