Singleton Implementation 7/1/2016 1 CS 631: Singleton Implementation

advertisement
Singleton Implementation
7/1/2016
CS 631: Singleton Implementation
1
Outline
• Dead Reference Problem
– Dead Reference Detection
•
•
•
•
The Phoenix Singleton
Policy Classes
Template Template Parameters
Assembling SingletonHolder
7/1/2016
CS 631: Singleton Implementation
2
Dead Reference Problem
• Example
– Another singleton Logger reports any events in the
system.
– When it shuts down it needs to report the latest state of
the market.
• Problem
– Assume both Market and Logger are Meyers singletons.
– The runtime C++ support destroys local static objects in
the reverse order of their creation.
– If the Market is created before the Logger it will be
destroyed first.
– The Logger needs to report the latest market at the
destruction, but it will get a reference to the "shell" of the
destroyed Market object. Undefined behavior!!!
7/1/2016
CS 631: Singleton Implementation
3
Detection of the Dead Reference
class DeadRefMarket
{
public:
static DeadRefMarket& getInstance()
{
if (!instance)
if (flagDestroyed)
onDeadReference();
else
create();
return *instance;
}
virtual ~DeadRefMarket()
{
instance = 0;
flagDestroyed = true;
}
...
7/1/2016
CS 631: Singleton Implementation
4
Detection of the Dead Reference (cont.)
private:
DeadRefMarket() {} ...
static void create()
{
static DeadRefCfg localInstance;
instance = &localInstance;
}
static void onDeadReference()
{throw std::runtime_error ("Dead reference detected");}
static DeadRefMarket* instance;
static bool flagDestroyed;
};
DeadRefMarket* DeadRefMarket::instance = 0;
bool DeadRefMarket::flagDestroyed = false;
7/1/2016
CS 631: Singleton Implementation
5
The Phoenix Singleton
• The above implementation detects the dead
reference, but does not ensure that the singleton is
available at all times.
• The Phoenix singleton ensures that an instance is
created again if the dead reference is detected.
7/1/2016
CS 631: Singleton Implementation
6
The Phoenix Singleton: Implementation
class PhoenixMarket
{
public:
static PhoenixMarket& getInstance()
{
if (!instance)
if (flagDestroyed)
onDeadReference();
else
create();
return *instance;
}
virtual ~PhoenixMarket()
{
instance = 0;
flagDestroyed = true;
}
double getRate(double maturity)
{return rates[maturity);}
7/1/2016
CS 631: Singleton Implementation
7
The Phoenix Singleton Implementation
private:
PhoenixMarket() {}
static void create()
{
static PhoenixMarket localInstance;
instance = &localInstance;
}
static void onDeadReference()
{
create();
// Create a new singleton at the instance
// address. (C++ guarantees that the static object's
// memory lasts for the duration of the program!)
new(instance) PhoenixMarket;
atexit(kill);
flagDestroyed = false;
}
7/1/2016
CS 631: Singleton Implementation
8
The Phoenix Singleton Implementation
(cont.)
void kill(void)
{
instance->~ PhoenixMarket();
}
static PhoenixMarket* instance;
static bool flagDestroyed;
};
PhoenixMarket* PhoenixMarket ::instance = 0;
bool PhoenixMarket::flagDestroyed = false;
7/1/2016
CS 631: Singleton Implementation
9
Policies
• Policies help in implementing safe, efficient and
highly customizable design elements.
• A policy defines a class interface or a class template
interface.
• The interface consists of one or all of the following:
– inner type definitions;
– member functions;
– member data.
• Example: define policy classes that implement the
Creator policy.
7/1/2016
CS 631: Singleton Implementation
10
Creator Policy: Using new()
template <class T> struct OpNewCreator
{
static T* create()
{
return new T;
}
};
7/1/2016
CS 631: Singleton Implementation
11
Creator Policy: Using malloc()
template <class T> struct MallocCreator
{
static T* create()
{
void* buf = malloc(sizeof(T));
if (!buf)
return 0;
// placement new operator!
return new(buf) T; }
}
7/1/2016
CS 631: Singleton Implementation
12
Policy: Analysis
• For a given policy there can be an unlimited number
of implementations, which are called policy classes.
• Unlike classic interfaces (abstract classes), policy
interfaces are loosely defined.
• Policies are syntax oriented, not signature oriented.
– For example, the Creator policy does not specify that
create must be static or virtual – the only requirement is
that the class define a create member function.
• Example
– The Market class needs to create a new Index that holds
specific rates.
7/1/2016
CS 631: Singleton Implementation
13
Creator Policy Usage
// Library code:
template <class CreationPolicy>
class Market : public
class CreationPolicy
{
...
Index* index = create();
...
};
// Client code:
typedef Market<OpNewCreator<Index> >
MyMarket;
7/1/2016
CS 631: Singleton Implementation
14
Template Template Parameters
template <template<class Created>
class CreationPolicy>
class Market : public CreationPolicy<Index>
{
...
Index* index = create();
...
};
// The Created symbol can simply be omitted as it
// does not contribute to the definition of Market:
7/1/2016
CS 631: Singleton Implementation
15
Template Template Parameters (cont.)
// Library code:
template <template<class>
class CreationPolicy>
class Market : public CreationPolicy<Index>
{
...
Index* index = create();
...
};
// Client code:
typedef Market<OpNewCreator> MyMarket;
7/1/2016
CS 631: Singleton Implementation
16
Assembling SingletonHolder
template <
class T,
template <class> class
CreationPolicy = CreateUsingNew,
template <class> class
LifetimePolicy = DefaultLifetime
>
class SingletonHolder
{
public:
7/1/2016
CS 631: Singleton Implementation
17
Assembling SingletonHolder (cont.)
static T& getInstance()
{
if (! instance)
{
if (flagDestroyed)
{
LifetimePolicy<T>::onDeadReference();
flagDestroyed = false;
}
instance = CreationPolicy<T>::create();
LifetimePolicy<T>::scheduleCall
(&destroySingleton);
}
return *instance;
}
7/1/2016
CS 631: Singleton Implementation
18
Assembling SingletonHolder (cont.)
private:
SingletonHolder();
static void destroySingleton()
{
CreationPolicy<T>::destroy(instance);
instance = 0;
flagDestroyed = false;
}
static T* instance;
static bool flagDestroyed;
};
template<class T>
T* SingletonHolder<T>::instance = 0;
template<class T>
bool SingletonHolder<T>:: flagDestroyed = false;
7/1/2016
CS 631: Singleton Implementation
19
SingletonHolder: Creation Policy
// Creation policy example:
template <class T> struct CreateUsingNew
{
static T* create()
{
return new T;
}
static void destroy(T* p)
{
delete p;
}
};
7/1/2016
CS 631: Singleton Implementation
20
SingletonHolder: Creation Policy
// LifetimePolicy example:
template <class T>
struct DefaultLifetime
{
static void ScheduleCall(void (*pFun)())
{std::atexit(pFun);}
static void onDeadReference()
{
throw
std::logic_error
("Dead Reference Detected");
}
};
// Client code:
typedef SingletonHolder<Market> BasicMarket;
7/1/2016
CS 631: Singleton Implementation
21
Download