1 /* 2 * Copyright 2012, The Android Open Source Project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #ifndef ANDROID_LINEARALLOCATOR_H 27 #define ANDROID_LINEARALLOCATOR_H 28 29 #include <stddef.h> 30 #include <type_traits> 31 32 namespace android { 33 namespace uirenderer { 34 35 /** 36 * A memory manager that internally allocates multi-kbyte buffers for placing objects in. It avoids 37 * the overhead of malloc when many objects are allocated. It is most useful when creating many 38 * small objects with a similar lifetime, and doesn't add significant overhead for large 39 * allocations. 40 */ 41 class LinearAllocator { 42 public: 43 LinearAllocator(); 44 ~LinearAllocator(); 45 46 /** 47 * Reserves and returns a region of memory of at least size 'size', aligning as needed. 48 * Typically this is used in an object's overridden new() method or as a replacement for malloc. 49 * 50 * The lifetime of the returned buffers is tied to that of the LinearAllocator. If calling 51 * delete() on an object stored in a buffer is needed, it should be overridden to use 52 * rewindIfLastAlloc() 53 */ 54 void* alloc(size_t size); 55 56 /** 57 * Allocates an instance of the template type with the default constructor 58 * and adds it to the automatic destruction list. 59 */ 60 template<class T> alloc()61 T* alloc() { 62 T* ret = new (*this) T; 63 autoDestroy(ret); 64 return ret; 65 } 66 67 /** 68 * Adds the pointer to the tracking list to have its destructor called 69 * when the LinearAllocator is destroyed. 70 */ 71 template<class T> autoDestroy(T * addr)72 void autoDestroy(T* addr) { 73 if (!std::is_trivially_destructible<T>::value) { 74 auto dtor = [](void* addr) { ((T*)addr)->~T(); }; 75 addToDestructionList(dtor, addr); 76 } 77 } 78 79 /** 80 * Attempt to deallocate the given buffer, with the LinearAllocator attempting to rewind its 81 * state if possible. 82 */ 83 void rewindIfLastAlloc(void* ptr, size_t allocSize); 84 85 /** 86 * Same as rewindIfLastAlloc(void*, size_t) 87 */ 88 template<class T> rewindIfLastAlloc(T * ptr)89 void rewindIfLastAlloc(T* ptr) { 90 rewindIfLastAlloc((void*)ptr, sizeof(T)); 91 } 92 93 /** 94 * Dump memory usage statistics to the log (allocated and wasted space) 95 */ 96 void dumpMemoryStats(const char* prefix = ""); 97 98 /** 99 * The number of bytes used for buffers allocated in the LinearAllocator (does not count space 100 * wasted) 101 */ usedSize()102 size_t usedSize() const { return mTotalAllocated - mWastedSpace; } 103 104 private: 105 LinearAllocator(const LinearAllocator& other); 106 107 class Page; 108 typedef void (*Destructor)(void* addr); 109 struct DestructorNode { 110 Destructor dtor; 111 void* addr; 112 DestructorNode* next = nullptr; 113 }; 114 115 void addToDestructionList(Destructor, void* addr); 116 void runDestructorFor(void* addr); 117 Page* newPage(size_t pageSize); 118 bool fitsInCurrentPage(size_t size); 119 void ensureNext(size_t size); 120 void* start(Page *p); 121 void* end(Page* p); 122 123 size_t mPageSize; 124 size_t mMaxAllocSize; 125 void* mNext; 126 Page* mCurrentPage; 127 Page* mPages; 128 DestructorNode* mDtorList = nullptr; 129 130 // Memory usage tracking 131 size_t mTotalAllocated; 132 size_t mWastedSpace; 133 size_t mPageCount; 134 size_t mDedicatedPageCount; 135 }; 136 137 }; // namespace uirenderer 138 }; // namespace android 139 140 void* operator new(std::size_t size, android::uirenderer::LinearAllocator& la); 141 142 #endif // ANDROID_LINEARALLOCATOR_H 143