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
3 // found in the LICENSE file.
5 // This file contains the implementation of IdAllocator.
7 #include "gpu/command_buffer/common/id_allocator.h"
10 #include "base/logging.h"
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 !=
19 used_ids_
.insert(std::make_pair(0u, 0u));
22 IdAllocator::~IdAllocator() {}
24 ResourceId
IdAllocator::AllocateID() {
25 return AllocateIDRange(1u);
28 ResourceId
IdAllocator::AllocateIDAtOrAbove(ResourceId desired_id
) {
29 if (desired_id
== 0u || desired_id
== 1u) {
30 return AllocateIDRange(1u);
33 ResourceIdRangeMap::iterator current
= used_ids_
.lower_bound(desired_id
);
34 ResourceIdRangeMap::iterator next
= current
;
35 if (current
== used_ids_
.end() || current
->first
> desired_id
) {
41 ResourceId first_id
= current
->first
;
42 ResourceId last_id
= current
->second
;
44 DCHECK(desired_id
>= first_id
);
46 if (desired_id
- 1u <= last_id
) {
47 // Append to current range.
50 // The increment overflowed.
51 return AllocateIDRange(1u);
54 current
->second
= last_id
;
56 if (next
!= used_ids_
.end() && next
->first
- 1u == last_id
) {
57 // Merge with next range.
58 current
->second
= next
->second
;
59 used_ids_
.erase(next
);
62 } else if (next
!= used_ids_
.end() && next
->first
- 1u == desired_id
) {
63 // Prepend to next range.
64 ResourceId last_existing_id
= next
->second
;
65 used_ids_
.erase(next
);
66 used_ids_
.insert(std::make_pair(desired_id
, last_existing_id
));
69 used_ids_
.insert(std::make_pair(desired_id
, desired_id
));
73 ResourceId
IdAllocator::AllocateIDRange(uint32_t range
) {
76 ResourceIdRangeMap::iterator current
= used_ids_
.begin();
77 ResourceIdRangeMap::iterator next
= current
;
79 while (++next
!= used_ids_
.end()) {
80 if (next
->first
- current
->second
> range
) {
86 ResourceId first_id
= current
->second
+ 1u;
87 ResourceId last_id
= first_id
+ range
- 1u;
89 if (first_id
== 0u || last_id
< first_id
) {
90 return kInvalidResource
;
93 current
->second
= last_id
;
95 if (next
!= used_ids_
.end() && next
->first
- 1u == last_id
) {
96 // Merge with next range.
97 current
->second
= next
->second
;
98 used_ids_
.erase(next
);
104 bool IdAllocator::MarkAsUsed(ResourceId id
) {
106 ResourceIdRangeMap::iterator current
= used_ids_
.lower_bound(id
);
107 if (current
!= used_ids_
.end() && current
->first
== id
) {
111 ResourceIdRangeMap::iterator next
= current
;
114 if (current
->second
>= id
) {
118 DCHECK(current
->first
< id
&& current
->second
< id
);
120 if (current
->second
+ 1u == id
) {
121 // Append to current range.
122 current
->second
= id
;
123 if (next
!= used_ids_
.end() && next
->first
- 1u == id
) {
124 // Merge with next range.
125 current
->second
= next
->second
;
126 used_ids_
.erase(next
);
129 } else if (next
!= used_ids_
.end() && next
->first
- 1u == id
) {
130 // Prepend to next range.
131 ResourceId last_existing_id
= next
->second
;
132 used_ids_
.erase(next
);
133 used_ids_
.insert(std::make_pair(id
, last_existing_id
));
137 used_ids_
.insert(std::make_pair(id
, id
));
141 void IdAllocator::FreeID(ResourceId id
) {
145 void IdAllocator::FreeIDRange(ResourceId first_id
, uint32 range
) {
146 COMPILE_ASSERT(kInvalidResource
== 0u, invalid_resource_is_not_zero
);
148 if (range
== 0u || (first_id
== 0u && range
== 1u)) {
152 if (first_id
== 0u) {
157 ResourceId last_id
= first_id
+ range
- 1u;
158 if (last_id
< first_id
) {
159 last_id
= std::numeric_limits
<ResourceId
>::max();
163 ResourceIdRangeMap::iterator current
= used_ids_
.lower_bound(last_id
);
164 if (current
== used_ids_
.end() || current
->first
> last_id
) {
168 if (current
->second
< first_id
) {
172 if (current
->first
>= first_id
) {
173 ResourceId last_existing_id
= current
->second
;
174 used_ids_
.erase(current
);
175 if (last_id
< last_existing_id
) {
176 used_ids_
.insert(std::make_pair(last_id
+ 1u, last_existing_id
));
178 } else if (current
->second
<= last_id
) {
179 current
->second
= first_id
- 1u;
181 DCHECK(current
->first
< first_id
&& current
->second
> last_id
);
182 ResourceId last_existing_id
= current
->second
;
183 current
->second
= first_id
- 1u;
184 used_ids_
.insert(std::make_pair(last_id
+ 1u, last_existing_id
));
189 bool IdAllocator::InUse(ResourceId id
) const {
190 if (id
== kInvalidResource
) {
194 ResourceIdRangeMap::const_iterator current
= used_ids_
.lower_bound(id
);
195 if (current
!= used_ids_
.end()) {
196 if (current
->first
== id
) {
202 return current
->second
>= id
;