重要的成员变量和函数
Singleton() = delete;
~Singleton() = delete;
static T& instance()
{
pthread_once(&ponce_, &Singleton::init);
assert(value_ != NULL);
return *value_;
}
static void init()
{
value_ = new T();
if (!detail::has_no_destroy<T>::value)
{
::atexit(destroy);
}
}
static void destroy()
{
typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1];
T_must_be_complete_type dummy; (void) dummy;
delete value_;
value_ = NULL;
}
static pthread_once_t ponce_;
static T* value_;
template<typename T>
pthread_once_t Singleton<T>::ponce_ = PTHREAD_ONCE_INIT;
template<typename T>
T* Singleton<T>::value_ = NULL;
test
#include "muduo/base/Singleton.h"
#include "muduo/base/CurrentThread.h"
#include "muduo/base/Thread.h"
#include <stdio.h>
class Test : muduo::noncopyable
{
public:
Test()
{
printf("tid=%d, constructing %p\n", muduo::CurrentThread::tid(), this);
}
~Test()
{
printf("tid=%d, destructing %p %s\n", muduo::CurrentThread::tid(), this, name_.c_str());
}
const muduo::string& name() const { return name_; }
void setName(const muduo::string& n) { name_ = n; }
private:
muduo::string name_;
};
class TestNoDestroy : muduo::noncopyable
{
public:
void no_destroy();
TestNoDestroy()
{
printf("tid=%d, constructing TestNoDestroy %p\n", muduo::CurrentThread::tid(), this);
}
~TestNoDestroy()
{
printf("tid=%d, destructing TestNoDestroy %p\n", muduo::CurrentThread::tid(), this);
}
};
void threadFunc()
{
printf("tid=%d, %p name=%s\n",
muduo::CurrentThread::tid(),
&muduo::Singleton<Test>::instance(),
muduo::Singleton<Test>::instance().name().c_str());
muduo::Singleton<Test>::instance().setName("only one, changed");
}
int main()
{
muduo::Singleton<Test>::instance().setName("only one");
muduo::Thread t1(threadFunc);
t1.start();
t1.join();
printf("tid=%d, %p name=%s\n",
muduo::CurrentThread::tid(),
&muduo::Singleton<Test>::instance(),
muduo::Singleton<Test>::instance().name().c_str());
muduo::Singleton<TestNoDestroy>::instance();
printf("with valgrind, you should see %zd-byte memory leak.\n", sizeof(TestNoDestroy));
}