bughunt: re-create the whole 2nd layer with a configurable product type --> HIT

Now we've reprduced the problematic situation in isolation
This commit is contained in:
Fischlurch 2013-10-06 18:50:53 +02:00
parent 675b2070ce
commit 4bd9eeb8ee
3 changed files with 109 additions and 35 deletions

View file

@ -1,26 +1,18 @@
#include "clang-static-init.hpp" #include "clang-static-init.hpp"
#include <iostream>
using std::cout;
using std::endl;
using namespace test;
int int
main (int, char**) main (int, char**)
{ {
cout << "\n.gulp.\n"; cout << "\nStart Testcase: invoking two instances of the configurable singleton factory...\n";
Subject& ref1 = fab.get(); test::Subject& ref1 = test::fab.get();
Subject& sub2 = test::fabricate(); test::Subject& sub2 = test::fabricate();
cout << "sub1="<< &ref1 << " sub2="<< &sub2 <<"\n"; cout << "sub1="<< &ref1 << " sub2="<< &sub2 <<"\n";
return 0; return 0;
} }

View file

@ -1,29 +1,33 @@
#include "clang-static-init.hpp" #include "clang-static-init.hpp"
#include <iostream>
using std::cout;
using std::endl;
namespace test { namespace test {
int Subject::cnt = 0; int Subject::creationCount = 0;
Subject::Subject() Subject::Subject()
{ {
++cnt; ++creationCount;
std::cout << "Subject("<<cnt<<")\n"; std::cout << "Subject("<<creationCount<<")\n";
} }
namespace { namespace {
// TypeInfo<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& Subject&

View file

@ -1,54 +1,132 @@
#include <iostream>
using std::cout;
namespace test { namespace test {
template<typename T
,template <class> class Fac
/* === Layer-1: a singleton factory based on a templated static variable === */
template<typename I ///< Interface of the product type
,template <class> class Fac ///< Policy: actual factory to create the instance
> >
struct Holder struct Holder
{ {
static T* instance; static I* instance;
T& I&
get() get()
{ {
if (!instance) if (!instance)
{ {
instance = Fac<T>::create(); cout << "Singleton Factory: invoke Fabrication ---> instance="<<&instance<<"...\n";
instance = Fac<I>::create();
} }
return *instance; return *instance;
} }
}; };
/**
template<typename T * allocate storage for the per-type shared
* (static) variable to hold the singleton instance
*/
template<typename I
,template <class> class F ,template <class> class F
> >
T* Holder<T,F>::instance; I* Holder<I,F>::instance;
template<typename T>
template<typename C>
struct Factory struct Factory
{ {
static T* static C*
create() create()
{ {
return new T(); return new C();
} }
}; };
/* === Layer-2: configurable product type === */
template<typename I>
struct Adapter
{
typedef I* FactoryFunction (void);
static FactoryFunction* factoryFunction;
template<typename C>
static I*
concreteFactoryFunction()
{
return static_cast<I*> (Factory<C>::create());
}
template<typename X>
struct AdaptedConfigurableFactory
{
static X*
create()
{
return (*factoryFunction)();
}
};
};
/** storage for the per-type shared function pointer to the concrete factory */
template<typename I>
typename Adapter<I>::FactoryFunction* Adapter<I>::factoryFunction;
template<typename C>
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<typename T>
struct ConfigurableHolder
: Holder<T, Adapter<T>::template AdaptedConfigurableFactory>
{
/** define the actual product type */
template<typename C>
ConfigurableHolder (TypeInfo<C>)
{
Adapter<T>::factoryFunction = &Adapter<T>::template concreteFactoryFunction<C>;
}
};
/* === Actual usage: Test case fabricating Subject instances === */
struct Subject struct Subject
{ {
static int cnt; static int creationCount;
Subject(); Subject();
}; };
typedef Holder<Subject,Factory> AccessPoint; typedef ConfigurableHolder<Subject> AccessPoint;
extern AccessPoint fab; extern AccessPoint fab;