| /* |
| * Copyright 2014 Google Inc. All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define IN_FRUIT_CPP_FILE 1 |
| |
| #include <algorithm> |
| #include <cstdlib> |
| #include <fruit/impl/util/type_info.h> |
| #include <iostream> |
| #include <memory> |
| #include <vector> |
| |
| #include <fruit/impl/component_storage/component_storage.h> |
| #include <fruit/impl/data_structures/semistatic_graph.templates.h> |
| #include <fruit/impl/injector/injector_storage.h> |
| #include <fruit/impl/normalized_component_storage/binding_normalization.h> |
| #include <fruit/impl/normalized_component_storage/binding_normalization.templates.h> |
| |
| using std::cout; |
| using std::endl; |
| |
| namespace fruit { |
| namespace impl { |
| |
| void InjectorStorage::fatal(const std::string& error) { |
| std::cerr << "Fatal injection error: " << error << std::endl; |
| exit(1); |
| } |
| |
| // LCOV_EXCL_START |
| namespace { |
| template <typename Id, typename Value> |
| struct DummyNode { |
| Id getId() { |
| return Id(); |
| } |
| bool isTerminal() { |
| return false; |
| } |
| Id* getEdgesBegin() { |
| return nullptr; |
| } |
| Id* getEdgesEnd() { |
| return nullptr; |
| } |
| Value getValue() { |
| return Value(); |
| } |
| }; |
| } |
| // LCOV_EXCL_STOP |
| |
| InjectorStorage::InjectorStorage(ComponentStorage&& component, |
| const std::vector<TypeId, ArenaAllocator<TypeId>>& exposed_types, |
| MemoryPool& memory_pool) |
| : normalized_component_storage_ptr(new NormalizedComponentStorage( |
| std::move(component), exposed_types, memory_pool, NormalizedComponentStorage::WithPermanentCompression())), |
| allocator(normalized_component_storage_ptr->fixed_size_allocator_data), |
| bindings(normalized_component_storage_ptr->bindings, (DummyNode<TypeId, NormalizedBinding>*)nullptr, |
| (DummyNode<TypeId, NormalizedBinding>*)nullptr, memory_pool), |
| multibindings(std::move(normalized_component_storage_ptr->multibindings)) { |
| |
| #if FRUIT_EXTRA_DEBUG |
| bindings.checkFullyConstructed(); |
| #endif |
| } |
| |
| InjectorStorage::InjectorStorage(const NormalizedComponentStorage& normalized_component, ComponentStorage&& component, |
| MemoryPool& memory_pool) { |
| |
| FixedSizeAllocator::FixedSizeAllocatorData fixed_size_allocator_data; |
| using new_bindings_vector_t = std::vector<ComponentStorageEntry, ArenaAllocator<ComponentStorageEntry>>; |
| new_bindings_vector_t new_bindings_vector = new_bindings_vector_t(ArenaAllocator<ComponentStorageEntry>(memory_pool)); |
| |
| BindingNormalization::normalizeBindingsAndAddTo(std::move(component).release(), memory_pool, normalized_component, |
| fixed_size_allocator_data, new_bindings_vector, multibindings); |
| |
| allocator = FixedSizeAllocator(fixed_size_allocator_data); |
| |
| bindings = Graph(normalized_component.bindings, BindingDataNodeIter{new_bindings_vector.begin()}, |
| BindingDataNodeIter{new_bindings_vector.end()}, memory_pool); |
| #if FRUIT_EXTRA_DEBUG |
| bindings.checkFullyConstructed(); |
| #endif |
| } |
| |
| InjectorStorage::~InjectorStorage() {} |
| |
| void InjectorStorage::ensureConstructedMultibinding(NormalizedMultibindingSet& multibinding_set) { |
| for (NormalizedMultibinding& multibinding : multibinding_set.elems) { |
| if (!multibinding.is_constructed) { |
| multibinding.object = multibinding.create(*this); |
| multibinding.is_constructed = true; |
| } |
| } |
| } |
| |
| void* InjectorStorage::getMultibindings(TypeId typeInfo) { |
| NormalizedMultibindingSet* multibinding_set = getNormalizedMultibindingSet(typeInfo); |
| if (multibinding_set == nullptr) { |
| // Not registered. |
| return nullptr; |
| } |
| return multibinding_set->get_multibindings_vector(*this).get(); |
| } |
| |
| void InjectorStorage::eagerlyInjectMultibindings() { |
| std::lock_guard<std::recursive_mutex> lock(mutex); |
| for (auto& typeInfoInfoPair : multibindings) { |
| typeInfoInfoPair.second.get_multibindings_vector(*this); |
| } |
| } |
| |
| } // namespace impl |
| // We need a LCOV_EXCL_BR_LINE below because for some reason gcov/lcov think there's a branch there. |
| } // namespace fruit LCOV_EXCL_BR_LINE |