Home | History | Annotate | Download | only in src
      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