1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file. 4*635a8641SAndroid Build Coastguard Worker 5*635a8641SAndroid Build Coastguard Worker #ifndef BASE_CONTAINERS_STACK_CONTAINER_H_ 6*635a8641SAndroid Build Coastguard Worker #define BASE_CONTAINERS_STACK_CONTAINER_H_ 7*635a8641SAndroid Build Coastguard Worker 8*635a8641SAndroid Build Coastguard Worker #include <stddef.h> 9*635a8641SAndroid Build Coastguard Worker 10*635a8641SAndroid Build Coastguard Worker #include <vector> 11*635a8641SAndroid Build Coastguard Worker 12*635a8641SAndroid Build Coastguard Worker #include "base/macros.h" 13*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h" 14*635a8641SAndroid Build Coastguard Worker 15*635a8641SAndroid Build Coastguard Worker namespace base { 16*635a8641SAndroid Build Coastguard Worker 17*635a8641SAndroid Build Coastguard Worker // This allocator can be used with STL containers to provide a stack buffer 18*635a8641SAndroid Build Coastguard Worker // from which to allocate memory and overflows onto the heap. This stack buffer 19*635a8641SAndroid Build Coastguard Worker // would be allocated on the stack and allows us to avoid heap operations in 20*635a8641SAndroid Build Coastguard Worker // some situations. 21*635a8641SAndroid Build Coastguard Worker // 22*635a8641SAndroid Build Coastguard Worker // STL likes to make copies of allocators, so the allocator itself can't hold 23*635a8641SAndroid Build Coastguard Worker // the data. Instead, we make the creator responsible for creating a 24*635a8641SAndroid Build Coastguard Worker // StackAllocator::Source which contains the data. Copying the allocator 25*635a8641SAndroid Build Coastguard Worker // merely copies the pointer to this shared source, so all allocators created 26*635a8641SAndroid Build Coastguard Worker // based on our allocator will share the same stack buffer. 27*635a8641SAndroid Build Coastguard Worker // 28*635a8641SAndroid Build Coastguard Worker // This stack buffer implementation is very simple. The first allocation that 29*635a8641SAndroid Build Coastguard Worker // fits in the stack buffer will use the stack buffer. Any subsequent 30*635a8641SAndroid Build Coastguard Worker // allocations will not use the stack buffer, even if there is unused room. 31*635a8641SAndroid Build Coastguard Worker // This makes it appropriate for array-like containers, but the caller should 32*635a8641SAndroid Build Coastguard Worker // be sure to reserve() in the container up to the stack buffer size. Otherwise 33*635a8641SAndroid Build Coastguard Worker // the container will allocate a small array which will "use up" the stack 34*635a8641SAndroid Build Coastguard Worker // buffer. 35*635a8641SAndroid Build Coastguard Worker template<typename T, size_t stack_capacity> 36*635a8641SAndroid Build Coastguard Worker class StackAllocator : public std::allocator<T> { 37*635a8641SAndroid Build Coastguard Worker public: 38*635a8641SAndroid Build Coastguard Worker typedef T* pointer; 39*635a8641SAndroid Build Coastguard Worker typedef typename std::allocator<T>::size_type size_type; 40*635a8641SAndroid Build Coastguard Worker 41*635a8641SAndroid Build Coastguard Worker // Backing store for the allocator. The container owner is responsible for 42*635a8641SAndroid Build Coastguard Worker // maintaining this for as long as any containers using this allocator are 43*635a8641SAndroid Build Coastguard Worker // live. 44*635a8641SAndroid Build Coastguard Worker struct Source { SourceSource45*635a8641SAndroid Build Coastguard Worker Source() : used_stack_buffer_(false) { 46*635a8641SAndroid Build Coastguard Worker } 47*635a8641SAndroid Build Coastguard Worker 48*635a8641SAndroid Build Coastguard Worker // Casts the buffer in its right type. stack_bufferSource49*635a8641SAndroid Build Coastguard Worker T* stack_buffer() { return reinterpret_cast<T*>(stack_buffer_); } stack_bufferSource50*635a8641SAndroid Build Coastguard Worker const T* stack_buffer() const { 51*635a8641SAndroid Build Coastguard Worker return reinterpret_cast<const T*>(&stack_buffer_); 52*635a8641SAndroid Build Coastguard Worker } 53*635a8641SAndroid Build Coastguard Worker 54*635a8641SAndroid Build Coastguard Worker // The buffer itself. It is not of type T because we don't want the 55*635a8641SAndroid Build Coastguard Worker // constructors and destructors to be automatically called. Define a POD 56*635a8641SAndroid Build Coastguard Worker // buffer of the right size instead. 57*635a8641SAndroid Build Coastguard Worker alignas(T) char stack_buffer_[sizeof(T[stack_capacity])]; 58*635a8641SAndroid Build Coastguard Worker #if defined(__GNUC__) && !defined(ARCH_CPU_X86_FAMILY) 59*635a8641SAndroid Build Coastguard Worker static_assert(alignof(T) <= 16, "http://crbug.com/115612"); 60*635a8641SAndroid Build Coastguard Worker #endif 61*635a8641SAndroid Build Coastguard Worker 62*635a8641SAndroid Build Coastguard Worker // Set when the stack buffer is used for an allocation. We do not track 63*635a8641SAndroid Build Coastguard Worker // how much of the buffer is used, only that somebody is using it. 64*635a8641SAndroid Build Coastguard Worker bool used_stack_buffer_; 65*635a8641SAndroid Build Coastguard Worker }; 66*635a8641SAndroid Build Coastguard Worker 67*635a8641SAndroid Build Coastguard Worker // Used by containers when they want to refer to an allocator of type U. 68*635a8641SAndroid Build Coastguard Worker template<typename U> 69*635a8641SAndroid Build Coastguard Worker struct rebind { 70*635a8641SAndroid Build Coastguard Worker typedef StackAllocator<U, stack_capacity> other; 71*635a8641SAndroid Build Coastguard Worker }; 72*635a8641SAndroid Build Coastguard Worker 73*635a8641SAndroid Build Coastguard Worker // For the straight up copy c-tor, we can share storage. StackAllocator(const StackAllocator<T,stack_capacity> & rhs)74*635a8641SAndroid Build Coastguard Worker StackAllocator(const StackAllocator<T, stack_capacity>& rhs) 75*635a8641SAndroid Build Coastguard Worker : std::allocator<T>(), source_(rhs.source_) { 76*635a8641SAndroid Build Coastguard Worker } 77*635a8641SAndroid Build Coastguard Worker 78*635a8641SAndroid Build Coastguard Worker // ISO C++ requires the following constructor to be defined, 79*635a8641SAndroid Build Coastguard Worker // and std::vector in VC++2008SP1 Release fails with an error 80*635a8641SAndroid Build Coastguard Worker // in the class _Container_base_aux_alloc_real (from <xutility>) 81*635a8641SAndroid Build Coastguard Worker // if the constructor does not exist. 82*635a8641SAndroid Build Coastguard Worker // For this constructor, we cannot share storage; there's 83*635a8641SAndroid Build Coastguard Worker // no guarantee that the Source buffer of Ts is large enough 84*635a8641SAndroid Build Coastguard Worker // for Us. 85*635a8641SAndroid Build Coastguard Worker // TODO: If we were fancy pants, perhaps we could share storage 86*635a8641SAndroid Build Coastguard Worker // iff sizeof(T) == sizeof(U). 87*635a8641SAndroid Build Coastguard Worker template<typename U, size_t other_capacity> StackAllocator(const StackAllocator<U,other_capacity> & other)88*635a8641SAndroid Build Coastguard Worker StackAllocator(const StackAllocator<U, other_capacity>& other) 89*635a8641SAndroid Build Coastguard Worker : source_(NULL) { 90*635a8641SAndroid Build Coastguard Worker } 91*635a8641SAndroid Build Coastguard Worker 92*635a8641SAndroid Build Coastguard Worker // This constructor must exist. It creates a default allocator that doesn't 93*635a8641SAndroid Build Coastguard Worker // actually have a stack buffer. glibc's std::string() will compare the 94*635a8641SAndroid Build Coastguard Worker // current allocator against the default-constructed allocator, so this 95*635a8641SAndroid Build Coastguard Worker // should be fast. StackAllocator()96*635a8641SAndroid Build Coastguard Worker StackAllocator() : source_(NULL) { 97*635a8641SAndroid Build Coastguard Worker } 98*635a8641SAndroid Build Coastguard Worker StackAllocator(Source * source)99*635a8641SAndroid Build Coastguard Worker explicit StackAllocator(Source* source) : source_(source) { 100*635a8641SAndroid Build Coastguard Worker } 101*635a8641SAndroid Build Coastguard Worker 102*635a8641SAndroid Build Coastguard Worker // Actually do the allocation. Use the stack buffer if nobody has used it yet 103*635a8641SAndroid Build Coastguard Worker // and the size requested fits. Otherwise, fall through to the standard 104*635a8641SAndroid Build Coastguard Worker // allocator. allocate(size_type n)105*635a8641SAndroid Build Coastguard Worker pointer allocate(size_type n) { 106*635a8641SAndroid Build Coastguard Worker if (source_ != NULL && !source_->used_stack_buffer_ 107*635a8641SAndroid Build Coastguard Worker && n <= stack_capacity) { 108*635a8641SAndroid Build Coastguard Worker source_->used_stack_buffer_ = true; 109*635a8641SAndroid Build Coastguard Worker return source_->stack_buffer(); 110*635a8641SAndroid Build Coastguard Worker } else { 111*635a8641SAndroid Build Coastguard Worker return std::allocator<T>::allocate(n); 112*635a8641SAndroid Build Coastguard Worker } 113*635a8641SAndroid Build Coastguard Worker } 114*635a8641SAndroid Build Coastguard Worker 115*635a8641SAndroid Build Coastguard Worker // Free: when trying to free the stack buffer, just mark it as free. For 116*635a8641SAndroid Build Coastguard Worker // non-stack-buffer pointers, just fall though to the standard allocator. deallocate(pointer p,size_type n)117*635a8641SAndroid Build Coastguard Worker void deallocate(pointer p, size_type n) { 118*635a8641SAndroid Build Coastguard Worker if (source_ != NULL && p == source_->stack_buffer()) 119*635a8641SAndroid Build Coastguard Worker source_->used_stack_buffer_ = false; 120*635a8641SAndroid Build Coastguard Worker else 121*635a8641SAndroid Build Coastguard Worker std::allocator<T>::deallocate(p, n); 122*635a8641SAndroid Build Coastguard Worker } 123*635a8641SAndroid Build Coastguard Worker 124*635a8641SAndroid Build Coastguard Worker private: 125*635a8641SAndroid Build Coastguard Worker Source* source_; 126*635a8641SAndroid Build Coastguard Worker }; 127*635a8641SAndroid Build Coastguard Worker 128*635a8641SAndroid Build Coastguard Worker // A wrapper around STL containers that maintains a stack-sized buffer that the 129*635a8641SAndroid Build Coastguard Worker // initial capacity of the vector is based on. Growing the container beyond the 130*635a8641SAndroid Build Coastguard Worker // stack capacity will transparently overflow onto the heap. The container must 131*635a8641SAndroid Build Coastguard Worker // support reserve(). 132*635a8641SAndroid Build Coastguard Worker // 133*635a8641SAndroid Build Coastguard Worker // This will not work with std::string since some implementations allocate 134*635a8641SAndroid Build Coastguard Worker // more bytes than requested in calls to reserve(), forcing the allocation onto 135*635a8641SAndroid Build Coastguard Worker // the heap. http://crbug.com/709273 136*635a8641SAndroid Build Coastguard Worker // 137*635a8641SAndroid Build Coastguard Worker // WATCH OUT: the ContainerType MUST use the proper StackAllocator for this 138*635a8641SAndroid Build Coastguard Worker // type. This object is really intended to be used only internally. You'll want 139*635a8641SAndroid Build Coastguard Worker // to use the wrappers below for different types. 140*635a8641SAndroid Build Coastguard Worker template<typename TContainerType, int stack_capacity> 141*635a8641SAndroid Build Coastguard Worker class StackContainer { 142*635a8641SAndroid Build Coastguard Worker public: 143*635a8641SAndroid Build Coastguard Worker typedef TContainerType ContainerType; 144*635a8641SAndroid Build Coastguard Worker typedef typename ContainerType::value_type ContainedType; 145*635a8641SAndroid Build Coastguard Worker typedef StackAllocator<ContainedType, stack_capacity> Allocator; 146*635a8641SAndroid Build Coastguard Worker 147*635a8641SAndroid Build Coastguard Worker // Allocator must be constructed before the container! StackContainer()148*635a8641SAndroid Build Coastguard Worker StackContainer() : allocator_(&stack_data_), container_(allocator_) { 149*635a8641SAndroid Build Coastguard Worker // Make the container use the stack allocation by reserving our buffer size 150*635a8641SAndroid Build Coastguard Worker // before doing anything else. 151*635a8641SAndroid Build Coastguard Worker container_.reserve(stack_capacity); 152*635a8641SAndroid Build Coastguard Worker } 153*635a8641SAndroid Build Coastguard Worker 154*635a8641SAndroid Build Coastguard Worker // Getters for the actual container. 155*635a8641SAndroid Build Coastguard Worker // 156*635a8641SAndroid Build Coastguard Worker // Danger: any copies of this made using the copy constructor must have 157*635a8641SAndroid Build Coastguard Worker // shorter lifetimes than the source. The copy will share the same allocator 158*635a8641SAndroid Build Coastguard Worker // and therefore the same stack buffer as the original. Use std::copy to 159*635a8641SAndroid Build Coastguard Worker // copy into a "real" container for longer-lived objects. container()160*635a8641SAndroid Build Coastguard Worker ContainerType& container() { return container_; } container()161*635a8641SAndroid Build Coastguard Worker const ContainerType& container() const { return container_; } 162*635a8641SAndroid Build Coastguard Worker 163*635a8641SAndroid Build Coastguard Worker // Support operator-> to get to the container. This allows nicer syntax like: 164*635a8641SAndroid Build Coastguard Worker // StackContainer<...> foo; 165*635a8641SAndroid Build Coastguard Worker // std::sort(foo->begin(), foo->end()); 166*635a8641SAndroid Build Coastguard Worker ContainerType* operator->() { return &container_; } 167*635a8641SAndroid Build Coastguard Worker const ContainerType* operator->() const { return &container_; } 168*635a8641SAndroid Build Coastguard Worker 169*635a8641SAndroid Build Coastguard Worker #ifdef UNIT_TEST 170*635a8641SAndroid Build Coastguard Worker // Retrieves the stack source so that that unit tests can verify that the 171*635a8641SAndroid Build Coastguard Worker // buffer is being used properly. stack_data()172*635a8641SAndroid Build Coastguard Worker const typename Allocator::Source& stack_data() const { 173*635a8641SAndroid Build Coastguard Worker return stack_data_; 174*635a8641SAndroid Build Coastguard Worker } 175*635a8641SAndroid Build Coastguard Worker #endif 176*635a8641SAndroid Build Coastguard Worker 177*635a8641SAndroid Build Coastguard Worker protected: 178*635a8641SAndroid Build Coastguard Worker typename Allocator::Source stack_data_; 179*635a8641SAndroid Build Coastguard Worker Allocator allocator_; 180*635a8641SAndroid Build Coastguard Worker ContainerType container_; 181*635a8641SAndroid Build Coastguard Worker 182*635a8641SAndroid Build Coastguard Worker private: 183*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(StackContainer); 184*635a8641SAndroid Build Coastguard Worker }; 185*635a8641SAndroid Build Coastguard Worker 186*635a8641SAndroid Build Coastguard Worker // StackVector ----------------------------------------------------------------- 187*635a8641SAndroid Build Coastguard Worker 188*635a8641SAndroid Build Coastguard Worker // Example: 189*635a8641SAndroid Build Coastguard Worker // StackVector<int, 16> foo; 190*635a8641SAndroid Build Coastguard Worker // foo->push_back(22); // we have overloaded operator-> 191*635a8641SAndroid Build Coastguard Worker // foo[0] = 10; // as well as operator[] 192*635a8641SAndroid Build Coastguard Worker template<typename T, size_t stack_capacity> 193*635a8641SAndroid Build Coastguard Worker class StackVector : public StackContainer< 194*635a8641SAndroid Build Coastguard Worker std::vector<T, StackAllocator<T, stack_capacity> >, 195*635a8641SAndroid Build Coastguard Worker stack_capacity> { 196*635a8641SAndroid Build Coastguard Worker public: StackVector()197*635a8641SAndroid Build Coastguard Worker StackVector() : StackContainer< 198*635a8641SAndroid Build Coastguard Worker std::vector<T, StackAllocator<T, stack_capacity> >, 199*635a8641SAndroid Build Coastguard Worker stack_capacity>() { 200*635a8641SAndroid Build Coastguard Worker } 201*635a8641SAndroid Build Coastguard Worker 202*635a8641SAndroid Build Coastguard Worker // We need to put this in STL containers sometimes, which requires a copy 203*635a8641SAndroid Build Coastguard Worker // constructor. We can't call the regular copy constructor because that will 204*635a8641SAndroid Build Coastguard Worker // take the stack buffer from the original. Here, we create an empty object 205*635a8641SAndroid Build Coastguard Worker // and make a stack buffer of its own. StackVector(const StackVector<T,stack_capacity> & other)206*635a8641SAndroid Build Coastguard Worker StackVector(const StackVector<T, stack_capacity>& other) 207*635a8641SAndroid Build Coastguard Worker : StackContainer< 208*635a8641SAndroid Build Coastguard Worker std::vector<T, StackAllocator<T, stack_capacity> >, 209*635a8641SAndroid Build Coastguard Worker stack_capacity>() { 210*635a8641SAndroid Build Coastguard Worker this->container().assign(other->begin(), other->end()); 211*635a8641SAndroid Build Coastguard Worker } 212*635a8641SAndroid Build Coastguard Worker 213*635a8641SAndroid Build Coastguard Worker StackVector<T, stack_capacity>& operator=( 214*635a8641SAndroid Build Coastguard Worker const StackVector<T, stack_capacity>& other) { 215*635a8641SAndroid Build Coastguard Worker this->container().assign(other->begin(), other->end()); 216*635a8641SAndroid Build Coastguard Worker return *this; 217*635a8641SAndroid Build Coastguard Worker } 218*635a8641SAndroid Build Coastguard Worker 219*635a8641SAndroid Build Coastguard Worker // Vectors are commonly indexed, which isn't very convenient even with 220*635a8641SAndroid Build Coastguard Worker // operator-> (using "->at()" does exception stuff we don't want). 221*635a8641SAndroid Build Coastguard Worker T& operator[](size_t i) { return this->container().operator[](i); } 222*635a8641SAndroid Build Coastguard Worker const T& operator[](size_t i) const { 223*635a8641SAndroid Build Coastguard Worker return this->container().operator[](i); 224*635a8641SAndroid Build Coastguard Worker } 225*635a8641SAndroid Build Coastguard Worker }; 226*635a8641SAndroid Build Coastguard Worker 227*635a8641SAndroid Build Coastguard Worker } // namespace base 228*635a8641SAndroid Build Coastguard Worker 229*635a8641SAndroid Build Coastguard Worker #endif // BASE_CONTAINERS_STACK_CONTAINER_H_ 230