From 4bd9eeb8ee81d57072c874c2a7b2d1b758abb6ce Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 6 Oct 2013 18:50:53 +0200 Subject: [PATCH] bughunt: re-create the whole 2nd layer with a configurable product type --> HIT Now we've reprduced the problematic situation in isolation --- research/clang-static-init-1.cpp | 14 +--- research/clang-static-init-2.cpp | 24 ++++--- research/clang-static-init.hpp | 106 +++++++++++++++++++++++++++---- 3 files changed, 109 insertions(+), 35 deletions(-) diff --git a/research/clang-static-init-1.cpp b/research/clang-static-init-1.cpp index 7170aa999..020f469b3 100644 --- a/research/clang-static-init-1.cpp +++ b/research/clang-static-init-1.cpp @@ -1,26 +1,18 @@ #include "clang-static-init.hpp" -#include -using std::cout; -using std::endl; - -using namespace test; - int main (int, char**) { - cout << "\n.gulp.\n"; + cout << "\nStart Testcase: invoking two instances of the configurable singleton factory...\n"; - Subject& ref1 = fab.get(); - Subject& sub2 = test::fabricate(); + test::Subject& ref1 = test::fab.get(); + test::Subject& sub2 = test::fabricate(); cout << "sub1="<< &ref1 << " sub2="<< &sub2 <<"\n"; return 0; } - - diff --git a/research/clang-static-init-2.cpp b/research/clang-static-init-2.cpp index 80cba771e..c23468837 100644 --- a/research/clang-static-init-2.cpp +++ b/research/clang-static-init-2.cpp @@ -1,29 +1,33 @@ #include "clang-static-init.hpp" -#include - -using std::cout; -using std::endl; namespace test { - int Subject::cnt = 0; + int Subject::creationCount = 0; Subject::Subject() { - ++cnt; - std::cout << "Subject("< shall_build_a_Subject_instance; } - AccessPoint fab; + /** + * instance of the singleton factory + * @note especially for this example we're using just \em one + * shared instance of the factory. + * Yet still, the two (inlined) calls to the get() function + * access different addresses for the embedded singleton instance + */ + AccessPoint fab(shall_build_a_Subject_instance); Subject& diff --git a/research/clang-static-init.hpp b/research/clang-static-init.hpp index f0694fd6b..6597e8b05 100644 --- a/research/clang-static-init.hpp +++ b/research/clang-static-init.hpp @@ -1,54 +1,132 @@ +#include + +using std::cout; + namespace test { - - template class Fac + + + + /* === Layer-1: a singleton factory based on a templated static variable === */ + + template class Fac ///< Policy: actual factory to create the instance > struct Holder { - static T* instance; + static I* instance; - T& + I& get() { if (!instance) { - instance = Fac::create(); + cout << "Singleton Factory: invoke Fabrication ---> instance="<<&instance<<"...\n"; + + instance = Fac::create(); } return *instance; } }; - - template class F > - T* Holder::instance; + I* Holder::instance; - template + + template struct Factory { - static T* + static C* create() { - return new T(); + return new C(); } }; + + + /* === Layer-2: configurable product type === */ + + template + struct Adapter + { + typedef I* FactoryFunction (void); + + static FactoryFunction* factoryFunction; + + + template + static I* + concreteFactoryFunction() + { + return static_cast (Factory::create()); + } + + + template + struct AdaptedConfigurableFactory + { + static X* + create() + { + return (*factoryFunction)(); + } + }; + }; + + /** storage for the per-type shared function pointer to the concrete factory */ + template + typename Adapter::FactoryFunction* Adapter::factoryFunction; + + + + template + struct TypeInfo { }; + + + + /** + * Singleton factory with the ability to configure the actual product type C + * only at the \em definition site. Users get to see only the interface type T + */ + template + struct ConfigurableHolder + : Holder::template AdaptedConfigurableFactory> + { + /** define the actual product type */ + template + ConfigurableHolder (TypeInfo) + { + Adapter::factoryFunction = &Adapter::template concreteFactoryFunction; + } + }; + + + + + + /* === Actual usage: Test case fabricating Subject instances === */ + struct Subject { - static int cnt; + static int creationCount; Subject(); }; - typedef Holder AccessPoint; + typedef ConfigurableHolder AccessPoint; extern AccessPoint fab;