293 lines
11 KiB
C++
293 lines
11 KiB
C++
//------------------------------------------------------------------------------
|
|
// File : SkySingleton.hpp
|
|
//------------------------------------------------------------------------------
|
|
// SkyWorks : Copyright 2002 Mark J. Harris and
|
|
// The University of North Carolina at Chapel Hill
|
|
//------------------------------------------------------------------------------
|
|
// Permission to use, copy, modify, distribute and sell this software and its
|
|
// documentation for any purpose is hereby granted without fee, provided that
|
|
// the above copyright notice appear in all copies and that both that copyright
|
|
// notice and this permission notice appear in supporting documentation.
|
|
// Binaries may be compiled with this software without any royalties or
|
|
// restrictions.
|
|
//
|
|
// The author(s) and The University of North Carolina at Chapel Hill make no
|
|
// representations about the suitability of this software for any purpose.
|
|
// It is provided "as is" without express or
|
|
// implied warranty.
|
|
/**
|
|
* @file SkySingleton.hpp
|
|
*
|
|
* A generic singleton template wrapper to make classes into singletons
|
|
*/
|
|
#ifndef __SKYSINGLETON_HPP__
|
|
#define __SKYSINGLETON_HPP__
|
|
|
|
#include "SkyUtil.hpp"
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* @class SkySingleton
|
|
* @brief A singleton template class.
|
|
*
|
|
* Usage : Use this template container class to make any class into a
|
|
* singleton. I usually do this:
|
|
*
|
|
* @code
|
|
* class MyClass
|
|
* {
|
|
* public:
|
|
* // normal class stuff, but don't put ctor/dtor here.
|
|
* int GetData() { return _someData; }
|
|
* protected:
|
|
* // Make the ctor(s)/dtor protected, so this can only be
|
|
* // instantiated as a singleton. Note: singleton will still
|
|
* // work on classes that do not follow this (public ctors)
|
|
* // but violation of the singleton is possible then, since non-
|
|
* // singleton versions of the class can be instantiated.
|
|
* MyClass() : _someData(5) {}
|
|
* MyClass(int arg) : _someData(arg) {} // etc...
|
|
* // don't implement the copy constructor, because singletons
|
|
* // shouldn't be copied!
|
|
* MyClass(const MyClass& mc) {}
|
|
* ~MyClass() {}
|
|
* private:
|
|
* int _someData;
|
|
* };
|
|
*
|
|
* // now create a singleton of MyClass
|
|
* typedef SkySingleton<MyClass> MyClassSingleton;
|
|
*
|
|
* @endcode
|
|
* Later, in your program code, you can instantiate the singleton and access
|
|
* its members like so:
|
|
*
|
|
* @code
|
|
* void somefunc()
|
|
* {
|
|
* // instantiate the MyClassSingleton
|
|
* MyClassSingleton::Instantiate();
|
|
* // could also call MyClassSingleton::Instantiate(10);
|
|
* // since we have a constructor of that form in MyClass.
|
|
*
|
|
* // access the methods in MyClass:
|
|
* int data1 = MyClassSingleton::InstancePtr()->GetData();
|
|
* // or...
|
|
* int data2 = MyClassSingleton::InstanceRef().GetData();
|
|
*
|
|
* // now destroy the singleton
|
|
* MyClassSingleton::Destroy();
|
|
* }
|
|
* @endcode
|
|
*/
|
|
template <class T>
|
|
class SkySingleton : protected T
|
|
{
|
|
public:
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Function : Instantiate
|
|
// Description :
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* @fn Instantiate()
|
|
* @brief Creates the singleton instance for class T.
|
|
*
|
|
* Assures (by assertion) that the instance will only be created once.
|
|
* This works for default constructors.
|
|
*/
|
|
static void Instantiate()
|
|
{
|
|
assert(!s_pInstance);
|
|
s_pInstance = new SkySingleton();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Function : Destroy
|
|
// Description :
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* @fn Destroy() { SAFE_DELETE(s_pInstance); }
|
|
* @brief Destructor, deletes the instance
|
|
*/
|
|
static void Destroy() { SAFE_DELETE(s_pInstance); }
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Function : InstancePtr
|
|
// Description :
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* @fn InstancePtr() { assert(s_pInstance); return s_pInstance; }
|
|
* @brief Returns a pointer to the instance
|
|
*/
|
|
static T* InstancePtr() { assert(s_pInstance); return s_pInstance; }
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Function : InstanceRef
|
|
// Description :
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* @fn InstanceRef() { assert(s_pInstance); return *s_pInstance; }
|
|
* @brief Returns a reference to the instance
|
|
*/
|
|
static T& InstanceRef() { assert(s_pInstance); return *s_pInstance; }
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Function : static void Instantiate
|
|
// Description :
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* @fn static void Instantiate(const A& a)
|
|
* @brief Instantiates class of type T that have constructors with an argument
|
|
*
|
|
* This might be a source of confusion. These templatized
|
|
* functions are used to instantiate classes of type T that
|
|
* have constructors with arguments. For n arguments, you
|
|
* to add a function below with n arguments. Note, these will
|
|
* only be created if they are used, since they are templates.
|
|
* I've added 4 below, for 1-4 arguments. If you get a
|
|
* compilation error, add one for the number of arguments you
|
|
* need. Also need a SkySingleton protected constructor with
|
|
* the same number of arguments.
|
|
*/
|
|
template<class A>
|
|
static void Instantiate(const A& a)
|
|
{
|
|
assert(!s_pInstance);
|
|
s_pInstance = new SkySingleton(a);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Function : Instantiate
|
|
// Description :
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* @fn Instantiate(const A& a, const B& b)
|
|
* @brief Instantiates class of type T that have constructors with 2 args
|
|
*/
|
|
template<class A, class B>
|
|
static void Instantiate(const A& a, const B& b)
|
|
{
|
|
assert(!s_pInstance);
|
|
s_pInstance = new SkySingleton(a, b);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Function : Instantiate
|
|
// Description :
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* @fn Instantiate(const A& a, const B& b, const C& c)
|
|
* @brief Instantiates class of type T that have constructors with 3 args
|
|
*/
|
|
template<class A, class B, class C>
|
|
static void Instantiate(const A& a, const B& b, const C& c)
|
|
{
|
|
assert(!s_pInstance);
|
|
s_pInstance = new SkySingleton(a, b, c);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Function : Instantiate
|
|
// Description :
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* @fn Instantiate(const A& a, const B& b, const C& c, const D& d)
|
|
* @brief Instantiates class of type T that have constructors with 4 args
|
|
*/
|
|
template<class A, class B, class C, class D>
|
|
static void Instantiate(const A& a, const B& b, const C& c, const D& d)
|
|
{
|
|
assert(!s_pInstance);
|
|
s_pInstance = new SkySingleton(a, b, c, d);
|
|
}
|
|
|
|
protected:
|
|
// although the instance is of type SkySingleton<T>, the Instance***() funcs
|
|
// above implicitly cast it to type T.
|
|
static SkySingleton* s_pInstance;
|
|
|
|
private:
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Function : SkySingleton
|
|
// Description :
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* @fn SkySingleton()
|
|
* @brief Hidden so that the singleton can only be instantiated via public static Instantiate function.
|
|
*/
|
|
SkySingleton() : T() {}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Function : Singleton
|
|
// Description :
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* @fn Singleton(const A& a)
|
|
* @brief Used by the templatized public Instantiate() functions.
|
|
*/
|
|
template<class A>
|
|
SkySingleton(const A& a) : T(a) {}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Function : Singleton
|
|
// Description :
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* @fn Singleton(const A& a, const B& b)
|
|
* @brief Used by the templatized public Instantiate() functions.
|
|
*/
|
|
template<class A, class B>
|
|
SkySingleton(const A& a, const B& b) : T(a, b) {}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Function : Singleton
|
|
// Description :
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* @fn Singleton(const A& a, const B& b, const C& c)
|
|
* @brief Used by the templatized public Instantiate() functions.
|
|
*/
|
|
template<class A, class B, class C>
|
|
SkySingleton(const A& a, const B& b, const C& c) : T(a, b, c) {}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Function : Singleton
|
|
// Description :
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* @fn Singleton(const A& a, const B& b, const C &c, const D& d)
|
|
* @brief Used by the templatized public Instantiate() functions.
|
|
*/
|
|
template<class A, class B, class C, class D>
|
|
SkySingleton(const A& a, const B& b, const C &c, const D& d) : T(a, b, c, d) {}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Function : SkySingleton
|
|
// Description :
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* @fn SkySingleton(const SkySingleton&)
|
|
* @brief Hidden because you can't copy a singleton!
|
|
*/
|
|
SkySingleton(const SkySingleton&) {} // hide the copy ctor: singletons can'
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Function : ~SkySingleton
|
|
// Description :
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* @fn ~SkySingleton()
|
|
* @brief Destructor, hidden, destroy via the public static Destroy() method.
|
|
*/
|
|
~SkySingleton() {} // hide the dtor:
|
|
};
|
|
|
|
// declare the static instance pointer
|
|
template<class T> SkySingleton<T>* SkySingleton<T>::s_pInstance = NULL;
|
|
|
|
#endif //__SKYSINGLETON_HPP__
|