Object-Oriented Design Workshop
Object-Oriented Design Workshop Week 10: Patterns of Object Creation, Part 3 (Singleton Revisited)
O-O Design Workshop
GOF Singleton
GOF Singleton
Singleton Example: SignalHandler A micro-framework for Unix signal handling
Variation: Multiple Singletons
Variation: Multiple Singletons
Gottcha: To Kill a Singleton
Gottcha: To Kill a Singleton
Gottcha: Multi-threaded Singletons
Gottcha: Multi-threaded Singletons
GOF Singleton Web References
924.00K

Ood_wk10

1. Object-Oriented Design Workshop

HST CCS Training Series
Object-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 Camp
Object 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

Singleton
Client
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

SignalCallbackAdapter
ClientAncestor
{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 Destructor
Must 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
English     Русский Rules