diff --git a/research/try.cpp b/research/try.cpp index 71bed1d9d..979816cf6 100644 --- a/research/try.cpp +++ b/research/try.cpp @@ -46,18 +46,12 @@ typedef unsigned int uint; #include "lib/format-cout.hpp" -#include "lib/depend.hpp" #include "lib/depend2.hpp" -#include "lib/meta/util.hpp" +#include "lib/depend-inject.hpp" //#include "lib/meta/util.hpp" #include "lib/test/test-helper.hpp" #include "lib/util.hpp" -#include -#include -#include -#include - #define SHOW_TYPE(_TY_) \ cout << "typeof( " << STRINGIFY(_TY_) << " )= " << lib::meta::typeStr<_TY_>() < - class InstanceHolder - : boost::noncopyable - { - std::unique_ptr instance_; - - - public: - TAR* - buildInstance() - { - if (instance_) - throw error::Fatal("Attempt to double-create a singleton service. " - "Either the application logic, or the compiler " - "or runtime system is seriously broken" - ,error::LUMIERA_ERROR_LIFECYCLE); - - // place new instance into embedded buffer - instance_.reset (new TAR{}); - return instance_.get(); - } - }; - - template - class InstanceHolder>> - { - public: - ABS* - buildInstance() - { - throw error::Fatal("Attempt to create a singleton instance of an abstract class. " - "Application architecture or lifecycle is seriously broken."); - } - }; - }//(End)Implementation helper - - - - template - class DependInject; - - template - class Depend - { - using Factory = std::function; - - static SRV* instance; - static Factory factory; - - static InstanceHolder singleton; - - friend class DependInject; - public: - - SRV& - operator() () - { - if (!instance) - retrieveInstance(); - ENSURE (instance); - return *instance; - } - - private: - void - retrieveInstance() - { - ClassLock guard; - - if (!instance) - { - if (!factory) - instance = singleton.buildInstance(); - else - instance = factory(); - factory = disabledFactory; - } - } - - static SRV* - disabledFactory() - { - throw error::Fatal("Service not available at this point of the Application Lifecycle" - ,error::LUMIERA_ERROR_LIFECYCLE); - } - }; - - - template - SRV* Depend::instance; - - template - typename Depend::Factory Depend::factory; - - template - InstanceHolder Depend::singleton; - - - ///////////////////////////////////////////////////////Configuration - - using std::move; - - - template - struct DependInject - { - using Factory = typename Depend::Factory; - - - /** configure dependency-injection for type SRV to build a subclass singleton - * @tparam SUB concrete subclass type to build on demand when invoking `Depend` - * @throws error::Logic (LUMIERA_ERROR_LIFECYCLE) when the default factory has already - * been invoked at the point when calling this (re)configuration function. - */ - template - static void - useSingleton() - { - __assert_compatible(); - static InstanceHolder singleton; - installFactory ([&]() - { - return singleton.buildInstance(); - }); - } - - - /** - * Configuration handle to expose a service implementation through the `Depend` front-end. - * This noncopyable (but movable) handle shall be planted within the context operating the service - * to be exposed. It will immediately create (in RAII style) and manage a heap-allocated instance - * of the subclass `IMP` and expose a baseclass pointer to this specific instance through `Depend`. - * Moreover, the implementation subclass can be accessed through this handle, which acts as smart-ptr. - * When the handle goes out of scope, the implementation instance is destroyed and the access through - * `Depend` is closed and inhibited, to prevent on-demand creation of a baseclass `SRV` singleton. - * @tparam IMP concrete service implementation subclass to build, manage and expose. - * @throws error::Logic (LUMIERA_ERROR_LIFECYCLE) when the default factory has already - * been invoked at the point when calling this (re)configuration function. - */ - template - class ServiceInstance - { - std::unique_ptr instance_; - - public: - ServiceInstance() - : instance_(new IMP{}) - { - __assert_compatible(); - activateServiceAccess (*instance_); - } - - ~ServiceInstance() - { - deactivateServiceAccess(); - } - - ServiceInstance (ServiceInstance&&) = default; - ServiceInstance (ServiceInstance const&) = delete; - ServiceInstance& operator= (ServiceInstance&&) = delete; - - explicit - operator bool() const - { - return bool(instance_); - } - - IMP& - operator* () const - { - ENSURE (instance_); - return *instance_; - } - - IMP* - operator-> () const - { - ENSURE (instance_); - return instance_.get(); - } - }; - - - /** - * Configuration handle for temporarily shadowing a dependency by a test mock instance. - * This noncopyable (but movable) handle shall be planted within the immediate test context. - * It immediately stashes away the existing state and configuration from `Depend`, but - * waits for actual invocation of the `Depend`-front-end to create a heap-allocated - * instance of the `MOC` subclass, which it manages and exposes like a smart-ptr. - * When the handle goes out of scope, the original state and configuration is restored - */ - template - class Local - { - std::unique_ptr mock_; - - SRV* origInstance_; - Factory origFactory_; - - public: - Local() - { - __assert_compatible(); - temporarilyInstallAlternateFactory (origInstance_, origFactory_ - ,[this]() - { - mock_.reset(new MOC{}); - return mock_.get(); - }); - } - ~Local() - { - restoreOriginalFactory (origInstance_, origFactory_); - } - - Local (Local&&) = default; - Local (Local const&) = delete; - Local& operator= (Local&&) = delete; - - explicit - operator bool() const - { - return bool(mock_); - } - - MOC& - operator* () const - { - ENSURE (mock_); - return *mock_; - } - - MOC* - operator-> () const - { - ENSURE (mock_); - return mock_.get(); - } - }; - - - - protected: /* ======= internal access-API for those configurations to manipulate Depend ======= */ - template - friend class ServiceInstance; - template - friend class Local; - - - template - static void - __assert_compatible() - { - static_assert (std::is_base_of::value, - "Installed implementation class must be compatible to the interface."); - } - - static void - installFactory (Factory&& otherFac) - { - ClassLock guard; - if (Depend::instance) - throw error::Logic("Attempt to reconfigure dependency injection after the fact. " - "The previously installed factory (typically Singleton) was already used." - , error::LUMIERA_ERROR_LIFECYCLE); - Depend::factory = move (otherFac); - } - - static void - temporarilyInstallAlternateFactory (SRV*& stashInstance, Factory& stashFac, Factory&& newFac) - { - ClassLock guard; - stashFac = move(Depend::factory); - stashInstance = Depend::instance; - Depend::factory = move(newFac); - Depend::instance = nullptr; - } - - static void - restoreOriginalFactory (SRV*& stashInstance, Factory& stashFac) - { - ClassLock guard; - Depend::factory = move(stashFac); - Depend::instance = stashInstance; - } - - static void - activateServiceAccess (SRV& newInstance) - { - ClassLock guard; - if (Depend::instance) - throw error::Logic("Attempt to activate an external service implementation, " - "but another instance has already been dependency-injected." - , error::LUMIERA_ERROR_LIFECYCLE); - Depend::instance = &newInstance; - Depend::factory = Depend::disabledFactory; - } - - static void - deactivateServiceAccess() - { - ClassLock guard; - Depend::instance = nullptr; - Depend::factory = Depend::disabledFactory; - } - }; + + using lib::Depend; + using lib::DependInject; ///////////////////////////////////////////////////////Usage diff --git a/src/lib/depend-inject.hpp b/src/lib/depend-inject.hpp new file mode 100644 index 000000000..5ba834529 --- /dev/null +++ b/src/lib/depend-inject.hpp @@ -0,0 +1,278 @@ +/* + DEPENDENCY-FACTORY.hpp - managing the lifecycle of singletons and dependencies + + Copyright (C) Lumiera.org + 2013, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/** @file dependency-factory.hpp + ** Implementation of a singleton factory used to bring up services as dependency. + ** @internal this implementation header belongs to our framework to deal with + ** [service dependencies](\ref depend.hpp) and should not be used directly. + ** @todo WIP-WIP 3/18 rework of the singleton / dependency factory is underway + */ + + + + +#ifndef LIB_DEPEND_INJECT_H +#define LIB_DEPEND_INJECT_H + + + +#include "lib/error.hpp" +#include "lib/depend2.hpp" +#include "lib/sync-classlock.hpp" + +#include +#include + + +namespace lib { + namespace error = lumiera::error; + + using std::move; + + + + + /** + * This framework allows to (re)configure the lib::Depend front-end for dependency-injection. + * By default, `Depend` will create a singleton instance of `TY` lazily, on demand. + * When instantiating one of the configuration handles provided here -- _prior_ to using + * retrieving the instance through `Depend` -- this default (singleton) behaviour + * can be reconfigured in various ways, without the client being aware of it + * - instead of a singleton, a service instance with well defined lifecycle can be + * exposed through the `Depend` front-end. When the service is shut down, + * clients will receive an exception on access. + * - instead of the interface type `TY` mentioned in `Depend`, an implementation subclass + * can be specified, optionally with a closure for the actual creation of this subclass + * singleton type, which still happens lazily, on demand + * - the current state and configuration can be shadowed temporarily by a test mock instance, + * which is managed automatically and removed when leaving the scope of the test. + */ + template + struct DependInject + { + using Factory = typename Depend::Factory; + + + /** configure dependency-injection for type SRV to build a subclass singleton + * @tparam SUB concrete subclass type to build on demand when invoking `Depend` + * @throws error::Logic (LUMIERA_ERROR_LIFECYCLE) when the default factory has already + * been invoked at the point when calling this (re)configuration function. + */ + template + static void + useSingleton() + { + __assert_compatible(); + static InstanceHolder singleton; + installFactory ([&]() + { + return singleton.buildInstance(); + }); + } + + + /** + * Configuration handle to expose a service implementation through the `Depend` front-end. + * This noncopyable (but movable) handle shall be planted within the context operating the service + * to be exposed. It will immediately create (in RAII style) and manage a heap-allocated instance + * of the subclass `IMP` and expose a baseclass pointer to this specific instance through `Depend`. + * Moreover, the implementation subclass can be accessed through this handle, which acts as smart-ptr. + * When the handle goes out of scope, the implementation instance is destroyed and the access through + * `Depend` is closed and inhibited, to prevent on-demand creation of a baseclass `SRV` singleton. + * @tparam IMP concrete service implementation subclass to build, manage and expose. + * @throws error::Logic (LUMIERA_ERROR_LIFECYCLE) when the default factory has already + * been invoked at the point when calling this (re)configuration function. + */ + template + class ServiceInstance + { + std::unique_ptr instance_; + + public: + ServiceInstance() + : instance_(new IMP{}) + { + __assert_compatible(); + activateServiceAccess (*instance_); + } + + ~ServiceInstance() + { + deactivateServiceAccess(); + } + + ServiceInstance (ServiceInstance&&) = default; + ServiceInstance (ServiceInstance const&) = delete; + ServiceInstance& operator= (ServiceInstance&&) = delete; + + explicit + operator bool() const + { + return bool(instance_); + } + + IMP& + operator* () const + { + ENSURE (instance_); + return *instance_; + } + + IMP* + operator-> () const + { + ENSURE (instance_); + return instance_.get(); + } + }; + + + /** + * Configuration handle for temporarily shadowing a dependency by a test mock instance. + * This noncopyable (but movable) handle shall be planted within the immediate test context. + * It immediately stashes away the existing state and configuration from `Depend`, but + * waits for actual invocation of the `Depend`-front-end to create a heap-allocated + * instance of the `MOC` subclass, which it manages and exposes like a smart-ptr. + * When the handle goes out of scope, the original state and configuration is restored + */ + template + class Local + { + std::unique_ptr mock_; + + SRV* origInstance_; + Factory origFactory_; + + public: + Local() + { + __assert_compatible(); + temporarilyInstallAlternateFactory (origInstance_, origFactory_ + ,[this]() + { + mock_.reset(new MOC{}); + return mock_.get(); + }); + } + ~Local() + { + restoreOriginalFactory (origInstance_, origFactory_); + } + + Local (Local&&) = default; + Local (Local const&) = delete; + Local& operator= (Local&&) = delete; + + explicit + operator bool() const + { + return bool(mock_); + } + + MOC& + operator* () const + { + ENSURE (mock_); + return *mock_; + } + + MOC* + operator-> () const + { + ENSURE (mock_); + return mock_.get(); + } + }; + + + + protected: /* ======= internal access-API for those configurations to manipulate Depend ======= */ + template + friend class ServiceInstance; + template + friend class Local; + + + template + static void + __assert_compatible() + { + static_assert (std::is_base_of::value, + "Installed implementation class must be compatible to the interface."); + } + + static void + installFactory (Factory&& otherFac) + { + ClassLock guard; + if (Depend::instance) + throw error::Logic("Attempt to reconfigure dependency injection after the fact. " + "The previously installed factory (typically Singleton) was already used." + , error::LUMIERA_ERROR_LIFECYCLE); + Depend::factory = move (otherFac); + } + + static void + temporarilyInstallAlternateFactory (SRV*& stashInstance, Factory& stashFac, Factory&& newFac) + { + ClassLock guard; + stashFac = move(Depend::factory); + stashInstance = Depend::instance; + Depend::factory = move(newFac); + Depend::instance = nullptr; + } + + static void + restoreOriginalFactory (SRV*& stashInstance, Factory& stashFac) + { + ClassLock guard; + Depend::factory = move(stashFac); + Depend::instance = stashInstance; + } + + static void + activateServiceAccess (SRV& newInstance) + { + ClassLock guard; + if (Depend::instance) + throw error::Logic("Attempt to activate an external service implementation, " + "but another instance has already been dependency-injected." + , error::LUMIERA_ERROR_LIFECYCLE); + Depend::instance = &newInstance; + Depend::factory = Depend::disabledFactory; + } + + static void + deactivateServiceAccess() + { + ClassLock guard; + Depend::instance = nullptr; + Depend::factory = Depend::disabledFactory; + } + }; + + + + +} // namespace lib +#endif diff --git a/src/lib/depend2.hpp b/src/lib/depend2.hpp index 8fdcb0c83..e8adc1ecd 100644 --- a/src/lib/depend2.hpp +++ b/src/lib/depend2.hpp @@ -81,17 +81,76 @@ This code is heavily inspired by #define WIP_LIB_DEPEND_H +#include "lib/error.hpp" +#include "lib/nobug-init.hpp" #include "lib/sync-classlock.hpp" -#include "lib/dependency-factory2.hpp" +#include "lib/meta/util.hpp" + +#include +#include +#include +#include namespace lib { + namespace error = lumiera::error; + + + namespace { // Implementation helper... + + using lib::meta::enable_if; + + template + class InstanceHolder + : boost::noncopyable + { + std::unique_ptr instance_; + + + public: + TAR* + buildInstance() + { + if (instance_) + throw error::Fatal("Attempt to double-create a singleton service. " + "Either the application logic, or the compiler " + "or runtime system is seriously broken" + ,error::LUMIERA_ERROR_LIFECYCLE); + + // place new instance into embedded buffer + instance_.reset (new TAR{}); + return instance_.get(); + } + }; + + template + class InstanceHolder>> + { + public: + ABS* + buildInstance() + { + throw error::Fatal("Attempt to create a singleton instance of an abstract class. " + "Application architecture or lifecycle is seriously broken."); + } + }; + }//(End)Implementation helper + + + + /** + * @internal access point to reconfigure dependency injection on a per type base + * @see depend-inject.hpp + */ + template + class DependInject; + /** * Access point to singletons and other kinds of dependencies. * Actually this is a Factory object, which is typically placed into a * static field of the Singleton (target) class or some otherwise suitable interface. - * @param SI the class of the Singleton instance + * @tparam SRV the class of the Service or Singleton instance * @note uses static fields internally, so all factory configuration is shared per type * @remark there is an ongoing discussion regarding the viability of the * Double Checked Locking pattern, which requires either the context of a clearly defined @@ -110,106 +169,70 @@ namespace lib { * @todo WIP-WIP 3/18 rework of the singleton / dependency factory is underway /////////////////////TICKET #1086 * @param SI the class of the Singleton instance */ - template - class Depend2 + template + class Depend { - typedef ClassLock SyncLock; + using Factory = std::function; - static SI* volatile instance; - static DependencyFactory2 factory; + static SRV* instance; + static Factory factory; + + static InstanceHolder singleton; + + friend class DependInject; public: /** Interface to be used by clients for retrieving the service instance. * Manages the instance creation, lifecycle and access in multithreaded context. - * @return instance of class SI. When used in default configuration, + * @return instance of class `SRV`. When used in default configuration, * this service instance is a singleton */ - SI& + SRV& operator() () { if (!instance) - { - SyncLock guard; - - if (!instance) - instance = static_cast (factory.buildInstance()); - } + retrieveInstance(); ENSURE (instance); return *instance; } - - - typedef DependencyFactory2::InstanceConstructor Constructor; - - - /** default configuration of the dependency factory - * is to build a singleton instance on demand */ - Depend2() + private: + void + retrieveInstance() { - factory.ensureInitialisation (buildSingleton2()); + ClassLock guard; + + if (!instance) + { + if (!factory) + instance = singleton.buildInstance(); + else + instance = factory(); + factory = disabledFactory; + } } - /** - * optionally, the instance creation process can be configured explicitly - * \em once per type. By default, a singleton instance will be created. - * Installing another factory function enables other kinds of dependency injection; - * this configuration must be done \em prior to any use the dependency factory. - * @param ctor a constructor function, which will be invoked on first usage. - * @note basically a custom constructor function is responsible to manage any - * created service instances. - * @remark typically the \c Depend factory will be placed into a static variable, - * embedded into another type or interface. In this case, actual storage for - * this static variable needs to be allocated within some translation unit. - * And this is the point where this ctor will be invoked, in the static - * initialisation phase of the respective translation unit (*.cpp) - */ - Depend2 (Constructor ctor) + static SRV* + disabledFactory() { - factory.installConstructorFunction (ctor); - } - - // standard copy operations applicable - - - - /* === Management / Test support interface === */ - - /** temporarily replace the service instance. - * The purpose of this operation is to support unit testing. - * @param mock reference to an existing service instance (mock). - * @return reference to the currently active service instance. - * @warning this is a dangerous operation and not threadsafe. - * Concurrent accesses might still get the old reference; - * the only way to prevent this would be to synchronise - * \em any access (which is too expensive). - * This feature should only be used for unit tests thusly. - * @remark the replacement is not actively managed by the DependencyFactory, - * it remains in ownership of the calling client (unit test). Typically - * this test will keep the returned original service reference and - * care for restoring the original state when done. - * @see Depend4Test scoped object for automated test mock injection - */ - static SI* - injectReplacement (SI* mock) - { - SyncLock guard; - SI* currentInstance = instance; - instance = mock; - return currentInstance; + throw error::Fatal("Service not available at this point of the Application Lifecycle" + ,error::LUMIERA_ERROR_LIFECYCLE); } }; - // Storage for static per type instance management... - template - SI* volatile Depend2::instance; + /* === allocate Storage for static per type instance management === */ + template + SRV* Depend::instance; - template - DependencyFactory2 Depend2::factory; + template + typename Depend::Factory Depend::factory; + + template + InstanceHolder Depend::singleton; diff --git a/src/lib/dependency-factory2.hpp b/src/lib/dependency-factory2.hpp deleted file mode 100644 index 411a52394..000000000 --- a/src/lib/dependency-factory2.hpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - DEPENDENCY-FACTORY.hpp - managing the lifecycle of singletons and dependencies - - Copyright (C) Lumiera.org - 2013, Hermann Vosseler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - - -/** @file dependency-factory.hpp - ** Implementation of a singleton factory used to bring up services as dependency. - ** @internal this implementation header belongs to our framework to deal with - ** [service dependencies](\ref depend.hpp) and should not be used directly. - ** @todo WIP-WIP 3/18 rework of the singleton / dependency factory is underway - */ - - - - -#ifndef WIP_LIB_DEPENDENCY_FACTORY_H -#define WIP_LIB_DEPENDENCY_FACTORY_H - - - -#include "lib/nobug-init.hpp" -#include "lib/error.hpp" - - -namespace lib { - - namespace error = lumiera::error; - - - /** - * @internal Factory to generate and manage service objects classified by type. - * An instance of this factory is placed once for each type for use by - * the lib::Depend front-end for dependency management. While the latter - * provides the singleton-style initialisation patter, the DependencyFacotry - * maintains a customisable factory function for instance creation. Moreover, - * the embedded helper template DependencyFactory::InstanceHolder actually - * creates and manages the singleton instances in default configuration; - * it is placed into a function-scope static variable; consequently - * the singleton instances are placed into static memory by default. - */ - class DependencyFactory2 - { - public: - typedef void* (*InstanceConstructor)(void); - - /** ensure initialisation by installing a default constructor function, - * but don't change an explicitly installed different constructor function. - * @remark deliberately this DependencyFactory has no constructor to - * initialise the object field \c ctorFunction_ to zero. - * The reason is, in the intended usage scenario, the - * DependencyFactory lives within a static variable, - * which might be constructed in no defined order - * in relation to the Depend instance. - */ - void - ensureInitialisation (InstanceConstructor defaultCtor) - { - if (!ctorFunction_) - this->ctorFunction_ = defaultCtor; - ENSURE (ctorFunction_); - } - - - /** explicitly set up constructor function, unless already configured - * In the default configuration, the template \c Depend installs a - * builder function to create a singleton instance in static memory. - * But specific instances might install e.g. a factory to create a - * implementation defined subclass; this might also be the place - * to hook in some kind of centralised service manager in future. - * @param ctor a function to be invoked to create a new service instance - * @throw error::Fatal when attempting to change an existing configuration. - */ - void - installConstructorFunction (InstanceConstructor ctor) - { - if (ctorFunction_ && ctor != ctorFunction_) - throw error::Fatal ("DependencyFactory: attempt to change the instance builder function " - "after-the-fact. Before this call, a different function was installed " - "and possibly also used already. Hint: visit all code locations, which " - "actually create an instance of the Depend template." - ,error::LUMIERA_ERROR_LIFECYCLE); - this->ctorFunction_ = ctor; - } - - - - /** invoke the installed ctor function */ - void* - buildInstance() - { - if (!ctorFunction_) - throw error::Fatal ("lib::Depend: attempt to retrieve a service object prior to initialisation " - "of the DependencyFactory. Typically, this happens due to a misconfiguration " - "regarding static initialisation order. When lib::Depend is placed into " - "a class static variable, then the definition and initialisation of that " - "variable must happen prior to the call which caused this exception." - ,error::LUMIERA_ERROR_LIFECYCLE); - return ctorFunction_(); - } - - - - - - private: - /** pointer to the concrete function - * used for building new service instances */ - InstanceConstructor ctorFunction_; - - - - /** function to build service instances. - * A service class with private ctor can declare DependencyFactory as friend, - * to indicate this is the expected way to create instances */ - template - static TAR* - create_in_buffer (void* buffer) - { - return new(buffer) TAR; - } - - - /** - * @internal Helper to manage a service instance within an embedded buffer. - * This helper and thus the service instance will be allocated into static memory. - */ - template - class InstanceHolder - : boost::noncopyable - { - /** storage for the service instance */ - char buff_[sizeof(TAR)]; - uint lifecycle_; - - - public: - InstanceHolder() - : lifecycle_(0) - { } - - ~InstanceHolder() - { - lifecycle_ |= 4; - if (1 & lifecycle_) - { - reinterpret_cast (buff_). ~TAR(); - --lifecycle_; - } } - - - TAR* - buildInstance () - { - if (0 < lifecycle_) - throw error::Fatal("Attempt to double-create a singleton service. " - "Either the application logic, or the compiler " - "or runtime system is seriously broken" - ,error::LUMIERA_ERROR_LIFECYCLE); - - // place new instance into embedded buffer - TAR* newInstance = create_in_buffer(buff_); - ++lifecycle_; - return newInstance; - } - }; - - - - template - static void* - createSingletonInstance() - { - static InstanceHolder storage; // note: the singleton(s) live here - return storage.buildInstance(); - } - - - template - friend InstanceConstructor buildSingleton2(); - - }; - - - - /** - * DSL-style marker function for client code - * to configure the usage of a specific subclass. - * Typically this function is used right within the - * Constructor call for lib::Depend; this allows to - * confine the actual service implementation class - * to a single compilation unit, without the need - * for clients of the respective service to know - * the actual concrete implementation class - */ - template - inline DependencyFactory2::InstanceConstructor - buildSingleton2() - { - return & DependencyFactory2::createSingletonInstance; - } - - -} // namespace lib -#endif diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 2ef93e6a3..51bfcaa2b 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -27027,7 +27027,7 @@ - + @@ -27191,12 +27191,59 @@ + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +