1*4882a593SmuzhiyunFrom da832c778d013f4217e2d704c27c1d2e19a9364c Mon Sep 17 00:00:00 2001 2*4882a593SmuzhiyunFrom: Khem Raj <raj.khem@gmail.com> 3*4882a593SmuzhiyunDate: Thu, 2 Jan 2020 17:13:55 -0800 4*4882a593SmuzhiyunSubject: [PATCH] chromium: Move CharAllocator definition to a header file 5*4882a593Smuzhiyun 6*4882a593SmuzhiyunFixes 7*4882a593Smuzhiyunerror: invalid application of 'sizeof' to an incomplete type 'cc::ListContainerHelper::CharAllocator' 8*4882a593Smuzhiyun 9*4882a593SmuzhiyunUpstream-Status: Pending 10*4882a593SmuzhiyunSigned-off-by: Khem Raj <raj.khem@gmail.com> 11*4882a593Smuzhiyun--- 12*4882a593Smuzhiyun chromium/cc/base/list_container_helper.cc | 251 --------------------- 13*4882a593Smuzhiyun chromium/cc/base/list_container_helper.h | 255 ++++++++++++++++++++++ 14*4882a593Smuzhiyun 2 files changed, 255 insertions(+), 251 deletions(-) 15*4882a593Smuzhiyun 16*4882a593Smuzhiyundiff --git a/chromium/cc/base/list_container_helper.cc b/chromium/cc/base/list_container_helper.cc 17*4882a593Smuzhiyunindex 7b594b4a458..9dae1c360c4 100644 18*4882a593Smuzhiyun--- a/chromium/cc/base/list_container_helper.cc 19*4882a593Smuzhiyun+++ b/chromium/cc/base/list_container_helper.cc 20*4882a593Smuzhiyun@@ -13,259 +13,8 @@ 21*4882a593Smuzhiyun #include "base/check_op.h" 22*4882a593Smuzhiyun #include "base/memory/aligned_memory.h" 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun-namespace { 25*4882a593Smuzhiyun-const size_t kDefaultNumElementTypesToReserve = 32; 26*4882a593Smuzhiyun-} // namespace 27*4882a593Smuzhiyun- 28*4882a593Smuzhiyun namespace cc { 29*4882a593Smuzhiyun 30*4882a593Smuzhiyun-// CharAllocator 31*4882a593Smuzhiyun-//////////////////////////////////////////////////// 32*4882a593Smuzhiyun-// This class deals only with char* and void*. It does allocation and passing 33*4882a593Smuzhiyun-// out raw pointers, as well as memory deallocation when being destroyed. 34*4882a593Smuzhiyun-class ListContainerHelper::CharAllocator { 35*4882a593Smuzhiyun- public: 36*4882a593Smuzhiyun- // CharAllocator::InnerList 37*4882a593Smuzhiyun- ///////////////////////////////////////////// 38*4882a593Smuzhiyun- // This class holds the raw memory chunk, as well as information about its 39*4882a593Smuzhiyun- // size and availability. 40*4882a593Smuzhiyun- struct InnerList { 41*4882a593Smuzhiyun- InnerList(const InnerList&) = delete; 42*4882a593Smuzhiyun- InnerList& operator=(const InnerList&) = delete; 43*4882a593Smuzhiyun- 44*4882a593Smuzhiyun- std::unique_ptr<char[], base::AlignedFreeDeleter> data; 45*4882a593Smuzhiyun- // The number of elements in total the memory can hold. The difference 46*4882a593Smuzhiyun- // between capacity and size is the how many more elements this list can 47*4882a593Smuzhiyun- // hold. 48*4882a593Smuzhiyun- size_t capacity; 49*4882a593Smuzhiyun- // The number of elements have been put into this list. 50*4882a593Smuzhiyun- size_t size; 51*4882a593Smuzhiyun- // The size of each element is in bytes. This is used to move from between 52*4882a593Smuzhiyun- // elements' memory locations. 53*4882a593Smuzhiyun- size_t step; 54*4882a593Smuzhiyun- 55*4882a593Smuzhiyun- InnerList() : capacity(0), size(0), step(0) {} 56*4882a593Smuzhiyun- 57*4882a593Smuzhiyun- void Erase(char* position) { 58*4882a593Smuzhiyun- // Confident that destructor is called by caller of this function. Since 59*4882a593Smuzhiyun- // CharAllocator does not handle construction after 60*4882a593Smuzhiyun- // allocation, it doesn't handle desctrution before deallocation. 61*4882a593Smuzhiyun- DCHECK_LE(position, LastElement()); 62*4882a593Smuzhiyun- DCHECK_GE(position, Begin()); 63*4882a593Smuzhiyun- char* start = position + step; 64*4882a593Smuzhiyun- std::copy(start, End(), position); 65*4882a593Smuzhiyun- 66*4882a593Smuzhiyun- --size; 67*4882a593Smuzhiyun- // Decrease capacity to avoid creating not full not last InnerList. 68*4882a593Smuzhiyun- --capacity; 69*4882a593Smuzhiyun- } 70*4882a593Smuzhiyun- 71*4882a593Smuzhiyun- void InsertBefore(size_t alignment, char** position, size_t count) { 72*4882a593Smuzhiyun- DCHECK_LE(*position, LastElement() + step); 73*4882a593Smuzhiyun- DCHECK_GE(*position, Begin()); 74*4882a593Smuzhiyun- 75*4882a593Smuzhiyun- // Adjust the size and capacity 76*4882a593Smuzhiyun- size_t old_size = size; 77*4882a593Smuzhiyun- size += count; 78*4882a593Smuzhiyun- capacity = size; 79*4882a593Smuzhiyun- 80*4882a593Smuzhiyun- // Allocate the new data and update the iterator's pointer. 81*4882a593Smuzhiyun- std::unique_ptr<char[], base::AlignedFreeDeleter> new_data( 82*4882a593Smuzhiyun- static_cast<char*>(base::AlignedAlloc(size * step, alignment))); 83*4882a593Smuzhiyun- size_t position_offset = *position - Begin(); 84*4882a593Smuzhiyun- *position = new_data.get() + position_offset; 85*4882a593Smuzhiyun- 86*4882a593Smuzhiyun- // Copy the data before the inserted segment 87*4882a593Smuzhiyun- memcpy(new_data.get(), data.get(), position_offset); 88*4882a593Smuzhiyun- // Copy the data after the inserted segment. 89*4882a593Smuzhiyun- memcpy(new_data.get() + position_offset + count * step, 90*4882a593Smuzhiyun- data.get() + position_offset, old_size * step - position_offset); 91*4882a593Smuzhiyun- data = std::move(new_data); 92*4882a593Smuzhiyun- } 93*4882a593Smuzhiyun- 94*4882a593Smuzhiyun- bool IsEmpty() const { return !size; } 95*4882a593Smuzhiyun- bool IsFull() { return capacity == size; } 96*4882a593Smuzhiyun- size_t NumElementsAvailable() const { return capacity - size; } 97*4882a593Smuzhiyun- 98*4882a593Smuzhiyun- void* AddElement() { 99*4882a593Smuzhiyun- DCHECK_LT(size, capacity); 100*4882a593Smuzhiyun- ++size; 101*4882a593Smuzhiyun- return LastElement(); 102*4882a593Smuzhiyun- } 103*4882a593Smuzhiyun- 104*4882a593Smuzhiyun- void RemoveLast() { 105*4882a593Smuzhiyun- DCHECK(!IsEmpty()); 106*4882a593Smuzhiyun- --size; 107*4882a593Smuzhiyun- } 108*4882a593Smuzhiyun- 109*4882a593Smuzhiyun- char* Begin() const { return data.get(); } 110*4882a593Smuzhiyun- char* End() const { return data.get() + size * step; } 111*4882a593Smuzhiyun- char* LastElement() const { return data.get() + (size - 1) * step; } 112*4882a593Smuzhiyun- char* ElementAt(size_t index) const { return data.get() + index * step; } 113*4882a593Smuzhiyun- }; 114*4882a593Smuzhiyun- 115*4882a593Smuzhiyun- CharAllocator(size_t alignment, size_t element_size, size_t element_count) 116*4882a593Smuzhiyun- // base::AlignedAlloc does not accept alignment less than sizeof(void*). 117*4882a593Smuzhiyun- : alignment_(std::max(sizeof(void*), alignment)), 118*4882a593Smuzhiyun- element_size_(element_size), 119*4882a593Smuzhiyun- size_(0), 120*4882a593Smuzhiyun- last_list_index_(0), 121*4882a593Smuzhiyun- last_list_(nullptr) { 122*4882a593Smuzhiyun- // If this fails, then alignment of elements after the first could be wrong, 123*4882a593Smuzhiyun- // and we need to pad sizes to fix that. 124*4882a593Smuzhiyun- DCHECK_EQ(element_size % alignment, 0u); 125*4882a593Smuzhiyun- AllocateNewList(element_count > 0 ? element_count 126*4882a593Smuzhiyun- : kDefaultNumElementTypesToReserve); 127*4882a593Smuzhiyun- last_list_ = storage_[last_list_index_].get(); 128*4882a593Smuzhiyun- } 129*4882a593Smuzhiyun- 130*4882a593Smuzhiyun- CharAllocator(const CharAllocator&) = delete; 131*4882a593Smuzhiyun- ~CharAllocator() = default; 132*4882a593Smuzhiyun- 133*4882a593Smuzhiyun- CharAllocator& operator=(const CharAllocator&) = delete; 134*4882a593Smuzhiyun- 135*4882a593Smuzhiyun- void* Allocate() { 136*4882a593Smuzhiyun- if (last_list_->IsFull()) { 137*4882a593Smuzhiyun- // Only allocate a new list if there isn't a spare one still there from 138*4882a593Smuzhiyun- // previous usage. 139*4882a593Smuzhiyun- if (last_list_index_ + 1 >= storage_.size()) 140*4882a593Smuzhiyun- AllocateNewList(last_list_->capacity * 2); 141*4882a593Smuzhiyun- 142*4882a593Smuzhiyun- ++last_list_index_; 143*4882a593Smuzhiyun- last_list_ = storage_[last_list_index_].get(); 144*4882a593Smuzhiyun- } 145*4882a593Smuzhiyun- 146*4882a593Smuzhiyun- ++size_; 147*4882a593Smuzhiyun- return last_list_->AddElement(); 148*4882a593Smuzhiyun- } 149*4882a593Smuzhiyun- 150*4882a593Smuzhiyun- size_t alignment() const { return alignment_; } 151*4882a593Smuzhiyun- size_t element_size() const { return element_size_; } 152*4882a593Smuzhiyun- size_t list_count() const { return storage_.size(); } 153*4882a593Smuzhiyun- size_t size() const { return size_; } 154*4882a593Smuzhiyun- bool IsEmpty() const { return size() == 0; } 155*4882a593Smuzhiyun- 156*4882a593Smuzhiyun- size_t Capacity() const { 157*4882a593Smuzhiyun- size_t capacity_sum = 0; 158*4882a593Smuzhiyun- for (const auto& inner_list : storage_) 159*4882a593Smuzhiyun- capacity_sum += inner_list->capacity; 160*4882a593Smuzhiyun- return capacity_sum; 161*4882a593Smuzhiyun- } 162*4882a593Smuzhiyun- 163*4882a593Smuzhiyun- void Clear() { 164*4882a593Smuzhiyun- // Remove all except for the first InnerList. 165*4882a593Smuzhiyun- DCHECK(!storage_.empty()); 166*4882a593Smuzhiyun- storage_.erase(storage_.begin() + 1, storage_.end()); 167*4882a593Smuzhiyun- last_list_index_ = 0; 168*4882a593Smuzhiyun- last_list_ = storage_[0].get(); 169*4882a593Smuzhiyun- last_list_->size = 0; 170*4882a593Smuzhiyun- size_ = 0; 171*4882a593Smuzhiyun- } 172*4882a593Smuzhiyun- 173*4882a593Smuzhiyun- void RemoveLast() { 174*4882a593Smuzhiyun- DCHECK(!IsEmpty()); 175*4882a593Smuzhiyun- last_list_->RemoveLast(); 176*4882a593Smuzhiyun- if (last_list_->IsEmpty() && last_list_index_ > 0) { 177*4882a593Smuzhiyun- --last_list_index_; 178*4882a593Smuzhiyun- last_list_ = storage_[last_list_index_].get(); 179*4882a593Smuzhiyun- 180*4882a593Smuzhiyun- // If there are now two empty inner lists, free one of them. 181*4882a593Smuzhiyun- if (last_list_index_ + 2 < storage_.size()) 182*4882a593Smuzhiyun- storage_.pop_back(); 183*4882a593Smuzhiyun- } 184*4882a593Smuzhiyun- --size_; 185*4882a593Smuzhiyun- } 186*4882a593Smuzhiyun- 187*4882a593Smuzhiyun- void Erase(PositionInCharAllocator* position) { 188*4882a593Smuzhiyun- DCHECK_EQ(this, position->ptr_to_container); 189*4882a593Smuzhiyun- 190*4882a593Smuzhiyun- // Update |position| to point to the element after the erased element. 191*4882a593Smuzhiyun- InnerList* list = storage_[position->vector_index].get(); 192*4882a593Smuzhiyun- char* item_iterator = position->item_iterator; 193*4882a593Smuzhiyun- if (item_iterator == list->LastElement()) 194*4882a593Smuzhiyun- position->Increment(); 195*4882a593Smuzhiyun- 196*4882a593Smuzhiyun- list->Erase(item_iterator); 197*4882a593Smuzhiyun- // TODO(weiliangc): Free the InnerList if it is empty. 198*4882a593Smuzhiyun- --size_; 199*4882a593Smuzhiyun- } 200*4882a593Smuzhiyun- 201*4882a593Smuzhiyun- void InsertBefore(ListContainerHelper::Iterator* position, size_t count) { 202*4882a593Smuzhiyun- if (!count) 203*4882a593Smuzhiyun- return; 204*4882a593Smuzhiyun- 205*4882a593Smuzhiyun- // If |position| is End(), then append |count| elements at the end. This 206*4882a593Smuzhiyun- // will happen to not invalidate any iterators or memory. 207*4882a593Smuzhiyun- if (!position->item_iterator) { 208*4882a593Smuzhiyun- // Set |position| to be the first inserted element. 209*4882a593Smuzhiyun- Allocate(); 210*4882a593Smuzhiyun- position->vector_index = storage_.size() - 1; 211*4882a593Smuzhiyun- position->item_iterator = storage_[position->vector_index]->LastElement(); 212*4882a593Smuzhiyun- // Allocate the rest. 213*4882a593Smuzhiyun- for (size_t i = 1; i < count; ++i) 214*4882a593Smuzhiyun- Allocate(); 215*4882a593Smuzhiyun- } else { 216*4882a593Smuzhiyun- storage_[position->vector_index]->InsertBefore( 217*4882a593Smuzhiyun- alignment_, &position->item_iterator, count); 218*4882a593Smuzhiyun- size_ += count; 219*4882a593Smuzhiyun- } 220*4882a593Smuzhiyun- } 221*4882a593Smuzhiyun- 222*4882a593Smuzhiyun- InnerList* InnerListById(size_t id) const { 223*4882a593Smuzhiyun- DCHECK_LT(id, storage_.size()); 224*4882a593Smuzhiyun- return storage_[id].get(); 225*4882a593Smuzhiyun- } 226*4882a593Smuzhiyun- 227*4882a593Smuzhiyun- size_t FirstInnerListId() const { 228*4882a593Smuzhiyun- // |size_| > 0 means that at least one vector in |storage_| will be 229*4882a593Smuzhiyun- // non-empty. 230*4882a593Smuzhiyun- DCHECK_GT(size_, 0u); 231*4882a593Smuzhiyun- size_t id = 0; 232*4882a593Smuzhiyun- while (storage_[id]->size == 0) 233*4882a593Smuzhiyun- ++id; 234*4882a593Smuzhiyun- return id; 235*4882a593Smuzhiyun- } 236*4882a593Smuzhiyun- 237*4882a593Smuzhiyun- size_t LastInnerListId() const { 238*4882a593Smuzhiyun- // |size_| > 0 means that at least one vector in |storage_| will be 239*4882a593Smuzhiyun- // non-empty. 240*4882a593Smuzhiyun- DCHECK_GT(size_, 0u); 241*4882a593Smuzhiyun- size_t id = storage_.size() - 1; 242*4882a593Smuzhiyun- while (storage_[id]->size == 0) 243*4882a593Smuzhiyun- --id; 244*4882a593Smuzhiyun- return id; 245*4882a593Smuzhiyun- } 246*4882a593Smuzhiyun- 247*4882a593Smuzhiyun- size_t NumAvailableElementsInLastList() const { 248*4882a593Smuzhiyun- return last_list_->NumElementsAvailable(); 249*4882a593Smuzhiyun- } 250*4882a593Smuzhiyun- 251*4882a593Smuzhiyun- private: 252*4882a593Smuzhiyun- void AllocateNewList(size_t list_size) { 253*4882a593Smuzhiyun- std::unique_ptr<InnerList> new_list(new InnerList); 254*4882a593Smuzhiyun- new_list->capacity = list_size; 255*4882a593Smuzhiyun- new_list->size = 0; 256*4882a593Smuzhiyun- new_list->step = element_size_; 257*4882a593Smuzhiyun- new_list->data.reset(static_cast<char*>( 258*4882a593Smuzhiyun- base::AlignedAlloc(list_size * element_size_, alignment_))); 259*4882a593Smuzhiyun- storage_.push_back(std::move(new_list)); 260*4882a593Smuzhiyun- } 261*4882a593Smuzhiyun- 262*4882a593Smuzhiyun- std::vector<std::unique_ptr<InnerList>> storage_; 263*4882a593Smuzhiyun- const size_t alignment_; 264*4882a593Smuzhiyun- const size_t element_size_; 265*4882a593Smuzhiyun- 266*4882a593Smuzhiyun- // The number of elements in the list. 267*4882a593Smuzhiyun- size_t size_; 268*4882a593Smuzhiyun- 269*4882a593Smuzhiyun- // The index of the last list to have had elements added to it, or the only 270*4882a593Smuzhiyun- // list if the container has not had elements added since being cleared. 271*4882a593Smuzhiyun- size_t last_list_index_; 272*4882a593Smuzhiyun- 273*4882a593Smuzhiyun- // This is equivalent to |storage_[last_list_index_]|. 274*4882a593Smuzhiyun- InnerList* last_list_; 275*4882a593Smuzhiyun-}; 276*4882a593Smuzhiyun- 277*4882a593Smuzhiyun // PositionInCharAllocator 278*4882a593Smuzhiyun ////////////////////////////////////////////////////// 279*4882a593Smuzhiyun ListContainerHelper::PositionInCharAllocator::PositionInCharAllocator( 280*4882a593Smuzhiyundiff --git a/chromium/cc/base/list_container_helper.h b/chromium/cc/base/list_container_helper.h 281*4882a593Smuzhiyunindex 31658bc8486..9e65013cbdb 100644 282*4882a593Smuzhiyun--- a/chromium/cc/base/list_container_helper.h 283*4882a593Smuzhiyun+++ b/chromium/cc/base/list_container_helper.h 284*4882a593Smuzhiyun@@ -8,9 +8,17 @@ 285*4882a593Smuzhiyun #include <stddef.h> 286*4882a593Smuzhiyun 287*4882a593Smuzhiyun #include <memory> 288*4882a593Smuzhiyun+#include <algorithm> 289*4882a593Smuzhiyun+#include <vector> 290*4882a593Smuzhiyun 291*4882a593Smuzhiyun+#include "base/logging.h" 292*4882a593Smuzhiyun+#include "base/memory/aligned_memory.h" 293*4882a593Smuzhiyun #include "cc/base/base_export.h" 294*4882a593Smuzhiyun 295*4882a593Smuzhiyun+namespace { 296*4882a593Smuzhiyun+const size_t kDefaultNumElementTypesToReserve = 32; 297*4882a593Smuzhiyun+} // namespace 298*4882a593Smuzhiyun+ 299*4882a593Smuzhiyun namespace cc { 300*4882a593Smuzhiyun 301*4882a593Smuzhiyun // Helper class for ListContainer non-templated logic. All methods are private, 302*4882a593Smuzhiyun@@ -174,6 +182,253 @@ class CC_BASE_EXPORT ListContainerHelper final { 303*4882a593Smuzhiyun std::unique_ptr<CharAllocator> data_; 304*4882a593Smuzhiyun }; 305*4882a593Smuzhiyun 306*4882a593Smuzhiyun+// CharAllocator 307*4882a593Smuzhiyun+//////////////////////////////////////////////////// 308*4882a593Smuzhiyun+// This class deals only with char* and void*. It does allocation and passing 309*4882a593Smuzhiyun+// out raw pointers, as well as memory deallocation when being destroyed. 310*4882a593Smuzhiyun+class ListContainerHelper::CharAllocator { 311*4882a593Smuzhiyun+ public: 312*4882a593Smuzhiyun+ // CharAllocator::InnerList 313*4882a593Smuzhiyun+ ///////////////////////////////////////////// 314*4882a593Smuzhiyun+ // This class holds the raw memory chunk, as well as information about its 315*4882a593Smuzhiyun+ // size and availability. 316*4882a593Smuzhiyun+ struct InnerList { 317*4882a593Smuzhiyun+ InnerList(const InnerList&) = delete; 318*4882a593Smuzhiyun+ InnerList& operator=(const InnerList&) = delete; 319*4882a593Smuzhiyun+ 320*4882a593Smuzhiyun+ std::unique_ptr<char[], base::AlignedFreeDeleter> data; 321*4882a593Smuzhiyun+ // The number of elements in total the memory can hold. The difference 322*4882a593Smuzhiyun+ // between capacity and size is the how many more elements this list can 323*4882a593Smuzhiyun+ // hold. 324*4882a593Smuzhiyun+ size_t capacity; 325*4882a593Smuzhiyun+ // The number of elements have been put into this list. 326*4882a593Smuzhiyun+ size_t size; 327*4882a593Smuzhiyun+ // The size of each element is in bytes. This is used to move from between 328*4882a593Smuzhiyun+ // elements' memory locations. 329*4882a593Smuzhiyun+ size_t step; 330*4882a593Smuzhiyun+ 331*4882a593Smuzhiyun+ InnerList() : capacity(0), size(0), step(0) {} 332*4882a593Smuzhiyun+ 333*4882a593Smuzhiyun+ void Erase(char* position) { 334*4882a593Smuzhiyun+ // Confident that destructor is called by caller of this function. Since 335*4882a593Smuzhiyun+ // CharAllocator does not handle construction after 336*4882a593Smuzhiyun+ // allocation, it doesn't handle desctrution before deallocation. 337*4882a593Smuzhiyun+ DCHECK_LE(position, LastElement()); 338*4882a593Smuzhiyun+ DCHECK_GE(position, Begin()); 339*4882a593Smuzhiyun+ char* start = position + step; 340*4882a593Smuzhiyun+ std::copy(start, End(), position); 341*4882a593Smuzhiyun+ 342*4882a593Smuzhiyun+ --size; 343*4882a593Smuzhiyun+ // Decrease capacity to avoid creating not full not last InnerList. 344*4882a593Smuzhiyun+ --capacity; 345*4882a593Smuzhiyun+ } 346*4882a593Smuzhiyun+ 347*4882a593Smuzhiyun+ void InsertBefore(size_t alignment, char** position, size_t count) { 348*4882a593Smuzhiyun+ DCHECK_LE(*position, LastElement() + step); 349*4882a593Smuzhiyun+ DCHECK_GE(*position, Begin()); 350*4882a593Smuzhiyun+ 351*4882a593Smuzhiyun+ // Adjust the size and capacity 352*4882a593Smuzhiyun+ size_t old_size = size; 353*4882a593Smuzhiyun+ size += count; 354*4882a593Smuzhiyun+ capacity = size; 355*4882a593Smuzhiyun+ 356*4882a593Smuzhiyun+ // Allocate the new data and update the iterator's pointer. 357*4882a593Smuzhiyun+ std::unique_ptr<char[], base::AlignedFreeDeleter> new_data( 358*4882a593Smuzhiyun+ static_cast<char*>(base::AlignedAlloc(size * step, alignment))); 359*4882a593Smuzhiyun+ size_t position_offset = *position - Begin(); 360*4882a593Smuzhiyun+ *position = new_data.get() + position_offset; 361*4882a593Smuzhiyun+ 362*4882a593Smuzhiyun+ // Copy the data before the inserted segment 363*4882a593Smuzhiyun+ memcpy(new_data.get(), data.get(), position_offset); 364*4882a593Smuzhiyun+ // Copy the data after the inserted segment. 365*4882a593Smuzhiyun+ memcpy(new_data.get() + position_offset + count * step, 366*4882a593Smuzhiyun+ data.get() + position_offset, old_size * step - position_offset); 367*4882a593Smuzhiyun+ data = std::move(new_data); 368*4882a593Smuzhiyun+ } 369*4882a593Smuzhiyun+ 370*4882a593Smuzhiyun+ bool IsEmpty() const { return !size; } 371*4882a593Smuzhiyun+ bool IsFull() { return capacity == size; } 372*4882a593Smuzhiyun+ size_t NumElementsAvailable() const { return capacity - size; } 373*4882a593Smuzhiyun+ 374*4882a593Smuzhiyun+ void* AddElement() { 375*4882a593Smuzhiyun+ DCHECK_LT(size, capacity); 376*4882a593Smuzhiyun+ ++size; 377*4882a593Smuzhiyun+ return LastElement(); 378*4882a593Smuzhiyun+ } 379*4882a593Smuzhiyun+ 380*4882a593Smuzhiyun+ void RemoveLast() { 381*4882a593Smuzhiyun+ DCHECK(!IsEmpty()); 382*4882a593Smuzhiyun+ --size; 383*4882a593Smuzhiyun+ } 384*4882a593Smuzhiyun+ 385*4882a593Smuzhiyun+ char* Begin() const { return data.get(); } 386*4882a593Smuzhiyun+ char* End() const { return data.get() + size * step; } 387*4882a593Smuzhiyun+ char* LastElement() const { return data.get() + (size - 1) * step; } 388*4882a593Smuzhiyun+ char* ElementAt(size_t index) const { return data.get() + index * step; } 389*4882a593Smuzhiyun+ }; 390*4882a593Smuzhiyun+ 391*4882a593Smuzhiyun+ CharAllocator(size_t alignment, size_t element_size, size_t element_count) 392*4882a593Smuzhiyun+ // base::AlignedAlloc does not accept alignment less than sizeof(void*). 393*4882a593Smuzhiyun+ : alignment_(std::max(sizeof(void*), alignment)), 394*4882a593Smuzhiyun+ element_size_(element_size), 395*4882a593Smuzhiyun+ size_(0), 396*4882a593Smuzhiyun+ last_list_index_(0), 397*4882a593Smuzhiyun+ last_list_(nullptr) { 398*4882a593Smuzhiyun+ // If this fails, then alignment of elements after the first could be wrong, 399*4882a593Smuzhiyun+ // and we need to pad sizes to fix that. 400*4882a593Smuzhiyun+ DCHECK_EQ(element_size % alignment, 0u); 401*4882a593Smuzhiyun+ AllocateNewList(element_count > 0 ? element_count 402*4882a593Smuzhiyun+ : kDefaultNumElementTypesToReserve); 403*4882a593Smuzhiyun+ last_list_ = storage_[last_list_index_].get(); 404*4882a593Smuzhiyun+ } 405*4882a593Smuzhiyun+ 406*4882a593Smuzhiyun+ CharAllocator(const CharAllocator&) = delete; 407*4882a593Smuzhiyun+ ~CharAllocator() = default; 408*4882a593Smuzhiyun+ 409*4882a593Smuzhiyun+ CharAllocator& operator=(const CharAllocator&) = delete; 410*4882a593Smuzhiyun+ 411*4882a593Smuzhiyun+ void* Allocate() { 412*4882a593Smuzhiyun+ if (last_list_->IsFull()) { 413*4882a593Smuzhiyun+ // Only allocate a new list if there isn't a spare one still there from 414*4882a593Smuzhiyun+ // previous usage. 415*4882a593Smuzhiyun+ if (last_list_index_ + 1 >= storage_.size()) 416*4882a593Smuzhiyun+ AllocateNewList(last_list_->capacity * 2); 417*4882a593Smuzhiyun+ 418*4882a593Smuzhiyun+ ++last_list_index_; 419*4882a593Smuzhiyun+ last_list_ = storage_[last_list_index_].get(); 420*4882a593Smuzhiyun+ } 421*4882a593Smuzhiyun+ 422*4882a593Smuzhiyun+ ++size_; 423*4882a593Smuzhiyun+ return last_list_->AddElement(); 424*4882a593Smuzhiyun+ } 425*4882a593Smuzhiyun+ 426*4882a593Smuzhiyun+ size_t alignment() const { return alignment_; } 427*4882a593Smuzhiyun+ size_t element_size() const { return element_size_; } 428*4882a593Smuzhiyun+ size_t list_count() const { return storage_.size(); } 429*4882a593Smuzhiyun+ size_t size() const { return size_; } 430*4882a593Smuzhiyun+ bool IsEmpty() const { return size() == 0; } 431*4882a593Smuzhiyun+ 432*4882a593Smuzhiyun+ size_t Capacity() const { 433*4882a593Smuzhiyun+ size_t capacity_sum = 0; 434*4882a593Smuzhiyun+ for (const auto& inner_list : storage_) 435*4882a593Smuzhiyun+ capacity_sum += inner_list->capacity; 436*4882a593Smuzhiyun+ return capacity_sum; 437*4882a593Smuzhiyun+ } 438*4882a593Smuzhiyun+ 439*4882a593Smuzhiyun+ void Clear() { 440*4882a593Smuzhiyun+ // Remove all except for the first InnerList. 441*4882a593Smuzhiyun+ DCHECK(!storage_.empty()); 442*4882a593Smuzhiyun+ storage_.erase(storage_.begin() + 1, storage_.end()); 443*4882a593Smuzhiyun+ last_list_index_ = 0; 444*4882a593Smuzhiyun+ last_list_ = storage_[0].get(); 445*4882a593Smuzhiyun+ last_list_->size = 0; 446*4882a593Smuzhiyun+ size_ = 0; 447*4882a593Smuzhiyun+ } 448*4882a593Smuzhiyun+ 449*4882a593Smuzhiyun+ void RemoveLast() { 450*4882a593Smuzhiyun+ DCHECK(!IsEmpty()); 451*4882a593Smuzhiyun+ last_list_->RemoveLast(); 452*4882a593Smuzhiyun+ if (last_list_->IsEmpty() && last_list_index_ > 0) { 453*4882a593Smuzhiyun+ --last_list_index_; 454*4882a593Smuzhiyun+ last_list_ = storage_[last_list_index_].get(); 455*4882a593Smuzhiyun+ 456*4882a593Smuzhiyun+ // If there are now two empty inner lists, free one of them. 457*4882a593Smuzhiyun+ if (last_list_index_ + 2 < storage_.size()) 458*4882a593Smuzhiyun+ storage_.pop_back(); 459*4882a593Smuzhiyun+ } 460*4882a593Smuzhiyun+ --size_; 461*4882a593Smuzhiyun+ } 462*4882a593Smuzhiyun+ 463*4882a593Smuzhiyun+ void Erase(PositionInCharAllocator* position) { 464*4882a593Smuzhiyun+ DCHECK_EQ(this, position->ptr_to_container); 465*4882a593Smuzhiyun+ 466*4882a593Smuzhiyun+ // Update |position| to point to the element after the erased element. 467*4882a593Smuzhiyun+ InnerList* list = storage_[position->vector_index].get(); 468*4882a593Smuzhiyun+ char* item_iterator = position->item_iterator; 469*4882a593Smuzhiyun+ if (item_iterator == list->LastElement()) 470*4882a593Smuzhiyun+ position->Increment(); 471*4882a593Smuzhiyun+ 472*4882a593Smuzhiyun+ list->Erase(item_iterator); 473*4882a593Smuzhiyun+ // TODO(weiliangc): Free the InnerList if it is empty. 474*4882a593Smuzhiyun+ --size_; 475*4882a593Smuzhiyun+ } 476*4882a593Smuzhiyun+ 477*4882a593Smuzhiyun+ void InsertBefore(ListContainerHelper::Iterator* position, size_t count) { 478*4882a593Smuzhiyun+ if (!count) 479*4882a593Smuzhiyun+ return; 480*4882a593Smuzhiyun+ 481*4882a593Smuzhiyun+ // If |position| is End(), then append |count| elements at the end. This 482*4882a593Smuzhiyun+ // will happen to not invalidate any iterators or memory. 483*4882a593Smuzhiyun+ if (!position->item_iterator) { 484*4882a593Smuzhiyun+ // Set |position| to be the first inserted element. 485*4882a593Smuzhiyun+ Allocate(); 486*4882a593Smuzhiyun+ position->vector_index = storage_.size() - 1; 487*4882a593Smuzhiyun+ position->item_iterator = storage_[position->vector_index]->LastElement(); 488*4882a593Smuzhiyun+ // Allocate the rest. 489*4882a593Smuzhiyun+ for (size_t i = 1; i < count; ++i) 490*4882a593Smuzhiyun+ Allocate(); 491*4882a593Smuzhiyun+ } else { 492*4882a593Smuzhiyun+ storage_[position->vector_index]->InsertBefore( 493*4882a593Smuzhiyun+ alignment_, &position->item_iterator, count); 494*4882a593Smuzhiyun+ size_ += count; 495*4882a593Smuzhiyun+ } 496*4882a593Smuzhiyun+ } 497*4882a593Smuzhiyun+ 498*4882a593Smuzhiyun+ InnerList* InnerListById(size_t id) const { 499*4882a593Smuzhiyun+ DCHECK_LT(id, storage_.size()); 500*4882a593Smuzhiyun+ return storage_[id].get(); 501*4882a593Smuzhiyun+ } 502*4882a593Smuzhiyun+ 503*4882a593Smuzhiyun+ size_t FirstInnerListId() const { 504*4882a593Smuzhiyun+ // |size_| > 0 means that at least one vector in |storage_| will be 505*4882a593Smuzhiyun+ // non-empty. 506*4882a593Smuzhiyun+ DCHECK_GT(size_, 0u); 507*4882a593Smuzhiyun+ size_t id = 0; 508*4882a593Smuzhiyun+ while (storage_[id]->size == 0) 509*4882a593Smuzhiyun+ ++id; 510*4882a593Smuzhiyun+ return id; 511*4882a593Smuzhiyun+ } 512*4882a593Smuzhiyun+ 513*4882a593Smuzhiyun+ size_t LastInnerListId() const { 514*4882a593Smuzhiyun+ // |size_| > 0 means that at least one vector in |storage_| will be 515*4882a593Smuzhiyun+ // non-empty. 516*4882a593Smuzhiyun+ DCHECK_GT(size_, 0u); 517*4882a593Smuzhiyun+ size_t id = storage_.size() - 1; 518*4882a593Smuzhiyun+ while (storage_[id]->size == 0) 519*4882a593Smuzhiyun+ --id; 520*4882a593Smuzhiyun+ return id; 521*4882a593Smuzhiyun+ } 522*4882a593Smuzhiyun+ 523*4882a593Smuzhiyun+ size_t NumAvailableElementsInLastList() const { 524*4882a593Smuzhiyun+ return last_list_->NumElementsAvailable(); 525*4882a593Smuzhiyun+ } 526*4882a593Smuzhiyun+ 527*4882a593Smuzhiyun+ private: 528*4882a593Smuzhiyun+ void AllocateNewList(size_t list_size) { 529*4882a593Smuzhiyun+ std::unique_ptr<InnerList> new_list(new InnerList); 530*4882a593Smuzhiyun+ new_list->capacity = list_size; 531*4882a593Smuzhiyun+ new_list->size = 0; 532*4882a593Smuzhiyun+ new_list->step = element_size_; 533*4882a593Smuzhiyun+ new_list->data.reset(static_cast<char*>( 534*4882a593Smuzhiyun+ base::AlignedAlloc(list_size * element_size_, alignment_))); 535*4882a593Smuzhiyun+ storage_.push_back(std::move(new_list)); 536*4882a593Smuzhiyun+ } 537*4882a593Smuzhiyun+ 538*4882a593Smuzhiyun+ std::vector<std::unique_ptr<InnerList>> storage_; 539*4882a593Smuzhiyun+ const size_t alignment_; 540*4882a593Smuzhiyun+ const size_t element_size_; 541*4882a593Smuzhiyun+ 542*4882a593Smuzhiyun+ // The number of elements in the list. 543*4882a593Smuzhiyun+ size_t size_; 544*4882a593Smuzhiyun+ 545*4882a593Smuzhiyun+ // The index of the last list to have had elements added to it, or the only 546*4882a593Smuzhiyun+ // list if the container has not had elements added since being cleared. 547*4882a593Smuzhiyun+ size_t last_list_index_; 548*4882a593Smuzhiyun+ 549*4882a593Smuzhiyun+ // This is equivalent to |storage_[last_list_index_]|. 550*4882a593Smuzhiyun+ InnerList* last_list_; 551*4882a593Smuzhiyun+}; 552*4882a593Smuzhiyun+ 553*4882a593Smuzhiyun } // namespace cc 554*4882a593Smuzhiyun 555*4882a593Smuzhiyun #endif // CC_BASE_LIST_CONTAINER_HELPER_H_ 556