LinearAllocator.h revision 499d83f21e7ffb687788bba1668b05fe38f6ebaf
156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi/* 256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Copyright 2012, The Android Open Source Project 356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * 456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Redistribution and use in source and binary forms, with or without 556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * modification, are permitted provided that the following conditions 656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * are met: 756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * * Redistributions of source code must retain the above copyright 856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * notice, this list of conditions and the following disclaimer. 956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * * Redistributions in binary form must reproduce the above copyright 1056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * notice, this list of conditions and the following disclaimer in the 1156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * documentation and/or other materials provided with the distribution. 1256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * 1356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 1456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 1756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 1856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 1956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20ad3183e2d4cecd02f6261270a7ea1c68be0efa0fFrançois Gaffie * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21ad3183e2d4cecd02f6261270a7ea1c68be0efa0fFrançois Gaffie * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2298cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie */ 2556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi 2656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi#ifndef ANDROID_LINEARALLOCATOR_H 2756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi#define ANDROID_LINEARALLOCATOR_H 28a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie 29a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie#include <stddef.h> 30a13cde98a880341f0a56d91da6364b093fb5d24eGlenn Kasten#include <type_traits> 31a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie 3256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi#include <vector> 3356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi 3456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivinamespace android { 3556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivinamespace uirenderer { 3656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi 3756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi/** 38a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie * A memory manager that internally allocates multi-kbyte buffers for placing objects in. It avoids 3956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * the overhead of malloc when many objects are allocated. It is most useful when creating many 4056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * small objects with a similar lifetime, and doesn't add significant overhead for large 41a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie * allocations. 4256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi */ 4356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Triviclass LinearAllocator { 4456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivipublic: 4556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi LinearAllocator(); 46112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie ~LinearAllocator(); 4756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi 48a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie /** 4956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Reserves and returns a region of memory of at least size 'size', aligning as needed. 50112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * Typically this is used in an object's overridden new() method or as a replacement for malloc. 51112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie * 5256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * The lifetime of the returned buffers is tied to that of the LinearAllocator. If calling 537288ab87a7aa730ffe97d7dc7e118123107bfceaEric Laurent * delete() on an object stored in a buffer is needed, it should be overridden to use 5456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * rewindIfLastAlloc() 55a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie * 5656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Note that unlike create, for alloc the type is purely for compile-time error 57a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie * checking and does not affect size. 58a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie */ 59a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie template<class T> 60a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie void* alloc(size_t size) { 61a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie static_assert(std::is_trivially_destructible<T>::value, 62322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent "Error, type is non-trivial! did you mean to use create()?"); 6356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi return allocImpl(size); 64cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie } 65a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie 66a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie /** 6756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Allocates an instance of the template type with the given construction parameters 68a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie * and adds it to the automatic destruction list. 69a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie */ 70a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie template<class T, typename... Params> 71a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie T* create(Params&&... params) { 72cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie T* ret = new (allocImpl(sizeof(T))) T(std::forward<Params>(params)...); 7356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi if (!std::is_trivially_destructible<T>::value) { 7456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi auto dtor = [](void* ret) { ((T*)ret)->~T(); }; 7556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi addToDestructionList(dtor, ret); 76a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie } 77a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie return ret; 78a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie } 79a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie 80a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie template<class T, typename... Params> 81a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie T* create_trivial(Params&&... params) { 82a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie static_assert(std::is_trivially_destructible<T>::value, 83a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie "Error, called create_trivial on a non-trivial type"); 84a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie return new (allocImpl(sizeof(T))) T(std::forward<Params>(params)...); 85a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie } 86a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie 87a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie /** 88a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie * Attempt to deallocate the given buffer, with the LinearAllocator attempting to rewind its 89a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie * state if possible. 90a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie */ 91a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie void rewindIfLastAlloc(void* ptr, size_t allocSize); 92a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie 93a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie /** 94a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie * Same as rewindIfLastAlloc(void*, size_t) 95a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie */ 9656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi template<class T> 9756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi void rewindIfLastAlloc(T* ptr) { 9856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi rewindIfLastAlloc((void*)ptr, sizeof(T)); 99a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie } 10056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi 10156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi /** 10256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Dump memory usage statistics to the log (allocated and wasted space) 10356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi */ 10456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi void dumpMemoryStats(const char* prefix = ""); 10556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi 10656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi /** 10756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * The number of bytes used for buffers allocated in the LinearAllocator (does not count space 10856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * wasted) 109112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie */ 11056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi size_t usedSize() const { return mTotalAllocated - mWastedSpace; } 111a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie 112112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffieprivate: 113112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie LinearAllocator(const LinearAllocator& other); 11456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi 1157288ab87a7aa730ffe97d7dc7e118123107bfceaEric Laurent class Page; 11656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi typedef void (*Destructor)(void* addr); 117a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie struct DestructorNode { 11856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi Destructor dtor; 1197b279bbc24139ee1e01b58055ca94926ec18e2e9Eric Laurent void* addr; 1207b279bbc24139ee1e01b58055ca94926ec18e2e9Eric Laurent DestructorNode* next = nullptr; 12156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi }; 122a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie 12356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi void* allocImpl(size_t size); 12456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi 12556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi void addToDestructionList(Destructor, void* addr); 12656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi void runDestructorFor(void* addr); 12756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi Page* newPage(size_t pageSize); 128a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie bool fitsInCurrentPage(size_t size); 12956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi void ensureNext(size_t size); 13056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi void* start(Page *p); 13156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi void* end(Page* p); 13256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi 13356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi size_t mPageSize; 13456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi size_t mMaxAllocSize; 13556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi void* mNext; 13656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi Page* mCurrentPage; 137cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie Page* mPages; 138cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie DestructorNode* mDtorList = nullptr; 139cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie 140cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie // Memory usage tracking 141cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie size_t mTotalAllocated; 142cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie size_t mWastedSpace; 143cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie size_t mPageCount; 144cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie size_t mDedicatedPageCount; 145cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie}; 146cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie 147cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffietemplate <class T> 148cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffieclass LinearStdAllocator { 149cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffiepublic: 150cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie typedef T value_type; // needed to implement std::allocator 151cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie typedef T* pointer; // needed to implement std::allocator 152cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie 153cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie LinearStdAllocator(LinearAllocator& allocator) 154cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie : linearAllocator(allocator) {} 155cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie LinearStdAllocator(const LinearStdAllocator& other) 156cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie : linearAllocator(other.linearAllocator) {} 157cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie ~LinearStdAllocator() {} 158cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie 159cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie // rebind marks that allocators can be rebound to different types 160cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie template <class U> 161cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie struct rebind { 162cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie typedef LinearStdAllocator<U> other; 163cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie }; 164cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie // enable allocators to be constructed from other templated types 165cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie template <class U> 166cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie LinearStdAllocator(const LinearStdAllocator<U>& other) 167cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie : linearAllocator(other.linearAllocator) {} 168cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie 169cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie T* allocate(size_t num, const void* = 0) { 170cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie return (T*)(linearAllocator.alloc<void*>(num * sizeof(T))); 171cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie } 172cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie 173cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie void deallocate(pointer p, size_t num) { 174cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie // attempt to rewind, but no guarantees 175cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie linearAllocator.rewindIfLastAlloc(p, num * sizeof(T)); 176cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie } 177cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie 178cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie // public so template copy constructor can access 179cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie LinearAllocator& linearAllocator; 180cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie}; 181cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie 182cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie// return that all specializations of LinearStdAllocator are interchangeable 183cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffietemplate <class T1, class T2> 184cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffiebool operator== (const LinearStdAllocator<T1>&, const LinearStdAllocator<T2>&) { return true; } 185cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffietemplate <class T1, class T2> 186cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffiebool operator!= (const LinearStdAllocator<T1>&, const LinearStdAllocator<T2>&) { return false; } 187cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie 188cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffietemplate <class T> 189cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffieclass LsaVector : public std::vector<T, LinearStdAllocator<T>> { 190cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffiepublic: 191cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie LsaVector(const LinearStdAllocator<T>& allocator) 192cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie : std::vector<T, LinearStdAllocator<T>>(allocator) {} 193cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie}; 194cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie 195cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie}; // namespace uirenderer 196cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie}; // namespace android 197cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie 198cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie#endif // ANDROID_LINEARALLOCATOR_H 199cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie