Skip to content
Snippets Groups Projects
Commit f64130c6 authored by Markus Blatt's avatar Markus Blatt
Browse files

An adapter for easily constructing singletons. (This is fun! Templates rule!)

[[Imported from SVN: r4602]]
parent 5d0b2baf
No related branches found
No related tags found
No related merge requests found
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_SINGLETON_HH
#define DUEN_DINGLETON_HH
/**
* @file
* @brief Usefull wrapper for creating singletons.
*
* Inspirated by the article
* <a href="http://www.codeguru.com/cpp/cpp/cpp_mfc/singletons/article.php/c755/">CodeGuru: A Leak-Free Singleton class</a>
*/
namespace Dune
{
/**
* @brief An adapter to turn a class into a singleton.
*
* The class represented by the template parameter T must
* have a parameterless constructor.
*
* Class T can be publically
* derived from Singleton<T>:
*
* \code
* #include<dune/common/singleton.hh>
* class Foo : public Dune::Singleton<Foo>
* {
* public:
* Foo()
* {
* bytes = new char[1000];
* }
*
* ~Foo()
* {
* delete[] bytes;
* }
* private:
* char* bytes;
* };
* \endcode
*
* Or one can construct a Singleton of an existing class. Say Foo1 is a class
* with parameterless constructor then
* \code
* typedef Dune::Singleton<Foo1> FooSingleton;
* Foo1 instance& = FooSingleton::instance();
* \endcode
* Creates a singleton of that class and accesses its instance.
*/
template<class T>
class Singleton
{
public:
/**
* @brief A simple smart pointer responsible for creation
* and deletion of the instance.
*/
class InstancePointer
{
public:
/** @brief Construct a null pointer. */
InstancePointer() : pointer_(0)
{}
/** @brief Delete the instance we point to. */
~InstancePointer()
{
if(pointer_ != 0)
delete pointer_;
}
/**
* @brief Get a pointer to the instance.
* @return The instance we store.
*/
T* get()
{
return pointer_;
}
/**
* @brief Set the pointer.
* @paramter pointer A pointer to the instance.
*/
void set(T* pointer)
{
if(pointer != 0) {
delete pointer_;
pointer_ = pointer;
}
}
private:
T* pointer_;
};
private:
/** @brief Smartpointer to the instance. */
static InstancePointer instance_;
protected:
/* @brief Private constructor. */
Singleton(){}
/** @brief Private copy constructor. */
Singleton(const Singleton&){}
/** @brief Private assignment operator. */
Singleton& operator=(const Singleton&){}
public:
/**
* @brief Get the instance of the singleton.
* @return The instance of the singleton.
*/
static T& instance()
{
if(instance_.get() == 0)
instance_.set(new T());
return *instance_.get();
}
};
template<class T>
typename Singleton<T>::InstancePointer Singleton<T>::instance_;
} // namespace Dune
#endif
......@@ -24,3 +24,4 @@ timing_old
timing_flt
bigunsignedinttest
mpihelpertest
singletontest
......@@ -3,7 +3,7 @@
TESTPROGS = parsetest test-stack arraylisttest smartpointertest \
sllisttest iteratorfacadetest tuplestest fmatrixtest \
poolallocatortest settest gcdlcdtest streamtest \
bigunsignedinttest mpihelpertest
bigunsignedinttest mpihelpertest singletontest
# exprtmpl
# which tests to run
......@@ -78,4 +78,7 @@ mpihelpertest_SOURCES = mpihelpertest.cc
mpihelpertest_CXXFLAGS = $(MPI_CPPFLAGS)
mpihelpertest_LDFLAGS = $(MPI_LDFLAGS) $(MPI_LIBS)
singletontest_SOURCES = singletontest.cc
singletontest_LDFLAGS = $(LOCAL_LIBS)
include $(top_srcdir)/am/global-rules
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#include <dune/common/singleton.hh>
#include <iostream>
class Foo : public Dune::Singleton<Foo>
{
public:
Foo()
{
bytes = new char[1000];
}
~Foo()
{
delete[] bytes;
}
private:
char* bytes;
};
class Foo1
{
public:
Foo1()
{
bytes = new char[1000];
}
~Foo1()
{
delete[] bytes;
}
private:
char* bytes;
};
typedef Dune::Singleton<Foo1> FooSingleton;
Foo* globalFoo = 0;
Foo1* globalFoo1 = 0;
void setFoo()
{
globalFoo = &Foo::instance();
}
void setFoo1()
{
globalFoo1 = &FooSingleton::instance();
}
int testFoo()
{
if(globalFoo != &Foo::instance()) {
std::cerr<<" Foo is not a real singleton!"<<std::endl;
return 1;
}
return 0;
}
int testFoo1()
{
if(globalFoo1 != &FooSingleton::instance()) {
std::cerr<<" Foo is not a real singleton!"<<std::endl;
return 1;
}
return 0;
}
int main()
{
int ret=0;
{
Foo& foo = Foo::instance();
Foo& foo1 = Foo::instance();
if(&foo!=&foo1) {
std::cerr<<" Foo is not a real singleton!"<<std::endl;
++ret;
}
}
setFoo();
ret += testFoo();
{
Foo1& foo = FooSingleton::instance();
Foo1& foo1 = FooSingleton::instance();
if(&foo!=&foo1) {
std::cerr<<" Foo is not a real singleton!"<<std::endl;
++ret;
}
}
setFoo1();
return ret += testFoo1();
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment