1 /* 2 * Copyright 2019, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ANDROID_REGION_FAT_VECTOR_H 18 #define ANDROID_REGION_FAT_VECTOR_H 19 20 #include <stddef.h> 21 #include <stdlib.h> 22 #include <utils/Log.h> 23 #include <type_traits> 24 25 #include <vector> 26 27 namespace android { 28 29 template <typename T, size_t SIZE = 4> 30 class InlineStdAllocator { 31 public: 32 struct Allocation { 33 private: 34 Allocation(const Allocation&) = delete; 35 void operator=(const Allocation&) = delete; 36 37 public: AllocationAllocation38 Allocation() {} 39 // char array instead of T array, so memory is uninitialized, with no destructors run 40 char array[sizeof(T) * SIZE]; 41 bool inUse = false; 42 }; 43 44 typedef T value_type; // needed to implement std::allocator 45 typedef T* pointer; // needed to implement std::allocator 46 InlineStdAllocator(Allocation & allocation)47 explicit InlineStdAllocator(Allocation& allocation) : mAllocation(allocation) {} InlineStdAllocator(const InlineStdAllocator & other)48 InlineStdAllocator(const InlineStdAllocator& other) : mAllocation(other.mAllocation) {} ~InlineStdAllocator()49 ~InlineStdAllocator() {} 50 51 T* allocate(size_t num, const void* = 0) { 52 if (!mAllocation.inUse && num <= SIZE) { 53 mAllocation.inUse = true; 54 return static_cast<T*>(static_cast<void*>(mAllocation.array)); 55 } else { 56 return static_cast<T*>(static_cast<void*>(malloc(num * sizeof(T)))); 57 } 58 } 59 deallocate(pointer p,size_t)60 void deallocate(pointer p, size_t) { 61 if (p == static_cast<T*>(static_cast<void*>(mAllocation.array))) { 62 mAllocation.inUse = false; 63 } else { 64 // 'free' instead of delete here - destruction handled separately 65 free(p); 66 } 67 } 68 Allocation& mAllocation; 69 }; 70 71 /** 72 * std::vector with SIZE elements preallocated into an internal buffer. 73 * 74 * Useful for avoiding the cost of malloc in cases where only SIZE or 75 * fewer elements are needed in the common case. 76 */ 77 template <typename T, size_t SIZE = 4> 78 class FatVector : public std::vector<T, InlineStdAllocator<T, SIZE>> { 79 public: FatVector()80 FatVector() 81 : std::vector<T, InlineStdAllocator<T, SIZE>>(InlineStdAllocator<T, SIZE>(mAllocation)) { 82 this->reserve(SIZE); 83 } 84 FatVector(size_t capacity)85 explicit FatVector(size_t capacity) : FatVector() { this->resize(capacity); } 86 87 private: 88 typename InlineStdAllocator<T, SIZE>::Allocation mAllocation; 89 }; 90 91 } // namespace android 92 93 #endif // ANDROID_REGION_FAT_VECTOR_H 94