1 // Copyright 2018 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 #pragma once 15 16 #include "base/AlignedBuf.h" 17 18 #include <vector> 19 #include <unordered_set> 20 21 #include <inttypes.h> 22 23 namespace android { 24 namespace base { 25 26 // Class to make it easier to set up memory regions where it is fast 27 // to allocate buffers AND we don't care about freeing individual pieces, 28 // BUT it's necessary to preserve previous pointer values in between the first 29 // alloc() after a freeAll(), and the freeAll() itself, allowing some sloppy use of 30 // malloc in the first pass while we find out how much data was needed. 31 class BumpPool { 32 public: 33 BumpPool(size_t startingBytes = 4096) : mStorage(startingBytes / sizeof(uint64_t)) { } 34 // All memory allocated by this pool 35 // is automatically deleted when the pool 36 // is deconstructed. ~BumpPool()37 ~BumpPool() { } 38 alloc(size_t wantedSize)39 void* alloc(size_t wantedSize) { 40 size_t wantedSizeRoundedUp = 41 sizeof(uint64_t) * ((wantedSize + sizeof(uint64_t) - 1) / (sizeof(uint64_t))); 42 43 mTotalWantedThisGeneration += wantedSizeRoundedUp; 44 if (mAllocPos + wantedSizeRoundedUp > mStorage.size() * sizeof(uint64_t)) { 45 mNeedRealloc = true; 46 void* fallbackPtr = malloc(wantedSizeRoundedUp); 47 mFallbackPtrs.insert(fallbackPtr); 48 return fallbackPtr; 49 } 50 void* allocPtr = (void*)(((unsigned char*)mStorage.data()) + mAllocPos); 51 mAllocPos += wantedSizeRoundedUp; 52 return allocPtr; 53 } 54 freeAll()55 void freeAll() { 56 mAllocPos = 0; 57 if (mNeedRealloc) { 58 mStorage.resize((mTotalWantedThisGeneration * 2) / sizeof(uint64_t)); 59 mNeedRealloc = false; 60 for (auto ptr : mFallbackPtrs) { 61 free(ptr); 62 } 63 mFallbackPtrs.clear(); 64 } 65 mTotalWantedThisGeneration = 0; 66 } 67 68 // Convenience function to allocate an array 69 // of objects of type T. 70 template <class T> allocArray(size_t count)71 T* allocArray(size_t count) { 72 size_t bytes = sizeof(T) * count; 73 void* res = alloc(bytes); 74 return (T*) res; 75 } 76 strDup(const char * toCopy)77 char* strDup(const char* toCopy) { 78 size_t bytes = strlen(toCopy) + 1; 79 void* res = alloc(bytes); 80 memset(res, 0x0, bytes); 81 memcpy(res, toCopy, bytes); 82 return (char*)res; 83 } 84 strDupArray(const char * const * arrayToCopy,size_t count)85 char** strDupArray(const char* const* arrayToCopy, size_t count) { 86 char** res = allocArray<char*>(count); 87 88 for (size_t i = 0; i < count; i++) { 89 res[i] = strDup(arrayToCopy[i]); 90 } 91 92 return res; 93 } 94 dupArray(const void * buf,size_t bytes)95 void* dupArray(const void* buf, size_t bytes) { 96 void* res = alloc(bytes); 97 memcpy(res, buf, bytes); 98 return res; 99 } 100 101 private: 102 AlignedBuf<uint64_t, 8> mStorage; 103 std::unordered_set<void*> mFallbackPtrs; 104 size_t mAllocPos = 0; 105 size_t mTotalWantedThisGeneration = 0; 106 bool mNeedRealloc = false; 107 }; 108 109 } // namespace base 110 } // namespace android 111