1*a65addddSAndroid Build Coastguard Worker /* 2*a65addddSAndroid Build Coastguard Worker * Copyright 2014 Google Inc. All rights reserved. 3*a65addddSAndroid Build Coastguard Worker * 4*a65addddSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*a65addddSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*a65addddSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*a65addddSAndroid Build Coastguard Worker * 8*a65addddSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*a65addddSAndroid Build Coastguard Worker * 10*a65addddSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*a65addddSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*a65addddSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*a65addddSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*a65addddSAndroid Build Coastguard Worker * limitations under the License. 15*a65addddSAndroid Build Coastguard Worker */ 16*a65addddSAndroid Build Coastguard Worker 17*a65addddSAndroid Build Coastguard Worker #ifndef FRUIT_NORMALIZED_COMPONENT_H 18*a65addddSAndroid Build Coastguard Worker #define FRUIT_NORMALIZED_COMPONENT_H 19*a65addddSAndroid Build Coastguard Worker 20*a65addddSAndroid Build Coastguard Worker // This include is not required here, but having it here shortens the include trace in error messages. 21*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/injection_errors.h> 22*a65addddSAndroid Build Coastguard Worker 23*a65addddSAndroid Build Coastguard Worker #include <fruit/fruit_forward_decls.h> 24*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/fruit_internal_forward_decls.h> 25*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/component.h> 26*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/normalized_component_storage/normalized_component_storage_holder.h> 27*a65addddSAndroid Build Coastguard Worker #include <memory> 28*a65addddSAndroid Build Coastguard Worker 29*a65addddSAndroid Build Coastguard Worker namespace fruit { 30*a65addddSAndroid Build Coastguard Worker 31*a65addddSAndroid Build Coastguard Worker /** 32*a65addddSAndroid Build Coastguard Worker * This class allows for fast creation of multiple injectors that share most (or all) the bindings. 33*a65addddSAndroid Build Coastguard Worker * 34*a65addddSAndroid Build Coastguard Worker * This is an advanced feature of Fruit that allows to reduce injection time in some cases; if you're just starting to 35*a65addddSAndroid Build Coastguard Worker * use Fruit you might want to ignore this for now (just construct an Injector from your root Component function). 36*a65addddSAndroid Build Coastguard Worker * 37*a65addddSAndroid Build Coastguard Worker * Using a NormalizedComponent only helps if: 38*a65addddSAndroid Build Coastguard Worker * 39*a65addddSAndroid Build Coastguard Worker * - You create multiple injectors during the lifetime of a process. E.g. if you only create one injector at startup you 40*a65addddSAndroid Build Coastguard Worker * won't benefit from using NormalizedComponent. 41*a65addddSAndroid Build Coastguard Worker * - Some of those injectors share all (or almost all) their bindings. 42*a65addddSAndroid Build Coastguard Worker * 43*a65addddSAndroid Build Coastguard Worker * When both of those requirements apply, you can switch to using NormalizedComponent in the "similar" injectors by 44*a65addddSAndroid Build Coastguard Worker * first refactoring the injectors' root components to be of the form: 45*a65addddSAndroid Build Coastguard Worker * 46*a65addddSAndroid Build Coastguard Worker * fruit::Component<...> getRootComponent(...) { 47*a65addddSAndroid Build Coastguard Worker * return fruit::createComponent() 48*a65addddSAndroid Build Coastguard Worker * // This contains the bindings common to the group of similar injectors. 49*a65addddSAndroid Build Coastguard Worker * .install(getSharedComponent, ...) 50*a65addddSAndroid Build Coastguard Worker * // This contains the bindings specific to this injector. 51*a65addddSAndroid Build Coastguard Worker * .install(getSpecificComponent, ...); 52*a65addddSAndroid Build Coastguard Worker * } 53*a65addddSAndroid Build Coastguard Worker * 54*a65addddSAndroid Build Coastguard Worker * Then you can change your injector construction from: 55*a65addddSAndroid Build Coastguard Worker * 56*a65addddSAndroid Build Coastguard Worker * fruit::Injector<...> injector(getRootComponent, ...); 57*a65addddSAndroid Build Coastguard Worker * 58*a65addddSAndroid Build Coastguard Worker * To: 59*a65addddSAndroid Build Coastguard Worker * 60*a65addddSAndroid Build Coastguard Worker * fruit::NormalizedComponent<fruit::Required<...>, ...> normalized_component(getSharedComponent, ...); 61*a65addddSAndroid Build Coastguard Worker * fruit::Injector<...> injector(normalized_component, getSpecificComponent, ...); 62*a65addddSAndroid Build Coastguard Worker * 63*a65addddSAndroid Build Coastguard Worker * This splits the work of constructing the Injector in two phases: normalization (where Fruit will call the Component 64*a65addddSAndroid Build Coastguard Worker * functions to collect all the bindings and check for some classes of runtime errors) and the actual creation of the 65*a65addddSAndroid Build Coastguard Worker * injector, during which Fruit will also collect/check the additional bindings specific to that injector. 66*a65addddSAndroid Build Coastguard Worker * 67*a65addddSAndroid Build Coastguard Worker * Then you can share the same normalized_component object across all those injectors (also in different threads, 68*a65addddSAndroid Build Coastguard Worker * NormalizedComponent is thread-safe), so that the normalization step only occurs once (i.e., you should only construct 69*a65addddSAndroid Build Coastguard Worker * NormalizedComponent from getSharedComponent once, otherwise you'd pay the normalization cost multiple times). 70*a65addddSAndroid Build Coastguard Worker * 71*a65addddSAndroid Build Coastguard Worker * Creating an Injector from a NormalizedComponent and injecting separate instances is very cheap, on the order of 2 us 72*a65addddSAndroid Build Coastguard Worker * for an injection graph with 100 classes and 900 edges (for more details see the Benchmarks page of the Fruit wiki: 73*a65addddSAndroid Build Coastguard Worker * https://github.com/google/fruit/wiki/benchmarks ). 74*a65addddSAndroid Build Coastguard Worker * This might (depending of course on your performance requirements) allow you to create injectors where it would 75*a65addddSAndroid Build Coastguard Worker * otherwise be unthinkable, e.g. creating a separate injector for each request in a server. 76*a65addddSAndroid Build Coastguard Worker * 77*a65addddSAndroid Build Coastguard Worker * Injectors that share the same NormalizedComponent are still independent; for example, if you call injector.get<Foo>() 78*a65addddSAndroid Build Coastguard Worker * in two injectors, each injector will construct its own instance of Foo. 79*a65addddSAndroid Build Coastguard Worker * 80*a65addddSAndroid Build Coastguard Worker * Example usage in a server: 81*a65addddSAndroid Build Coastguard Worker * 82*a65addddSAndroid Build Coastguard Worker * // In the global scope. 83*a65addddSAndroid Build Coastguard Worker * Component<Request> getRequestComponent(Request* request) { 84*a65addddSAndroid Build Coastguard Worker * return fruit::createComponent() 85*a65addddSAndroid Build Coastguard Worker * .bindInstance(*request); 86*a65addddSAndroid Build Coastguard Worker * } 87*a65addddSAndroid Build Coastguard Worker * 88*a65addddSAndroid Build Coastguard Worker * // At startup (e.g. inside main()). 89*a65addddSAndroid Build Coastguard Worker * NormalizedComponent<Required<Request>, Bar, Bar2> normalizedComponent = ...; 90*a65addddSAndroid Build Coastguard Worker * 91*a65addddSAndroid Build Coastguard Worker * ... 92*a65addddSAndroid Build Coastguard Worker * for (...) { 93*a65addddSAndroid Build Coastguard Worker * // For each request. 94*a65addddSAndroid Build Coastguard Worker * Request request = ...; 95*a65addddSAndroid Build Coastguard Worker * 96*a65addddSAndroid Build Coastguard Worker * Injector<Foo, Bar> injector(normalizedComponent, getRequestComponent, &request); 97*a65addddSAndroid Build Coastguard Worker * Foo* foo = injector.get<Foo*>(); 98*a65addddSAndroid Build Coastguard Worker * ... 99*a65addddSAndroid Build Coastguard Worker * } 100*a65addddSAndroid Build Coastguard Worker * 101*a65addddSAndroid Build Coastguard Worker * See also the documentation for the Injector constructor that takes a NormalizedComponent. 102*a65addddSAndroid Build Coastguard Worker */ 103*a65addddSAndroid Build Coastguard Worker template <typename... Params> 104*a65addddSAndroid Build Coastguard Worker class NormalizedComponent { 105*a65addddSAndroid Build Coastguard Worker public: 106*a65addddSAndroid Build Coastguard Worker /** 107*a65addddSAndroid Build Coastguard Worker * The Component used as parameter can have (and usually has) unsatisfied requirements, so it's usually of the form 108*a65addddSAndroid Build Coastguard Worker * Component<Required<...>, ...>. 109*a65addddSAndroid Build Coastguard Worker * 110*a65addddSAndroid Build Coastguard Worker * The given component function is called with the provided arguments to construct the root component. 111*a65addddSAndroid Build Coastguard Worker * The constraints on the argument types (if there are any) are the same as the ones for PartialComponent::install(). 112*a65addddSAndroid Build Coastguard Worker */ 113*a65addddSAndroid Build Coastguard Worker template <typename... FormalArgs, typename... Args> 114*a65addddSAndroid Build Coastguard Worker explicit NormalizedComponent(Component<Params...> (*)(FormalArgs...), Args&&... args); 115*a65addddSAndroid Build Coastguard Worker NormalizedComponent(NormalizedComponent && storage)116*a65addddSAndroid Build Coastguard Worker NormalizedComponent(NormalizedComponent&& storage) noexcept : storage(std::move(storage.storage)) {} 117*a65addddSAndroid Build Coastguard Worker NormalizedComponent(const NormalizedComponent&) = delete; 118*a65addddSAndroid Build Coastguard Worker 119*a65addddSAndroid Build Coastguard Worker NormalizedComponent& operator=(NormalizedComponent&&) = delete; 120*a65addddSAndroid Build Coastguard Worker NormalizedComponent& operator=(const NormalizedComponent&) = delete; 121*a65addddSAndroid Build Coastguard Worker 122*a65addddSAndroid Build Coastguard Worker private: 123*a65addddSAndroid Build Coastguard Worker NormalizedComponent(fruit::impl::ComponentStorage&& storage, fruit::impl::MemoryPool memory_pool); 124*a65addddSAndroid Build Coastguard Worker 125*a65addddSAndroid Build Coastguard Worker // This is held via a unique_ptr to avoid including normalized_component_storage.h 126*a65addddSAndroid Build Coastguard Worker // in fruit.h. 127*a65addddSAndroid Build Coastguard Worker fruit::impl::NormalizedComponentStorageHolder storage; 128*a65addddSAndroid Build Coastguard Worker 129*a65addddSAndroid Build Coastguard Worker template <typename... OtherParams> 130*a65addddSAndroid Build Coastguard Worker friend class Injector; 131*a65addddSAndroid Build Coastguard Worker 132*a65addddSAndroid Build Coastguard Worker using Comp = fruit::impl::meta::Eval<fruit::impl::meta::ConstructComponentImpl(fruit::impl::meta::Type<Params>...)>; 133*a65addddSAndroid Build Coastguard Worker 134*a65addddSAndroid Build Coastguard Worker using Check1 = typename fruit::impl::meta::CheckIfError<Comp>::type; 135*a65addddSAndroid Build Coastguard Worker // Force instantiation of Check1. 136*a65addddSAndroid Build Coastguard Worker static_assert(true || sizeof(Check1), ""); 137*a65addddSAndroid Build Coastguard Worker }; 138*a65addddSAndroid Build Coastguard Worker 139*a65addddSAndroid Build Coastguard Worker } // namespace fruit 140*a65addddSAndroid Build Coastguard Worker 141*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/normalized_component.defn.h> 142*a65addddSAndroid Build Coastguard Worker 143*a65addddSAndroid Build Coastguard Worker #endif // FRUIT_NORMALIZED_COMPONENT_H 144