• 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_NORMALIZED_COMPONENT_STORAGE_H
18 #define FRUIT_NORMALIZED_COMPONENT_STORAGE_H
19 
20 #if !IN_FRUIT_CPP_FILE
21 // We don't want to include it in public headers to save some compile time.
22 #error "normalized_component_storage.h included in non-cpp file."
23 #endif
24 
25 #include <fruit/impl/component_storage/component_storage_entry.h>
26 #include <fruit/impl/data_structures/fixed_size_allocator.h>
27 #include <fruit/impl/data_structures/semistatic_graph.h>
28 #include <fruit/impl/data_structures/semistatic_map.h>
29 #include <fruit/impl/fruit_internal_forward_decls.h>
30 #include <fruit/impl/normalized_component_storage/normalized_bindings.h>
31 #include <fruit/impl/util/hash_helpers.h>
32 #include <fruit/impl/util/type_info.h>
33 
34 #include <memory>
35 #include <unordered_map>
36 
37 namespace fruit {
38 namespace impl {
39 
40 /**
41  * Similar to ComponentStorage, but used a normalized representation to minimize the amount
42  * of work needed to turn this into an injector. However, adding bindings to a normalized
43  * component is slower than adding them to a simple component.
44  */
45 class NormalizedComponentStorage {
46 public:
47   struct CompressedBindingUndoInfo {
48     TypeId i_type_id;
49     ComponentStorageEntry::BindingForObjectToConstruct i_binding;
50     ComponentStorageEntry::BindingForObjectToConstruct c_binding;
51   };
52 
53   // A map from c_type_id to the corresponding CompressedBindingUndoInfo (if binding compression was performed for
54   // c_type_id).
55   using BindingCompressionInfoMap = HashMapWithArenaAllocator<TypeId, CompressedBindingUndoInfo>;
56   using BindingCompressionInfoMapAllocator = BindingCompressionInfoMap::allocator_type;
57 
58   using LazyComponentWithNoArgs = ComponentStorageEntry::LazyComponentWithNoArgs;
59   using LazyComponentWithArgs = ComponentStorageEntry::LazyComponentWithArgs;
60 
61   struct HashLazyComponentWithNoArgs {
operatorHashLazyComponentWithNoArgs62     std::size_t operator()(const LazyComponentWithNoArgs& x) const {
63       return x.hashCode();
64     }
65   };
66 
67   struct LazyComponentWithArgsEqualTo {
operatorLazyComponentWithArgsEqualTo68     bool operator()(const LazyComponentWithArgs& x, const LazyComponentWithArgs& y) const {
69       return *x.component == *y.component;
70     }
71   };
72 
73   struct HashLazyComponentWithArgs {
operatorHashLazyComponentWithArgs74     std::size_t operator()(const LazyComponentWithArgs& x) const {
75       return x.component->hashCode();
76     }
77   };
78 
79   using LazyComponentWithNoArgsSet = HashSetWithArenaAllocator<LazyComponentWithNoArgs, HashLazyComponentWithNoArgs,
80                                                                std::equal_to<LazyComponentWithNoArgs>>;
81   using LazyComponentWithArgsSet =
82       HashSetWithArenaAllocator<LazyComponentWithArgs, HashLazyComponentWithArgs, LazyComponentWithArgsEqualTo>;
83 
84   using LazyComponentWithNoArgsReplacementMap =
85       HashMapWithArenaAllocator<LazyComponentWithNoArgs, ComponentStorageEntry,
86                                 NormalizedComponentStorage::HashLazyComponentWithNoArgs,
87                                 std::equal_to<LazyComponentWithNoArgs>>;
88   using LazyComponentWithArgsReplacementMap =
89       HashMapWithArenaAllocator<LazyComponentWithArgs, ComponentStorageEntry,
90                                 NormalizedComponentStorage::HashLazyComponentWithArgs,
91                                 NormalizedComponentStorage::LazyComponentWithArgsEqualTo>;
92 
93   static LazyComponentWithNoArgsSet createLazyComponentWithNoArgsSet(size_t capacity, MemoryPool& memory_pool);
94   static LazyComponentWithArgsSet createLazyComponentWithArgsSet(size_t capacity, MemoryPool& memory_pool);
95 
96   static LazyComponentWithNoArgsReplacementMap createLazyComponentWithNoArgsReplacementMap(size_t capacity,
97                                                                                            MemoryPool& memory_pool);
98   static LazyComponentWithArgsReplacementMap createLazyComponentWithArgsReplacementMap(size_t capacity,
99                                                                                        MemoryPool& memory_pool);
100 
101 private:
102   // A graph with types as nodes (each node stores the BindingData for the type) and dependencies as edges.
103   // For types that have a constructed object already, the corresponding node is stored as terminal node.
104   SemistaticGraph<TypeId, NormalizedBinding> bindings;
105 
106   // Maps the type index of a type T to the corresponding NormalizedMultibindingSet.
107   std::unordered_map<TypeId, NormalizedMultibindingSet> multibindings;
108 
109   // Contains data on the set of types that can be allocated using this component.
110   FixedSizeAllocator::FixedSizeAllocatorData fixed_size_allocator_data;
111 
112   // The MemoryPool used to allocate bindingCompressionInfoMap, fully_expanded_components_with_no_args and
113   // fully_expanded_components_with_args.
114   MemoryPool normalized_component_memory_pool;
115 
116   // Stores information on binding compression that was performed in bindings of this object.
117   // See also the documentation for BindingCompressionInfoMap.
118   BindingCompressionInfoMap binding_compression_info_map;
119 
120   LazyComponentWithNoArgsSet fully_expanded_components_with_no_args;
121   LazyComponentWithArgsSet fully_expanded_components_with_args;
122 
123   LazyComponentWithNoArgsReplacementMap component_with_no_args_replacements;
124   LazyComponentWithArgsReplacementMap component_with_args_replacements;
125 
126   friend class InjectorStorage;
127   friend class BindingNormalization;
128 
129 public:
130   using Graph = SemistaticGraph<TypeId, NormalizedBinding>;
131 
132   NormalizedComponentStorage() = delete;
133 
134   NormalizedComponentStorage(NormalizedComponentStorage&&) = delete;
135   NormalizedComponentStorage(const NormalizedComponentStorage&) = delete;
136 
137   NormalizedComponentStorage& operator=(NormalizedComponentStorage&&) = delete;
138   NormalizedComponentStorage& operator=(const NormalizedComponentStorage&) = delete;
139 
140   // These are just used as tags to select the desired constructor.
141   struct WithUndoableCompression {};
142   struct WithPermanentCompression {};
143 
144   /**
145    * The MemoryPool is only used during construction, the constructed object *can* outlive the memory pool.
146    */
147   NormalizedComponentStorage(ComponentStorage&& component,
148                              const std::vector<TypeId, ArenaAllocator<TypeId>>& exposed_types, MemoryPool& memory_pool,
149                              WithUndoableCompression);
150 
151   /**
152    * The MemoryPool is only used during construction, the constructed object *can* outlive the memory pool.
153    */
154   NormalizedComponentStorage(ComponentStorage&& component,
155                              const std::vector<TypeId, ArenaAllocator<TypeId>>& exposed_types, MemoryPool& memory_pool,
156                              WithPermanentCompression);
157 
158   // We don't use the default destructor because that will require the inclusion of
159   // the Boost's hashmap header. We define this in the cpp file instead.
160   ~NormalizedComponentStorage() noexcept;
161 };
162 
163 } // namespace impl
164 } // namespace fruit
165 
166 #include <fruit/impl/normalized_component_storage/normalized_component_storage.defn.h>
167 
168 #endif // FRUIT_NORMALIZED_COMPONENT_STORAGE_H
169