• 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 #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::__anonde01d0370111::DummyNode49   Id getId() {
50     return Id();
51   }
isTerminalfruit::impl::__anonde01d0370111::DummyNode52   bool isTerminal() {
53     return false;
54   }
getEdgesBeginfruit::impl::__anonde01d0370111::DummyNode55   Id* getEdgesBegin() {
56     return nullptr;
57   }
getEdgesEndfruit::impl::__anonde01d0370111::DummyNode58   Id* getEdgesEnd() {
59     return nullptr;
60   }
getValuefruit::impl::__anonde01d0370111::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