/*
|
* 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;
|
|
using namespace fruit::impl;
|
|
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
|