Similar presentations:
Ood_wk10
1. Object-Oriented Design Workshop
HST CCS Training SeriesObject-Oriented Design Workshop
Patterns of Object Creation, Part 3
1
2. Object-Oriented Design Workshop Week 10: Patterns of Object Creation, Part 3 (Singleton Revisited)
David Van CampObject Technology Consultant
Software Architects
P.O. Box 3104, Collegedale, TN 37315
Phone: (301) 918-7431
[email protected]
2
7/97
3. O-O Design Workshop
Week 10: Patterns of Object Creation,Part 3 (Singleton Revisited)
Topics of this Workshop:
Singleton Variations and Gottcha’s
Singleton Review and Example
Variation: Controlled multiple instances
Gottcha: To Kill a Singleton
Gottcha: Double-Checked Locking
avoiding race conditions in a multi-threaded environment
7/97
3
4. GOF Singleton
Purpose of a Singleton?Insure only one instance of a class can
1ever
exist at any point in time
Provide a global point of access to that
2instance
4
5. GOF Singleton
SingletonClient
aMethod()
$self : Singleton *
someData
if (self is NULL)
self = new Singleton
return self
$instance()
doOperation()
...
Singleton::instance()->doOperation()
...
Source: Design Patterns: Elements of Reusable ObjectOriented Software, Gamma, Helm, Johnson & Vlissides,
Addison-Wesley, 1994
5
6. Singleton Example: SignalHandler A micro-framework for Unix signal handling
SignalCallbackAdapterClientAncestor
{optional}
getInstance()
registerCallback(signo)
signalRecieved(signo)
~SignalCallbackAdapter()
SignalHandlerSingleton
callbacks $self
callbacks[max]
$instance()
$signalHandler(signo)
registerCallback(signo, adapter)
removeCallback(signo, adapter)
return SignalHandler::instance()
p=getInstance()
return p->registerCallback (signo, this)
CallbackClient
someOperation
signalRecieved(signo)
perform actions required
when a registered signal is
received.
getInstance()->removeCallback (signo, this)
...
registerCallback (signo)
...
6
7. Variation: Multiple Singletons
Variation:Allow a controlled but variable number of instances of the Singleton
(hmm… should we call this a “multiton”??? ☺)
Implementation
The instance function can easily be implemented to allow multiple
instances of the Singleton class, while still maintaining full control over
each instance
The singleton maintains a list of pointers to each created object.
The instance function may take a parameter which indicates a key value
for a specific instance to create or retrieve.
Subclasses may be used to determine the specific types created based on a
key value parameter.
The singleton may define a registration facility of possible instances that
can be created and returned.
7
8. Variation: Multiple Singletons
Example - Login for Multi-User System:class User {
public:
static const User * LogIn(const char * name,
const char * password);
protected:
static User * Lookup(const char *name);
private:
static List<UserName> * _instances;
}
class UserName : public ListItem {
User * instance;
char * name;
}
8
9. Gottcha: To Kill a Singleton
Singleton DestructorMust have one! Allow no dangling references.
Set the self attribute to 0 (or for “multitons”, look-up list
entry and remove.)
Public, Private or Protected?
Public: Anyone could delete singleton, may cause dangling
references! Not recommended.
Private: Restrict ability to subclass Singleton. Not
recommended.
Protected: Allows subclassing Singleton -- Recommended.
9
10. Gottcha: To Kill a Singleton
When and How to Destroy a Singleton?Use the atexit() function to register a private, static
destroy() method which is called on program exit:
public const Singleton * Singleton::instance(){
if (self==0) {self = new Singleton;
atexit (destroy); }
return self; }
private static void Singleton::destroy() {
if (self != 0) delete self; }
Reference Counting: Provide a “release” method to request
deletion. Singleton may be deleted when count reaches 0:
public static void Singleton::release(){
if (--ref_count == 0) delete self; }
10
11. Gottcha: Multi-threaded Singletons
Problem:Singletons used in multi-theaded systems are
susceptible to a “race” condition during execution of
the instance() function which can allow creation of
multiple instances and cause a memory leak.
Solution: Double-Checked Locking
In the instance() function, if self is zero, then aquire a
lock (semaphore, mutex, etc.).
Next, double check to insure that self is still zero
If self is still zero, then create an instance of the
Singleton and assign it to self.
Release the lock and return.
11
12. Gottcha: Multi-threaded Singletons
Example Code:class Singleton {
public:
static Singleton * instance();
private:
static Singleton * self;
static SEMAPHORE key
}
Singleton * Singleton::instance() {
if (self == 0) {
if ( lock(key) >= 0 ) {
if (self == 0 ) //double-check!
self = new Singleton;
unlock (key);
} } }
12
13. GOF Singleton Web References
Web References:Issue: How & when to destroy a singleton?
“To Kill A Singleton,” John Vlissides, C++ Report, June 1996
http://www.sigs.com/publications/docs/cppr/9606/cppr9606.c.vlissides.html
Issue: How to insure that Singleton’s work properly in a multithreaded
environment?
“Double-Checked Locking -- A Optimization Pattern for Efficiently
Initializing and Accessing Thread-safe Objects.,” Douglas C. Schmidt,
Presented at the 3rd annual Pattern Languages of Programming
conference in Allerton Park, Illinois, September 4-6, 1996
http://www.sigs.com/publications/docs/cppr/9606/cppr9606.c.vlissides.html
13