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 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 { 49 Id getId() { 50 return Id(); 51 } 52 bool isTerminal() { 53 return false; 54 } 55 Id* getEdgesBegin() { 56 return nullptr; 57 } 58 Id* getEdgesEnd() { 59 return nullptr; 60 } 61 Value getValue() { 62 return Value(); 63 } 64 }; 65 } 66 // LCOV_EXCL_STOP 67 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 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 102 InjectorStorage::~InjectorStorage() {} 103 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 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 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