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:
parent
675b2070ce
commit
4bd9eeb8ee
3 changed files with 109 additions and 35 deletions
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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&
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue