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