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 using namespace fruit::impl;
36
37 namespace fruit {
38 namespace impl {
39
fatal(const std::string & error)40 void InjectorStorage::fatal(const std::string& error) {
41 std::cerr << "Fatal injection error: " << error << std::endl;
42 exit(1);
43 }
44
45 // LCOV_EXCL_START
46 namespace {
47 template <typename Id, typename Value>
48 struct DummyNode {
getIdfruit::impl::__anonb8d2f4f90111::DummyNode49 Id getId() {
50 return Id();
51 }
isTerminalfruit::impl::__anonb8d2f4f90111::DummyNode52 bool isTerminal() {
53 return false;
54 }
getEdgesBeginfruit::impl::__anonb8d2f4f90111::DummyNode55 Id* getEdgesBegin() {
56 return nullptr;
57 }
getEdgesEndfruit::impl::__anonb8d2f4f90111::DummyNode58 Id* getEdgesEnd() {
59 return nullptr;
60 }
getValuefruit::impl::__anonb8d2f4f90111::DummyNode61 Value getValue() {
62 return Value();
63 }
64 };
65 }
66 // LCOV_EXCL_STOP
67
InjectorStorage(ComponentStorage && component,const std::vector<TypeId,ArenaAllocator<TypeId>> & exposed_types,MemoryPool & memory_pool)68 InjectorStorage::InjectorStorage(ComponentStorage&& component,
69 const std::vector<TypeId, ArenaAllocator<TypeId>>& exposed_types,
70 MemoryPool& memory_pool)
71 : normalized_component_storage_ptr(new NormalizedComponentStorage(
72 std::move(component), exposed_types, memory_pool, NormalizedComponentStorage::WithPermanentCompression())),
73 allocator(normalized_component_storage_ptr->fixed_size_allocator_data),
74 bindings(normalized_component_storage_ptr->bindings, (DummyNode<TypeId, NormalizedBinding>*)nullptr,
75 (DummyNode<TypeId, NormalizedBinding>*)nullptr, memory_pool),
76 multibindings(std::move(normalized_component_storage_ptr->multibindings)) {
77
78 #if FRUIT_EXTRA_DEBUG
79 bindings.checkFullyConstructed();
80 #endif
81 }
82
InjectorStorage(const NormalizedComponentStorage & normalized_component,ComponentStorage && component,MemoryPool & memory_pool)83 InjectorStorage::InjectorStorage(const NormalizedComponentStorage& normalized_component, ComponentStorage&& component,
84 MemoryPool& memory_pool) {
85
86 FixedSizeAllocator::FixedSizeAllocatorData fixed_size_allocator_data;
87 using new_bindings_vector_t = std::vector<ComponentStorageEntry, ArenaAllocator<ComponentStorageEntry>>;
88 new_bindings_vector_t new_bindings_vector = new_bindings_vector_t(ArenaAllocator<ComponentStorageEntry>(memory_pool));
89
90 BindingNormalization::normalizeBindingsAndAddTo(std::move(component).release(), memory_pool, normalized_component,
91 fixed_size_allocator_data, new_bindings_vector, multibindings);
92
93 allocator = FixedSizeAllocator(fixed_size_allocator_data);
94
95 bindings = Graph(normalized_component.bindings, BindingDataNodeIter{new_bindings_vector.begin()},
96 BindingDataNodeIter{new_bindings_vector.end()}, memory_pool);
97 #if FRUIT_EXTRA_DEBUG
98 bindings.checkFullyConstructed();
99 #endif
100 }
101
~InjectorStorage()102 InjectorStorage::~InjectorStorage() {}
103
ensureConstructedMultibinding(NormalizedMultibindingSet & multibinding_set)104 void InjectorStorage::ensureConstructedMultibinding(NormalizedMultibindingSet& multibinding_set) {
105 for (NormalizedMultibinding& multibinding : multibinding_set.elems) {
106 if (!multibinding.is_constructed) {
107 multibinding.object = multibinding.create(*this);
108 multibinding.is_constructed = true;
109 }
110 }
111 }
112
getMultibindings(TypeId typeInfo)113 void* InjectorStorage::getMultibindings(TypeId typeInfo) {
114 NormalizedMultibindingSet* multibinding_set = getNormalizedMultibindingSet(typeInfo);
115 if (multibinding_set == nullptr) {
116 // Not registered.
117 return nullptr;
118 }
119 return multibinding_set->get_multibindings_vector(*this).get();
120 }
121
eagerlyInjectMultibindings()122 void InjectorStorage::eagerlyInjectMultibindings() {
123 std::lock_guard<std::recursive_mutex> lock(mutex);
124 for (auto& typeInfoInfoPair : multibindings) {
125 typeInfoInfoPair.second.get_multibindings_vector(*this);
126 }
127 }
128
129 } // namespace impl
130 // We need a LCOV_EXCL_BR_LINE below because for some reason gcov/lcov think there's a branch there.
131 } // namespace fruit LCOV_EXCL_BR_LINE
132