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 <iostream>
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,29 +1,33 @@
|
|||
|
||||
#include "clang-static-init.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
|
||||
namespace test {
|
||||
|
||||
|
||||
int Subject::cnt = 0;
|
||||
int Subject::creationCount = 0;
|
||||
|
||||
Subject::Subject()
|
||||
{
|
||||
++cnt;
|
||||
std::cout << "Subject("<<cnt<<")\n";
|
||||
++creationCount;
|
||||
std::cout << "Subject("<<creationCount<<")\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
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&
|
||||
|
|
|
|||
|
|
@ -1,54 +1,132 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
using std::cout;
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
static T* instance;
|
||||
static I* instance;
|
||||
|
||||
T&
|
||||
I&
|
||||
get()
|
||||
{
|
||||
if (!instance)
|
||||
{
|
||||
instance = Fac<T>::create();
|
||||
cout << "Singleton Factory: invoke Fabrication ---> instance="<<&instance<<"...\n";
|
||||
|
||||
instance = Fac<I>::create();
|
||||
}
|
||||
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
|
||||
>
|
||||
T* Holder<T,F>::instance;
|
||||
I* Holder<I,F>::instance;
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
|
||||
template<typename C>
|
||||
struct Factory
|
||||
{
|
||||
static T*
|
||||
static C*
|
||||
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
|
||||
{
|
||||
static int cnt;
|
||||
static int creationCount;
|
||||
|
||||
Subject();
|
||||
|
||||
};
|
||||
|
||||
typedef Holder<Subject,Factory> AccessPoint;
|
||||
typedef ConfigurableHolder<Subject> AccessPoint;
|
||||
|
||||
extern AccessPoint fab;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue