muduo网络库学习笔记(3)——Singleton类以及单例模式的总结

先介绍一下单例模式:
https://www.cnblogs.com/sunchaothu/p/10389842.html
上文所讲的几种单例模式从懒汉式(Lazy-Initialization)的方法升级到使用锁机制和智能指针,再升级到使用局部静态变量(关于静态变量的特性:如果当变量在初始化的时候,并发同时进入声明语句,并发线程将会阻塞等待初始化结束),对加深C++特性大有帮助。

但在muduo库中采用有pthread_once实现单例模式:

#ifndef MUDUO_BASE_SINGLETON_H
#define MUDUO_BASE_SINGLETON_H

#include "muduo/base/noncopyable.h"

#include <assert.h>
#include <pthread.h>
#include <stdlib.h> // atexit

namespace muduo
{

namespace detail
{
// This doesn't detect inherited member functions!
// http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions
template<typename T>
struct has_no_destroy
{
  template <typename C> static char test(decltype(&C::no_destroy));
  template <typename C> static int32_t test(...);
  const static bool value = sizeof(test<T>(0)) == 1;
};
}  // namespace detail

template<typename T>
class Singleton : noncopyable
{
 public:
  Singleton() = delete;
  ~Singleton() = delete;

  static T& instance()
  {
    pthread_once(&ponce_, &Singleton::init); //保证只初始化一次,并且线程安全
    assert(value_ != NULL);
    return *value_;
  }

 private:
  static void init()
  {
    value_ = new T();
    if (!detail::has_no_destroy<T>::value)
    {
      ::atexit(destroy);//atexit用来设置在程序正常结束前调用的函数
      					//程序结束自动销毁
    }
  }

  static void destroy()
  {
    typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1];//T必须为完整的类型,否则报错,而不是警告
    T_must_be_complete_type dummy; (void) dummy;

    delete value_;
    value_ = NULL;
  }

 private:
  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;

}  // namespace muduo

#endif  // MUDUO_BASE_SINGLETON_H

pthread_once函数

int pthread_once(pthread_once_t *once_control, void (*init_routine) (void));

pthread_once_t Singleton<T>::ponce_ = PTHREAD_ONCE_INIT;

功能:本函数使用初值为PTHREAD_ONCE_INIT的once_control变量保证init_routine()函数在本进程执行序列中仅执行一次。

Linux Threads使用互斥锁和条件变量保证由pthread_once()指定的函数执行且仅执行一次,而once_control表示是否执行过。
如果once_control的初值不是PTHREAD_ONCE_INIT(Linux Threads定义为0),pthread_once() 的行为就会不正常。

static变量:

  • 一个类中可以有一个或多个静态成员变量,所有的对象都共享这些静态成员变量,都可以引用它。
  • static 成员变量和普通 static 变量一样,都在内存分区中的全局数据区分配内存,到程序结束时才释放。这就意味着,static 成员变量不随对象的创建而分配内存,也不随对象的销毁而释放内存。而普通成员变量在对象创建时分配内存,在对象销毁时释放内存。
  • 静态成员变量必须初始化,而且只能在类体外进行。
  • 初始化时可以赋初值,也可以不赋值。如果不赋值,那么会被默认初始化为0。
  • 静态成员变量既可以通过对象名访问,也可以通过类名访问,但要遵循 private、protected 和 public 关键字的访问权限限制。当通过对象名访问时,对于不同的对象,访问的是同一份内存
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值