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 #define IN_FRUIT_CPP_FILE 1
18
19 #include <algorithm>
20 #include <cstdlib>
21 #include <fruit/impl/util/type_info.h>
22 #include <iostream>
23 #include <memory>
24 #include <vector>
25
26 #include <fruit/impl/component_storage/component_storage.h>
27 #include <fruit/impl/data_structures/semistatic_graph.templates.h>
28 #include <fruit/impl/injector/injector_storage.h>
29 #include <fruit/impl/normalized_component_storage/binding_normalization.h>
30 #include <fruit/impl/normalized_component_storage/binding_normalization.templates.h>
31
32 using std::cout;
33 using std::endl;
34
35 namespace fruit {
36 namespace impl {
37
fatal(const std::string & error)38 void InjectorStorage::fatal(const std::string& error) {
39 std::cerr << "Fatal injection error: " << error << std::endl;
40 exit(1);
41 }
42
43 // LCOV_EXCL_START
44 namespace {
45 template <typename Id, typename Value>
46 struct DummyNode {
getIdfruit::impl::__anon6c16492e0111::DummyNode47 Id getId() {
48 return Id();
49 }
isTerminalfruit::impl::__anon6c16492e0111::DummyNode50 bool isTerminal() {
51 return false;
52 }
getEdgesBeginfruit::impl::__anon6c16492e0111::DummyNode53 Id* getEdgesBegin() {
54 return nullptr;
55 }
getEdgesEndfruit::impl::__anon6c16492e0111::DummyNode56 Id* getEdgesEnd() {
57 return nullptr;
58 }
getValuefruit::impl::__anon6c16492e0111::DummyNode59 Value getValue() {
60 return Value();
61 }
62 };
63 }
64 // LCOV_EXCL_STOP
65
InjectorStorage(ComponentStorage && component,const std::vector<TypeId,ArenaAllocator<TypeId>> & exposed_types,MemoryPool & memory_pool)66 InjectorStorage::InjectorStorage(ComponentStorage&& component,
67 const std::vector<TypeId, ArenaAllocator<TypeId>>& exposed_types,
68 MemoryPool& memory_pool)
69 : normalized_component_storage_ptr(new NormalizedComponentStorage(
70 std::move(component), exposed_types, memory_pool, NormalizedComponentStorage::WithPermanentCompression())),
71 allocator(normalized_component_storage_ptr->fixed_size_allocator_data),
72 bindings(normalized_component_storage_ptr->bindings, (DummyNode<TypeId, NormalizedBinding>*)nullptr,
73 (DummyNode<TypeId, NormalizedBinding>*)nullptr, memory_pool),
74 multibindings(std::move(normalized_component_storage_ptr->multibindings)) {
75
76 #if FRUIT_EXTRA_DEBUG
77 bindings.checkFullyConstructed();
78 #endif
79 }
80
InjectorStorage(const NormalizedComponentStorage & normalized_component,ComponentStorage && component,MemoryPool & memory_pool)81 InjectorStorage::InjectorStorage(const NormalizedComponentStorage& normalized_component, ComponentStorage&& component,
82 MemoryPool& memory_pool) {
83
84 FixedSizeAllocator::FixedSizeAllocatorData fixed_size_allocator_data;
85 using new_bindings_vector_t = std::vector<ComponentStorageEntry, ArenaAllocator<ComponentStorageEntry>>;
86 new_bindings_vector_t new_bindings_vector = new_bindings_vector_t(ArenaAllocator<ComponentStorageEntry>(memory_pool));
87
88 BindingNormalization::normalizeBindingsAndAddTo(std::move(component).release(), memory_pool, normalized_component,
89 fixed_size_allocator_data, new_bindings_vector, multibindings);
90
91 allocator = FixedSizeAllocator(fixed_size_allocator_data);
92
93 bindings = Graph(normalized_component.bindings, BindingDataNodeIter{new_bindings_vector.begin()},
94 BindingDataNodeIter{new_bindings_vector.end()}, memory_pool);
95 #if FRUIT_EXTRA_DEBUG
96 bindings.checkFullyConstructed();
97 #endif
98 }
99
~InjectorStorage()100 InjectorStorage::~InjectorStorage() {}
101
ensureConstructedMultibinding(NormalizedMultibindingSet & multibinding_set)102 void InjectorStorage::ensureConstructedMultibinding(NormalizedMultibindingSet& multibinding_set) {
103 for (NormalizedMultibinding& multibinding : multibinding_set.elems) {
104 if (!multibinding.is_constructed) {
105 multibinding.object = multibinding.create(*this);
106 multibinding.is_constructed = true;
107 }
108 }
109 }
110
getMultibindings(TypeId typeInfo)111 void* InjectorStorage::getMultibindings(TypeId typeInfo) {
112 NormalizedMultibindingSet* multibinding_set = getNormalizedMultibindingSet(typeInfo);
113 if (multibinding_set == nullptr) {
114 // Not registered.
115 return nullptr;
116 }
117 return multibinding_set->get_multibindings_vector(*this).get();
118 }
119
eagerlyInjectMultibindings()120 void InjectorStorage::eagerlyInjectMultibindings() {
121 std::lock_guard<std::recursive_mutex> lock(mutex);
122 for (auto& typeInfoInfoPair : multibindings) {
123 typeInfoInfoPair.second.get_multibindings_vector(*this);
124 }
125 }
126
127 } // namespace impl
128 // We need a LCOV_EXCL_BR_LINE below because for some reason gcov/lcov think there's a branch there.
129 } // namespace fruit LCOV_EXCL_BR_LINE
130