Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(102)

Side by Side Diff: gpu/command_buffer/common/id_allocator.cc

Issue 692073002: command_buffer: Implement IdAllocator by recording ranges (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@new-05-path-fragment-input-gen
Patch Set: rebase Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // This file contains the implementation of IdAllocator. 5 // This file contains the implementation of IdAllocator.
6 6
7 #include "gpu/command_buffer/common/id_allocator.h" 7 #include "gpu/command_buffer/common/id_allocator.h"
8 8
9 #include <limits>
9 #include "base/logging.h" 10 #include "base/logging.h"
10 11
11 namespace gpu { 12 namespace gpu {
12 13
13 IdAllocator::IdAllocator() {} 14 IdAllocator::IdAllocator() {
15 COMPILE_ASSERT(kInvalidResource == 0u, invalid_resource_is_not_zero);
16 // Simplify the code by making sure that lower_bound(id) never
17 // returns the beginning of the map, if id is valid (eg !=
18 // kInvalidResource).
19 used_ids_.insert(std::make_pair(0u, 0u));
20 }
14 21
15 IdAllocator::~IdAllocator() {} 22 IdAllocator::~IdAllocator() {}
16 23
17 ResourceId IdAllocator::AllocateID() { 24 ResourceId IdAllocator::AllocateID() {
18 ResourceId id; 25 return AllocateIDRange(1u);
19 ResourceIdSet::iterator iter = free_ids_.begin(); 26 }
20 if (iter != free_ids_.end()) { 27
21 id = *iter; 28 ResourceId IdAllocator::AllocateIDAtOrAbove(ResourceId desired_id) {
29 DCHECK(desired_id > 0u);
David Yen 2015/02/04 22:57:16 Nit: Even though 0 is a invalid ID, seems like it
Kimmo Kinnunen 2015/02/05 08:29:33 Done.
30 if (desired_id == 1u) {
31 return AllocateIDRange(1u);
32 }
33
34 ResourceIdRangeMap::iterator current = used_ids_.lower_bound(desired_id);
35 ResourceIdRangeMap::iterator next = current;
36 if (current == used_ids_.end() || current->first > desired_id) {
37 current--;
22 } else { 38 } else {
23 id = LastUsedId() + 1; 39 next++;
24 if (!id) { 40 }
25 // We wrapped around to 0. 41
26 id = FindFirstUnusedId(); 42 ResourceId first_id = current->first;
27 } 43 ResourceId last_id = current->second;
28 } 44
29 MarkAsUsed(id); 45 DCHECK(desired_id >= first_id);
30 return id; 46
31 } 47 if (desired_id - 1u <= last_id) {
32 48 // Append to current range.
33 ResourceId IdAllocator::AllocateIDAtOrAbove(ResourceId desired_id) { 49 last_id++;
34 ResourceId id; 50 if (last_id == 0) {
35 ResourceIdSet::iterator iter = free_ids_.lower_bound(desired_id); 51 // The increment overflowed.
36 if (iter != free_ids_.end()) { 52 return AllocateIDRange(1u);
37 id = *iter; 53 }
38 } else if (LastUsedId() < desired_id) { 54
39 id = desired_id; 55 current->second = last_id;
40 } else { 56
41 id = LastUsedId() + 1; 57 if (next != used_ids_.end() && next->first - 1u == last_id) {
42 if (!id) { 58 // Merge with next range.
43 // We wrapped around to 0. 59 current->second = next->second;
44 id = FindFirstUnusedId(); 60 used_ids_.erase(next);
45 } 61 }
46 } 62 return last_id;
47 MarkAsUsed(id); 63 } else if (next != used_ids_.end() && next->first - 1u == desired_id) {
48 return id; 64 // Prepend to next range.
65 ResourceId last_existing_id = next->second;
66 used_ids_.erase(next);
67 used_ids_.insert(std::make_pair(desired_id, last_existing_id));
68 return desired_id;
69 }
70 used_ids_.insert(std::make_pair(desired_id, desired_id));
71 return desired_id;
72 }
73
74 ResourceId IdAllocator::AllocateIDRange(uint32_t range) {
75 DCHECK(range > 0u);
76
77 ResourceIdRangeMap::iterator current = used_ids_.begin();
78 ResourceIdRangeMap::iterator next = current;
79
80 while (++next != used_ids_.end()) {
81 if (next->first - current->second > range) {
82 break;
83 }
84 current = next;
85 }
86
87 ResourceId first_id = current->second + 1u;
88 ResourceId last_id = first_id + range - 1u;
89
90 if (first_id == 0u || last_id < first_id) {
91 return kInvalidResource;
92 }
93
94 current->second = last_id;
95
96 if (next != used_ids_.end() && next->first - 1u == last_id) {
97 // Merge with next range.
98 current->second = next->second;
99 used_ids_.erase(next);
100 }
101
102 return first_id;
49 } 103 }
50 104
51 bool IdAllocator::MarkAsUsed(ResourceId id) { 105 bool IdAllocator::MarkAsUsed(ResourceId id) {
52 DCHECK(id); 106 DCHECK(id);
53 free_ids_.erase(id); 107 ResourceIdRangeMap::iterator current = used_ids_.lower_bound(id);
54 std::pair<ResourceIdSet::iterator, bool> result = used_ids_.insert(id); 108 if (current != used_ids_.end() && current->first == id) {
55 return result.second; 109 return false;
110 }
111
112 ResourceIdRangeMap::iterator next = current;
113 --current;
114
115 if (current->second >= id) {
116 return false;
117 }
118
119 DCHECK(current->first < id && current->second < id);
120
121 if (current->second + 1u == id) {
122 // Append to current range.
123 current->second = id;
124 if (next != used_ids_.end() && next->first - 1u == id) {
125 // Merge with next range.
126 current->second = next->second;
127 used_ids_.erase(next);
128 }
129 return true;
130 } else if (next != used_ids_.end() && next->first - 1u == id) {
131 // Prepend to next range.
132 ResourceId last_existing_id = next->second;
133 used_ids_.erase(next);
134 used_ids_.insert(std::make_pair(id, last_existing_id));
135 return true;
136 }
137
138 used_ids_.insert(std::make_pair(id, id));
139 return true;
56 } 140 }
57 141
58 void IdAllocator::FreeID(ResourceId id) { 142 void IdAllocator::FreeID(ResourceId id) {
59 if (id) { 143 if (id) {
David Yen 2015/02/04 22:57:16 Nit: This check no longer seems necessary.
Kimmo Kinnunen 2015/02/05 08:29:33 Done.
60 used_ids_.erase(id); 144 FreeIDRange(id, 1u);
61 free_ids_.insert(id); 145 }
146 }
147
148 void IdAllocator::FreeIDRange(ResourceId first_id, uint32 range) {
149 COMPILE_ASSERT(kInvalidResource == 0u, invalid_resource_is_not_zero);
150
151 if (range == 0u || (first_id == 0u && range == 1u)) {
152 return;
153 }
154
155 if (first_id == 0u) {
156 first_id++;
157 range--;
158 }
159
160 ResourceId last_id = first_id + range - 1u;
161 if (last_id < first_id) {
162 last_id = std::numeric_limits<ResourceId>::max();
163 }
164
165 while (true) {
166 ResourceIdRangeMap::iterator current = used_ids_.lower_bound(last_id);
167 if (current == used_ids_.end() || current->first > last_id) {
168 --current;
169 }
170
171 if (current->second < first_id) {
172 return;
173 }
174
175 if (current->first >= first_id) {
176 ResourceId last_existing_id = current->second;
177 used_ids_.erase(current);
178 if (last_id < last_existing_id) {
179 used_ids_.insert(std::make_pair(last_id + 1u, last_existing_id));
180 }
181 } else if (current->second <= last_id) {
182 current->second = first_id - 1u;
183 } else {
184 DCHECK(current->first < first_id && current->second > last_id);
185 ResourceId last_existing_id = current->second;
186 current->second = first_id - 1u;
187 used_ids_.insert(std::make_pair(last_id + 1u, last_existing_id));
188 }
62 } 189 }
63 } 190 }
64 191
65 bool IdAllocator::InUse(ResourceId id) const { 192 bool IdAllocator::InUse(ResourceId id) const {
66 return id == kInvalidResource || used_ids_.find(id) != used_ids_.end(); 193 DCHECK(id);
vmiura 2015/02/04 07:32:56 Should we return true if (id == kInvalidResource)
Kimmo Kinnunen 2015/02/04 08:13:08 Whichever way you want.. The suggestion breaks th
Kimmo Kinnunen 2015/02/05 08:29:33 So I now changed the assert into if(). However, th
67 } 194
68 195 ResourceIdRangeMap::const_iterator current = used_ids_.lower_bound(id);
69 ResourceId IdAllocator::LastUsedId() const { 196 if (current != used_ids_.end()) {
70 if (used_ids_.empty()) { 197 if (current->first == id) {
71 return 0u; 198 return true;
72 } else { 199 }
73 return *used_ids_.rbegin(); 200 }
74 } 201
75 } 202 --current;
76 203 return current->second >= id;
77 ResourceId IdAllocator::FindFirstUnusedId() const {
78 ResourceId id = 1;
79 for (ResourceIdSet::const_iterator it = used_ids_.begin();
80 it != used_ids_.end(); ++it) {
81 if ((*it) != id) {
82 return id;
83 }
84 ++id;
85 }
86 return id;
87 } 204 }
88 205
89 } // namespace gpu 206 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/command_buffer/common/id_allocator.h ('k') | gpu/command_buffer/common/id_allocator_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698