Making a singleton of a global pointer with minimal work

D

Daniel Lidström

Hello!

I have discovered a way to make a global pointer accessible in a safe way,
that dosn't involve making lots of code changes. For example, let's say
that there is a class called _GHAL (from our code base) and that there is a
global pointer to the only instance of this class:

_GHAL* GHAL; // initialized as part of some startup code

Users of this class assume that the pointer actually points to an instance
of _GHAL. As you know, static initialization order can not be determined,
so if there are other classes using the GHAL pointer as part of their
initialization, we are in trouble. Now, it's quite easy to make _GHAL a
singleton class. Make the constructor private, as well as copy constructor
and assignment operator. Allow access only through static Instance method:

class _GHAL
{
_GHAL();
_GHAL(const _GHAL&);
_GHAL& operator=(const _GHAL&);
public:
static _GHAL& Instance(); // singleton point of access
};

Now, everyone using _GHAL has to write _GHAL::Instance().Method(...). This
is much better, but what if you don't know all the places the GHAL pointer
is actually used? There might be libraries using GHAL that you normally
don't compile. There are going to be compilation errors that other people
will have to fix, which is not a very nice thing to do. Well, I have found
a workaround that doesn't require any changes except to the _GHAL class and
to the global GHAL pointer. Let's have a look.

We need to change the GHAL pointer so that it works just like a _GHAL
pointer, but actually uses _GHAL as a singleton. What we do is to create a
new class, and overload operator->:

struct GHAL_ptr
{
_GHAL* operator->() const;
// Singleton point of access
static GHAL_ptr& Instance();
private:
GHAL_ptr();
GHAL_ptr(const GHAL_ptr&);
GHAL_ptr& operator=(const GHAL_ptr&);
};

This class is a singleton and we let the only instance be named GHAL.

extern GHAL_ptr& GHAL; // in a headerfile

Let's look at the implementation.

// operator-> returns a pointer to the only _GHAL instance
_GHAL* GHAL_ptr::eek:perator->() const
{
static _GHAL* theGHAL = &_GHAL::Instance();
return theGHAL;
}

GHAL_ptr::GHAL_ptr()
{}

// GHAL_ptr singleton access
GHAL_ptr& GHAL_ptr::Instance()
{
static GHAL_ptr theGHAL_ptr;
return theGHAL_ptr;
}

// initialize the global GHAL variable to the only GHAL_ptr instance
GHAL_ptr& GHAL = GHAL_ptr::Instance();

That's it! All those GHAL-> uses that might be littered all over the code
base will now be safe. No other code changes are required. Now we can
change all those GHAL-> into _GHAL::Instance() little by little, which is a
nice thing to do, I believe.

I hope this was interesting for someone! Comments are welcome.

P.S. Followup set to m.p.v.l because I can only post there.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,571
Members
45,045
Latest member
DRCM

Latest Threads

Top