• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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