1 /* 2 * Copyright 2014 Google Inc. All rights reserved. 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 FRUIT_FIXED_SIZE_ALLOCATOR_H 18 #define FRUIT_FIXED_SIZE_ALLOCATOR_H 19 20 #include <fruit/impl/data_structures/fixed_size_vector.h> 21 #include <fruit/impl/meta/component.h> 22 #include <fruit/impl/util/type_info.h> 23 24 #if FRUIT_EXTRA_DEBUG 25 #include <unordered_map> 26 #endif 27 28 namespace fruit { 29 namespace impl { 30 31 /** 32 * An allocator where the maximum total size is fixed at construction, and all memory is retained until the allocator 33 * object itself is destructed. 34 */ 35 class FixedSizeAllocator { 36 public: 37 using destroy_t = void (*)(void*); 38 39 private: 40 // A pointer to the last used byte in the allocated memory chunk starting at storage_begin. 41 char* storage_last_used = nullptr; 42 43 // The chunk of memory that will be used for all allocations. 44 char* storage_begin = nullptr; 45 46 #if FRUIT_EXTRA_DEBUG 47 std::unordered_map<TypeId, std::size_t> remaining_types; 48 #endif 49 50 // This vector contains the destroy operations that have to be performed at destruction, and 51 // the pointers that they must be invoked with. Allows destruction in the correct order. 52 // These must be called in reverse order. 53 FixedSizeVector<std::pair<destroy_t, void*>> on_destruction; 54 55 // Destroys an object previously created using constructObject(). 56 template <typename C> 57 static void destroyObject(void* p); 58 59 // Calls delete on an object previously allocated using new. 60 template <typename C> 61 static void destroyExternalObject(void* p); 62 63 public: 64 // Data used to construct an allocator for a fixed set of types. 65 class FixedSizeAllocatorData { 66 private: 67 std::size_t total_size = 0; 68 std::size_t num_types_to_destroy = 0; 69 #if FRUIT_EXTRA_DEBUG 70 std::unordered_map<TypeId, std::size_t> types; 71 #endif 72 73 static std::size_t maximumRequiredSpace(TypeId type); 74 75 friend class FixedSizeAllocator; 76 77 public: 78 // Adds 1 `typeId' to the type set. Multiple copies of the same type are allowed. 79 // Each call to this method allows 1 constructObject<T>(...) call on the resulting allocator. 80 void addType(TypeId typeId); 81 82 // Each call to this method with getTypeId<T>() allows 1 registerExternallyAllocatedType<T>(...) call on the 83 // resulting 84 // allocator. 85 void addExternallyAllocatedType(TypeId typeId); 86 }; 87 88 // Constructs an empty allocator (no allocations are allowed). 89 FixedSizeAllocator() = default; 90 91 // Constructs an allocator for the type set in FixedSizeAllocatorData. 92 FixedSizeAllocator(FixedSizeAllocatorData allocator_data); 93 94 FixedSizeAllocator(FixedSizeAllocator&&); 95 FixedSizeAllocator& operator=(FixedSizeAllocator&&); 96 97 FixedSizeAllocator(const FixedSizeAllocator&) = delete; 98 FixedSizeAllocator& operator=(const FixedSizeAllocator&) = delete; 99 100 // On destruction, all objects allocated with constructObject() and all externally-allocated objects registered with 101 // registerExternallyAllocatedObject() are destroyed. 102 ~FixedSizeAllocator(); 103 104 // Allocates an object of type T, constructing it with the specified arguments. Similar to: 105 // new C(args...) 106 template <typename AnnotatedT, typename... Args> 107 fruit::impl::meta::UnwrapType< 108 fruit::impl::meta::Eval<fruit::impl::meta::RemoveAnnotations(fruit::impl::meta::Type<AnnotatedT>)>>* 109 constructObject(Args&&... args); 110 111 template <typename T> 112 void registerExternallyAllocatedObject(T* p); 113 }; 114 115 } // namespace impl 116 } // namespace fruit 117 118 #include <fruit/impl/data_structures/fixed_size_allocator.defn.h> 119 120 #endif // FRUIT_FIXED_SIZE_ALLOCATOR_H 121