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

Side by Side Diff: courgette/third_party/bsdiff/paged_array.h

Issue 2008553007: [Courgette] PagedArray: Add Iterators and Parametrize Page Size as int Template. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 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
« no previous file with comments | « no previous file | courgette/third_party/bsdiff/paged_array_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 // PagedArray implements an array stored using many fixed-size pages. 5 // PagedArray implements an array stored using many fixed-size pages.
6 // 6 //
7 // PagedArray is a work-around to allow large arrays to be allocated when there 7 // PagedArray is a work-around to allow large arrays to be allocated when there
8 // is too much address space fragmentation for allocating the large arrays as 8 // is too much address space fragmentation for allocating the large arrays as
9 // contiguous arrays. 9 // contiguous arrays.
10 10
11 #ifndef COURGETTE_THIRD_PARTY_BSDIFF_PAGED_ARRAY_H_ 11 #ifndef COURGETTE_THIRD_PARTY_BSDIFF_PAGED_ARRAY_H_
12 #define COURGETTE_THIRD_PARTY_BSDIFF_PAGED_ARRAY_H_ 12 #define COURGETTE_THIRD_PARTY_BSDIFF_PAGED_ARRAY_H_
13 13
14 #include <stddef.h> 14 #include <stddef.h>
15 15
16 #include <iterator>
17
18 #include "base/logging.h"
16 #include "base/macros.h" 19 #include "base/macros.h"
17 #include "base/process/memory.h" 20 #include "base/process/memory.h"
18 21
19 namespace courgette { 22 namespace courgette {
20 23
24 // Page size of 2^18 * sizeof(T) is 1MB for T = int32_t.
25 constexpr int kPagedArrayDefaultPageLogSize = 18;
26
27 template <typename T, int LOG_PAGE_SIZE = kPagedArrayDefaultPageLogSize>
28 class PagedArray;
29
30 template <typename T, int LOG_PAGE_SIZE = kPagedArrayDefaultPageLogSize>
31 class PagedArray_const_iterator;
32
33 template <typename T, int LOG_PAGE_SIZE = kPagedArrayDefaultPageLogSize>
34 class PagedArray_iterator;
35
36 } // courgette
37
38 namespace std {
39
40 template <typename T, int LOG_PAGE_SIZE>
41 struct iterator_traits<class courgette::PagedArray_iterator<T, LOG_PAGE_SIZE>> {
etiennep 2016/05/25 14:19:02 We can declare these typedefs directly in the iter
huangs 2016/05/25 19:36:42 Went with directly declaring, using "using".
42 typedef ptrdiff_t difference_type;
43 typedef T value_type;
44 typedef T& reference;
45 typedef T* pointer;
46 typedef random_access_iterator_tag iterator_category;
47 };
48
49 template <typename T, int LOG_PAGE_SIZE>
50 struct iterator_traits<
51 class courgette::PagedArray_const_iterator<T, LOG_PAGE_SIZE>> {
52 typedef ptrdiff_t difference_type;
53 typedef T value_type;
54 typedef const T& reference;
55 typedef const T* pointer;
56 typedef random_access_iterator_tag iterator_category;
57 };
58
59 } // namespace std
60
61 namespace courgette {
62
63 template <typename T, int LOG_PAGE_SIZE>
64 class PagedArray_const_iterator {
etiennep 2016/05/25 14:19:01 This does a lot of duplicate code. I don't think w
huangs 2016/05/25 19:36:42 For this revision, went with the standard way of d
65 public:
66 using ContainerType = PagedArray<T, LOG_PAGE_SIZE>;
67 using ConstItType = PagedArray_const_iterator<T, LOG_PAGE_SIZE>;
68
69 PagedArray_const_iterator() : array_(nullptr), index_(0U) { }
70
71 PagedArray_const_iterator(const ContainerType* array, size_t index)
72 : array_(array), index_(index) { }
73
74 PagedArray_const_iterator(const PagedArray_const_iterator&) = default;
75
76 PagedArray_const_iterator(void*)
77 : array_(nullptr), index_(0) { }
78
79 ~PagedArray_const_iterator() { }
80
81 const T& operator*() const { return (*array_)[index_]; }
82
83 const T& operator[](size_t idx) const { return (*array_)[index_ + idx]; }
84
85 ConstItType& operator++() {
86 ++index_;
87 return *this;
88 }
89
90 ConstItType& operator--() {
91 --index_;
92 return *this;
93 }
94
95 ConstItType operator++(int) { return ConstItType(array_, index_++); }
96 ConstItType operator--(int) { return ConstItType(array_, index_--); }
97
98 ConstItType operator+=(size_t delta) {
etiennep 2016/05/25 14:19:01 NIT: the iterator concept requires delta to be dif
huangs 2016/05/25 19:36:42 Done.
99 return ConstItType(array_, index_ += delta);
100 }
101 ConstItType operator-=(size_t delta) {
102 return ConstItType(array_, index_ -= delta);
103 }
104
105 ConstItType operator+(size_t offset) {
106 return ConstItType(array_, index_ + offset);
107 }
108 ConstItType operator-(size_t offset) {
109 return ConstItType(array_, index_ - offset);
110 }
111
112 bool operator==(const ConstItType& it) const {
113 return index_ == it.index_ && array_ == it.array_;
114 }
115 bool operator!=(const ConstItType& it) const {
etiennep 2016/05/25 14:19:02 The implementation could be {return !(*this == it)
huangs 2016/05/25 19:36:42 Done.
116 return index_ != it.index_ || array_ != it.array_;
117 }
118
119 bool operator<(const ConstItType& it) const {
120 // Not bothering to check array_, for performance.
121 return index_ < it.index_;
122 }
123 bool operator<=(const ConstItType& it) const {
124 // Not bothering to check array_, for performance.
125 return index_ <= it.index_;
126 }
127
128 ptrdiff_t operator-(const ConstItType& it) const {
129 return index_ - it.index_;
130 }
131
132 private:
133 friend PagedArray_iterator<T, LOG_PAGE_SIZE>;
134
135 const ContainerType* array_;
136 size_t index_;
137 };
138
139 // RandomAccessIterator for PagedArray<T> to enable std::sort().
140 template <typename T, int LOG_PAGE_SIZE>
141 class PagedArray_iterator {
142 public:
143 using ContainerType = PagedArray<T, LOG_PAGE_SIZE>;
144 using ItType = PagedArray_iterator<T, LOG_PAGE_SIZE>;
145 using ConstItType = PagedArray_const_iterator<T, LOG_PAGE_SIZE>;
etiennep 2016/05/25 14:19:01 If you were to merge both iterator, we can get Con
huangs 2016/05/25 19:36:42 May try this next. So conversion operator will se
146
147 PagedArray_iterator() : array_(nullptr), index_(0U) { }
148
149 PagedArray_iterator(ContainerType* array, size_t index)
150 : array_(array), index_(index) { }
151
152 PagedArray_iterator(const PagedArray_iterator&) = default;
153
154 ~PagedArray_iterator() { }
etiennep 2016/05/25 14:19:02 Would be more consistent = default
huangs 2016/05/25 19:36:42 Done.
155
156 operator ConstItType() { return ConstItType(array_, index_); }
157
158 const T& operator*() const { return (*array_)[index_]; }
159 T& operator*() { return (*array_)[index_]; }
160
etiennep 2016/05/25 14:19:01 We could put operator-> as it is a requirement for
huangs 2016/05/25 19:36:42 Added, with tests.
161 const T& operator[](size_t idx) const { return (*array_)[index_ + idx]; }
etiennep 2016/05/25 14:19:01 Not very useful. A const-qualified iterator (could
huangs 2016/05/25 19:36:42 Good point; removed! Also removing const T& opera
162 T& operator[](size_t idx) { return (*array_)[index_ + idx]; }
163
164 ItType& operator++() {
165 ++index_;
166 return *this;
167 }
168
169 ItType& operator--() {
170 --index_;
171 return *this;
172 }
173
174 ItType operator++(int) { return ItType(array_, index_++); }
175 ItType operator--(int) { return ItType(array_, index_--); }
176
177 ItType operator+=(size_t delta) { return ItType(array_, index_ += delta); }
178 ItType operator-=(size_t delta) { return ItType(array_, index_ -= delta); }
179
180 ItType operator+(size_t offset) { return ItType(array_, index_ + offset); }
181 ItType operator-(size_t offset) { return ItType(array_, index_ - offset); }
182
183 // Only useful for assigning nullptr.
184 ItType& operator=(void*) {
etiennep 2016/05/25 14:19:01 The arguments should be std::nullptr_t instead.
huangs 2016/05/25 19:36:42 Done.
185 array_ = nullptr;
186 index_ = 0;
187 return *this;
188 }
189
190 bool operator==(const ItType& it) const {
191 return index_ == it.index_ && array_ == it.array_;
192 }
193
194 // Only intended for comparing against nullptr.
195 bool operator==(const void* p) const {
etiennep 2016/05/25 14:19:02 std::nullptr_t again. There would be non need to c
huangs 2016/05/25 19:36:42 Done.
196 DCHECK_EQ(nullptr, p);
197 return index_ == 0 && array_ == p;
198 }
199
200 bool operator!=(const ItType& it) const {
201 return index_ != it.index_ || array_ != it.array_;
202 }
203
204 bool operator<(const ItType& it) const {
205 // Not bothering to check array_, for performance.
206 return index_ < it.index_;
207 }
208 bool operator<=(const ItType& it) const {
209 // Not bothering to check array_, for performance.
210 return index_ <= it.index_;
211 }
212
213 ptrdiff_t operator-(const ItType& it) const {
214 return index_ - it.index_;
215 }
216
217 ptrdiff_t operator-(const ConstItType& it) const {
218 return index_ - it.index_;
219 }
220
221 private:
222 ContainerType* array_;
223 size_t index_;
224 };
225
21 // PagedArray implements an array stored using many fixed-size pages. 226 // PagedArray implements an array stored using many fixed-size pages.
22 template <typename T> 227 template <typename T, int LOG_PAGE_SIZE>
23 class PagedArray { 228 class PagedArray {
24 enum { 229 enum {
25 // Page size in elements. Page size of 2^18 * sizeof(T) is 1MB for T = int. 230 // Page size in elements.
26 kLogPageSize = 18, 231 kLogPageSize = LOG_PAGE_SIZE,
27 kPageSize = 1 << kLogPageSize 232 kPageSize = 1 << LOG_PAGE_SIZE
28 }; 233 };
29 234
30 public: 235 public:
31 PagedArray() : pages_(NULL), page_count_(0) {} 236 typedef PagedArray_const_iterator<T, LOG_PAGE_SIZE> const_iterator;
32 237 typedef PagedArray_iterator<T, LOG_PAGE_SIZE> iterator;
238
239 PagedArray() { }
33 ~PagedArray() { clear(); } 240 ~PagedArray() { clear(); }
34 241
242 iterator begin() { return iterator(this, 0); }
243 iterator end() { return iterator(this, size_); }
244 const_iterator begin() const { return const_iterator(this, 0); }
245 const_iterator end() const { return const_iterator(this, size_); }
246
35 T& operator[](size_t i) { 247 T& operator[](size_t i) {
36 size_t page = i >> kLogPageSize; 248 size_t page = i >> kLogPageSize;
37 size_t offset = i & (kPageSize - 1); 249 size_t offset = i & (kPageSize - 1);
38 // It is tempting to add a DCHECK(page < page_count_), but that makes 250 // It is tempting to add a DCHECK(page < page_count_), but that makes
39 // bsdiff_create run 2x slower (even when compiled optimized.) 251 // bsdiff_create run 2x slower (even when compiled optimized.)
40 return pages_[page][offset]; 252 return pages_[page][offset];
41 } 253 }
42 254
255 const T& operator[](size_t i) const {
etiennep 2016/05/25 14:19:01 This is me asking : If PagedArray is meant to supp
huangs 2016/05/25 19:36:42 PagedArray is meant to solve memory fragmentation
256 size_t page = i >> kLogPageSize;
257 size_t offset = i & (kPageSize - 1);
258 // It is tempting to add a DCHECK(page < page_count_), but that makes
259 // bsdiff_create run 2x slower (even when compiled optimized.)
260 return pages_[page][offset];
261 }
262
43 // Allocates storage for |size| elements. Returns true on success and false if 263 // Allocates storage for |size| elements. Returns true on success and false if
44 // allocation fails. 264 // allocation fails.
45 bool Allocate(size_t size) { 265 bool Allocate(size_t size) {
46 clear(); 266 clear();
47 size_t pages_needed = (size + kPageSize - 1) >> kLogPageSize; 267 size_ = size;
268 size_t pages_needed = (size_ + kPageSize - 1) >> kLogPageSize;
48 if (!base::UncheckedMalloc(sizeof(T*) * pages_needed, 269 if (!base::UncheckedMalloc(sizeof(T*) * pages_needed,
49 reinterpret_cast<void**>(&pages_))) { 270 reinterpret_cast<void**>(&pages_))) {
50 return false; 271 return false;
51 } 272 }
52 273
53 for (page_count_ = 0; page_count_ < pages_needed; ++page_count_) { 274 for (page_count_ = 0; page_count_ < pages_needed; ++page_count_) {
54 T* block = nullptr; 275 T* block = nullptr;
55 if (!base::UncheckedMalloc(sizeof(T) * kPageSize, 276 if (!base::UncheckedMalloc(sizeof(T) * kPageSize,
56 reinterpret_cast<void**>(&block))) { 277 reinterpret_cast<void**>(&block))) {
57 clear(); 278 clear();
58 return false; 279 return false;
59 } 280 }
60 pages_[page_count_] = block; 281 pages_[page_count_] = block;
61 } 282 }
62 return true; 283 return true;
63 } 284 }
64 285
65 // Releases all storage. May be called more than once. 286 // Releases all storage. May be called more than once.
66 void clear() { 287 void clear() {
67 if (pages_ != NULL) { 288 if (pages_ != nullptr) {
68 while (page_count_ != 0) { 289 while (page_count_ != 0) {
69 --page_count_; 290 --page_count_;
70 free(pages_[page_count_]); 291 free(pages_[page_count_]);
71 } 292 }
72 free(pages_); 293 free(pages_);
73 pages_ = NULL; 294 pages_ = nullptr;
74 } 295 }
75 } 296 }
76 297
77 private: 298 private:
78 T** pages_; 299 T** pages_ = nullptr;
79 size_t page_count_; 300 size_t size_ = 0U;
301 size_t page_count_ = 0U;
80 302
81 DISALLOW_COPY_AND_ASSIGN(PagedArray); 303 DISALLOW_COPY_AND_ASSIGN(PagedArray);
82 }; 304 };
83 305
84 } // namespace courgette 306 } // namespace courgette
307
85 #endif // COURGETTE_THIRD_PARTY_BSDIFF_PAGED_ARRAY_H_ 308 #endif // COURGETTE_THIRD_PARTY_BSDIFF_PAGED_ARRAY_H_
OLDNEW
« no previous file with comments | « no previous file | courgette/third_party/bsdiff/paged_array_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698