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

Side by Side Diff: net/disk_cache/bitmap.cc

Issue 126179: Disk cache: First pass to add support for sparse entries.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « net/disk_cache/bitmap.h ('k') | net/disk_cache/bitmap_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2009 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/disk_cache/bitmap.h"
6
7 #include "base/logging.h"
8
9 namespace {
10
11 // Returns the number of trailing zeros.
12 int FindLSBSetNonZero(uint32 word) {
13 // Get the LSB, put it on the exponent of a 32 bit float and remove the
14 // mantisa and the bias.
15 float f = static_cast<float>(word & -static_cast<int>(word));
16 return (*reinterpret_cast<uint32*>(&f) >> 23) - 0x7f;
17 }
18
19 // Returns the index of the first bit set to |value| from |word|. This code
20 // assumes that we'll be able to find that bit.
21 int FindLSBNonEmpty(uint32 word, bool value) {
22 // If we are looking for 0, negate |word| and look for 1.
23 if (!value)
24 word = ~word;
25
26 return FindLSBSetNonZero(word);
27 }
28
29 }
30
31 namespace disk_cache {
32
33 void Bitmap::Resize(int num_bits, bool clear_bits) {
34 DCHECK(alloc_ || !map_);
35 const int old_maxsize = num_bits_;
36 const int old_array_size = array_size_;
37 array_size_ = RequiredArraySize(num_bits);
38
39 if (array_size_ != old_array_size) {
40 uint32* new_map = new uint32[array_size_];
41 memcpy(new_map, map_,
42 sizeof(*map_) * std::min(array_size_, old_array_size));
43 if (alloc_)
44 delete[] map_; // No need to check for NULL.
45 map_ = new_map;
46 alloc_ = true;
47 }
48
49 num_bits_ = num_bits;
50 if (old_maxsize < num_bits_ && clear_bits) {
51 SetRange(old_maxsize, num_bits_, false);
52 }
53 }
54
55 void Bitmap::Set(int index, bool value) {
56 DCHECK_LT(index, num_bits_);
57 DCHECK_GE(index, 0);
58 const int i = index & (kIntBits - 1);
59 const int j = index / kIntBits;
60 if (value)
61 map_[j] |= (1 << i);
62 else
63 map_[j] &= ~(1 << i);
64 }
65
66 bool Bitmap::Get(int index) const {
67 DCHECK_LT(index, num_bits_);
68 DCHECK_GE(index, 0);
69 const int i = index & (kIntBits-1);
70 const int j = index / kIntBits;
71 return map_[j] & (1 << i) ? true : false;
72 }
73
74 void Bitmap::Toggle(int index) {
75 DCHECK_LT(index, num_bits_);
76 DCHECK_GE(index, 0);
77 const int i = index & (kIntBits - 1);
78 const int j = index / kIntBits;
79 map_[j] ^= (1 << i);
80 }
81
82 void Bitmap::SetMapElement(int array_index, uint32 value) {
83 DCHECK_LT(array_index, array_size_);
84 DCHECK_GE(array_index, 0);
85 map_[array_index] = value;
86 }
87
88 uint32 Bitmap::GetMapElement(int array_index) const {
89 DCHECK_LT(array_index, array_size_);
90 DCHECK_GE(array_index, 0);
91 return map_[array_index];
92 }
93
94 void Bitmap::SetMap(const uint32* map, int size) {
95 memcpy(map_, map, std::min(size, array_size_) * sizeof(*map_));
96 }
97
98 void Bitmap::SetWordBits(int start, int len, bool value) {
99 DCHECK_LT(len, kIntBits);
100 if (!len)
101 return;
102
103 int word = start / kIntBits;
104 int offset = start % kIntBits;
105
106 uint32 to_add = 0xffffffff << len;
107 to_add = (~to_add) << offset;
108 if (value) {
109 map_[word] |= to_add;
110 } else {
111 map_[word] &= ~to_add;
112 }
113 }
114
115 void Bitmap::SetRange(int begin, int end, bool value) {
116 int start_offset = begin & (kIntBits - 1);
117 if (start_offset) {
118 // Set the bits in the first word.
119 int len = std::min(end - begin, kIntBits - start_offset);
120 SetWordBits(begin, len, value);
121 begin += len;
122 }
123
124 if (begin == end)
125 return;
126
127 // Now set the bits in the last word.
128 int end_offset = end & (kIntBits - 1);
129 end -= end_offset;
130 SetWordBits(end, end_offset, value);
131
132 // Set all the words in the middle.
133 memset(map_ + (begin / kIntBits), (value ? 0xFF : 0x00),
134 ((end / kIntBits) - (begin / kIntBits)) * sizeof(*map_));
135 }
136
137 // Return true if any bit between begin inclusive and end exclusive
138 // is set. 0 <= begin <= end <= bits() is required.
139 bool Bitmap::TestRange(int begin, int end, bool value) const {
140 DCHECK_LT(begin, num_bits_);
141 DCHECK_LE(end, num_bits_);
142 DCHECK_LE(begin, end);
143 DCHECK_GE(begin, 0);
144 DCHECK_GE(end, 0);
145
146 // Return false immediately if the range is empty.
147 if (begin >= end || end <= 0)
148 return false;
149
150 // Calculate the indices of the words containing the first and last bits,
151 // along with the positions of the bits within those words.
152 int word = begin / kIntBits;
153 int offset = begin & (kIntBits - 1);
154 int last_word = (end - 1) / kIntBits;
155 int last_offset = (end - 1) & (kIntBits - 1);
156
157 // If we are looking for zeros, negate the data from the map.
158 uint32 this_word = map_[word];
159 if (!value)
160 this_word = ~this_word;
161
162 // If the range spans multiple words, discard the extraneous bits of the
163 // first word by shifting to the right, and then test the remaining bits.
164 if (word < last_word) {
165 if (this_word >> offset)
166 return true;
167 offset = 0;
168
169 word++;
170 // Test each of the "middle" words that lies completely within the range.
171 while (word < last_word) {
172 this_word = map_[word++];
173 if (!value)
174 this_word = ~this_word;
175 if (this_word)
176 return true;
177 }
178 }
179
180 // Test the portion of the last word that lies within the range. (This logic
181 // also handles the case where the entire range lies within a single word.)
182 const uint32 mask = ((2 << (last_offset - offset)) - 1) << offset;
183
184 this_word = map_[last_word];
185 if (!value)
186 this_word = ~this_word;
187
188 return (this_word & mask) != 0;
189 }
190
191 bool Bitmap::FindNextBit(int* index, int limit, bool value) const {
192 DCHECK_LT(*index, num_bits_);
193 DCHECK_LE(limit, num_bits_);
194 DCHECK_LE(*index, limit);
195 DCHECK_GE(*index, 0);
196 DCHECK_GE(limit, 0);
197
198 const int bit_index = *index;
199 if (bit_index >= limit || limit <= 0)
200 return false;
201
202 // From now on limit != 0, since if it was we would have returned false.
203 int word_index = bit_index >> kLogIntBits;
204 uint32 one_word = map_[word_index];
205
206 // Simple optimization where we can immediately return true if the first
207 // bit is set. This helps for cases where many bits are set, and doesn't
208 // hurt too much if not.
209 if (Get(bit_index) == value)
210 return true;
211
212 const int first_bit_offset = bit_index & (kIntBits - 1);
213
214 // First word is special - we need to mask off leading bits.
215 uint32 mask = 0xFFFFFFFF << first_bit_offset;
216 if (value) {
217 one_word &= mask;
218 } else {
219 one_word |= ~mask;
220 }
221
222 uint32 empty_value = value ? 0 : 0xFFFFFFFF;
223
224 // Loop through all but the last word. Note that 'limit' is one
225 // past the last bit we want to check, and we don't want to read
226 // past the end of "words". E.g. if num_bits_ == 32 only words[0] is
227 // valid, so we want to avoid reading words[1] when limit == 32.
228 const int last_word_index = (limit - 1) >> kLogIntBits;
229 while (word_index < last_word_index) {
230 if (one_word != empty_value) {
231 *index = (word_index << kLogIntBits) + FindLSBNonEmpty(one_word, value);
232 return true;
233 }
234 one_word = map_[++word_index];
235 }
236
237 // Last word is special - we may need to mask off trailing bits. Note that
238 // 'limit' is one past the last bit we want to check, and if limit is a
239 // multiple of 32 we want to check all bits in this word.
240 const int last_bit_offset = (limit - 1) & (kIntBits - 1);
241 mask = 0xFFFFFFFE << last_bit_offset;
242 if (value) {
243 one_word &= ~mask;
244 } else {
245 one_word |= mask;
246 }
247 if (one_word != empty_value) {
248 *index = (word_index << kLogIntBits) + FindLSBNonEmpty(one_word, value);
249 return true;
250 }
251 return false;
252 }
253
254 int Bitmap::FindBits(int* index, int limit, bool value) const {
255 DCHECK_LT(*index, num_bits_);
256 DCHECK_LE(limit, num_bits_);
257 DCHECK_LE(*index, limit);
258 DCHECK_GE(*index, 0);
259 DCHECK_GE(limit, 0);
260
261 if (!FindNextBit(index, limit, value))
262 return false;
263
264 // Now see how many bits have the same value.
265 int end = *index;
266 if (!FindNextBit(&end, limit, !value))
267 return limit - *index;
268
269 return end - *index;
270 }
271
272 } // namespace disk_cache
OLDNEW
« no previous file with comments | « net/disk_cache/bitmap.h ('k') | net/disk_cache/bitmap_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698