muduo-base 源码分析(五)——singleton

重要的成员变量和函数

//默认构造函数和析构函数都删除,这里也可以设置为 private
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)
  {
    //程序结束后会调用 destroy 销毁对象
    ::atexit(destroy);
  }
}

//内部销毁对象
static void destroy()
{
  //判断 T 是不是完整类型
  //如果 T 不是完整类型,数组大小是 -1,发生错误
  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:
  // Tag member for Singleton<T>
  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()
{
  //一个程序只有一个 Test 对象,无论在什么线程中
  //创建一个 Test 对象
  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));
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值