muduo库的Singleton类剖析

C++开源项目学习指南:从入门到精通的实战路径 C++作为一门支撑操作系统、游戏引擎、数据库等核心系统的基础编程语言,其高性能和底层控制能力是构建复杂软件系统的基石。理解其核心原理,如内存管理、编译过程和并发模型,对于掌握系统级编程至关重要。现代C++标准(C++11/14/17/20)引入了智能指针、移动语义等特性,极大地提升了开发效率和代码安全性,其技术价值在于能够构建出既高效又可靠的大型软件。在实际应用场景中,无论是开发**高性能网络服务器**、**实时图形渲染引擎**,还是构建分布式存储系统,深入学习和借鉴优秀的开源项目都是快速提升工程能力的捷径 阅读详情


如题,分析muduo库线程安全的单例模式类。

它的类图如下:



分析如下:

#ifndef MUDUO_BASE_SINGLETON_H
#define MUDUO_BASE_SINGLETON_H

#include <boost/noncopyable.hpp>
#include <assert.h>
#include <stdlib.h> // atexit
#include <pthread.h>

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(typeof(&C::no_destroy)); // or decltype in C++11
  template <typename C> static int32_t test(...);
  const static bool value = sizeof(test<T>(0)) == 1;    //判断如果是类的话,是否有no_destroy方法。
};
}

template<typename T>
class Singleton : boost::noncopyable
{
 public:
  static T& instance()   //得到对象
  {
    pthread_once(&ponce_, &Singleton::init);   //第一次调用会在init函数内部创建,pthread_once保证该函数只被调用一次!!!!
    									   //并且pthread_once()能保证线程安全,效率高于mutex
    assert(value_ != NULL);
    return *value_;    //利用pthread_once只构造一次对象
  }

 private:
  Singleton();
  ~Singleton();

  static void init()   //客户端初始化该类
  {
    value_ = new T();   //直接调用构造函数
    if (!detail::has_no_destroy<T>::value)   //当参数是类且没有"no_destroy"方法才会注册atexit的destroy
    {
      ::atexit(destroy);   //登记atexit时调用的销毁函数,防止内存泄漏
    }
  }

  static void destroy()  //程序结束后自动调用该函数销毁
  {
    //用typedef定义了一个数组类型,数组的大小不能为-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;   //赋空
  }

 private:
  static pthread_once_t ponce_;     //pthread_once的参数
  static T*             value_;        //模板T类型的指针
};

template<typename T>
pthread_once_t Singleton<T>::ponce_ = PTHREAD_ONCE_INIT;   //初始化pthread_once

template<typename T>
T* Singleton<T>::value_ = NULL;    //静态成员外部会初始化为空

}
#endif

类内部用了C++的SFINAE技术,我在另外一篇博客中有介绍: http://blog.youkuaiyun.com/freeelinux/article/details/53429009


muduo的单例模式采用模板类实现,它内部维护一个模板参数的指针,可以生成任何一个模板参数的单例。凭借SFINAE技术muduo库可以检测模板参数如果是类的话,并且该类注册了一个no_destroy()方法,那么muduo库不会去自动销毁它。否则muduo库会在init时,利用pthread_once()函数为模板参数,注册一个atexit时的destroy()垃圾回收方法,实现自动垃圾回收。智能指针也能达到类似的效果,我们平时写的单例模式在Singleton中写一个Garbage类也可以完成垃圾回收。

muduo库与我们平时使用mutex取get_instance不同,我们平时通常在get_Instance中只产生对象,在此之前需要先手动调用init()方法。但muduo库使用了pthread_once()函数,该函数只会执行一次,且是线程安全的函数,所以只有在我们第一次get_instance()时,才会自动调用Init()方法。此后只会获取实例。

不得不说,开了眼界,原来单例模式还可以这样写。

百度新闻评论内容抓取 通过抓包分析发现,百家号手机app端文章评论内容接口为:https://ext.baidu.com/api/comment/v1/comment/getlist?appid=101&sid=1008524_2-1010050_1-1007549_23033-1007550_23035&cuid=01B5EAF73E8A83BB842BE04E4FB6C656|23200201047... 阅读详情

相关推荐

LSTM模型 轨迹经纬度预测

原始时间序列数据如下所示,我们只取前两列纬度和经度作为输入数据 我们设定用前六个位置信息预测下一个位置,则两个样本的输入输出数据如下所示: 创建LSTM网络训练模型: import numpy as np from keras.layers.core import Dense, Activation, Dropout from keras.layers import LS...

Muzi_Water的博客 2万+

has_no_destroy

本来想写Singleton的,但是被这个结构体给难住了。于是便查了下相关资料,这篇知乎的文章讲的比较多,可以看下:https://zhuanlan.zhihu.com/p/21314708。 template<typename T> struct has_no_destroy { template <typename C> static char test(decltype(&C::no_destroy)); template <typename C&gt.

qu1993的博客 770

MicroLogix1400编程(使用RSLogix 500 + RSLinx Classic Lite)

MicroLogix1400编程

noscallion的博客 1万+

模版检查类中是否有某个成员函数

//例子1 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; }; /

少言才不会咸's Tech-blog 560

IC版图设计之OASIS文件格式详解

OASIS(Open Artwork System Interchange Standard)是继GDSII之后新一代的集成电路版图数据交换标准,由SEMI在2004年正式发布(SEMI标准号:SEMI P39)。高压缩率:相比GDSII可减少3-10倍文件体积扩展性强:支持纳米级工艺的复杂图形描述跨平台兼容:独立于EDA工具和操作系统安全增强:内置校验和与加密支持。

ZZcppc的博客 2443

YOLOV8主干改进方法:C2f-Dual——DualConv轻量化双卷积设计(附改进代码)

DualConv是一种创新的卷积网络结构,旨在构建轻量级的深度神经网络。它通过结合3×3和1×1的卷积核处理相同的输入特征映射通道,优化了信息处理和特征提取。DualConv利用组卷积技术高效排列卷积滤波器,大大降低了计算成本和参数数量。

m0_74890428的博客 4700

检查类中是否有某个成员函数

1.检查类中是否有成员函数,不包括继承的成员函数 //例子1 template<typename T> struct has_no_destroy { template <typename C> static char test(decltype(&C::no_destroy)); template <typename C> static i...

小磊的专栏 691

搭建ROS小车真的难吗?

搭建ROS小车真的难吗?不难 1.引言 本着为大家谋福利的心态,根据自己以往的开发经验,打算写一个从零开始制作一个可以实现地图构建和导航的ROS小车。目前某宝上面有很多现成产品,但是我个人认为,一个好的移动机器人开发工程师,应该对机器人的整个流程都能具备维护的能力,然后再深入研究其中一个方向即可。看到网上很少有整个系列的开发教程,看到同学们大多东拼西凑,浪费了不少时间。我就想着利用空余时间,将我本人的开发过程输出给大家。有基础理论、有实际工程代码、有丰富的学习资料,尽最大努力帮大家进入移动机器人的大门。 国

「小白学移动机器人」一个专注分享移动机器人相关知识的公众号! 1万+

学习muduo库(7)之单例类Singleton

UML: pthread_once(&ponce_, &Singleton::init); pthread_once(&ponce_, &Singleton::init);是一个线程安全的,且保证Singleton::init仅仅被执行一次。 解释: Singleton是一个模板类,而且所有的成员都是静态的,所有不用生成对象。使用时这样写: mud...

请叫我少爷的博客 443

pandas教程:2012 Federal Election Commission Database 2012联邦选举委员会数据库

里面包含了支持者的名字,职业和雇主,地址,赞助金额。我们可以已经能想到如何切割、整理数据,来提取赞助者的统计数据,或提取宣传活动的模式,这里我们展示一些不同的分析方法。可以看到有些职业是同一种工作类型,指代的是同一个东西。这两个连续操作是分别独立执行的,一个结束后,另一个才开始。上,这里我是把数据集压缩成了ZIP格式,解压后能正常导入)。我觉得也有必要好好了解一下,这个网站做了很好的讲解,),所以我们最好添加这样的信息。这样的情况,即把两个索引操作连在一起。,发现映射关系被正常执行了,所以这里的。

Cachel Wood的博客 349

区块链技术概述:从比特币到Web3.0

区块链技术正重塑数字世界的信任机制。本文系统梳理了区块链的发展路径:从比特币的PoW共识和UTXO模型,到以太坊的智能合约和账户体系,直至Web3.0的去中心化互联网愿景。文章详细解析了区块链的核心特性(去中心化、不可篡改等)和数据结构,通过流程图展示了比特币交易生命周期和智能合约执行流程,并对比了Web2.0与Web3.0的关键差异。最后,用Python代码实现了包含区块类、交易处理和挖矿机制的简易区块链系统,为理解区块链底层原理提供了实践参考。

闲人编程的博客 456

(P26-P27)muduo_base库源码分析:muduo网络库的类图,定时器函数选择

文章目录1.muduo网络库的类图2.时序图 1.muduo网络库的类图 类图如下: 解释如下: 灰色是内部类,对外不可见; 白色是外部类,对外可见; EventLoop类 EventLoop是对事件循环的抽象; Poller类,PollPoller类,EPollPoller类 (1)下面的三个是muduo唯一使用面向对象编程思想的地方,下面三个类都是内部类,Poller是抽象类,有三个纯虚函数,muduo的对外接口不使用虚函数来暴露的: Poller是对I/O复用的抽象; PollPol

喜欢打篮球的普通人 741

MALTAB程序利用质心法去寻峰

质心法的优点是简单易实现且计算速度快,适用于数据点较少或峰值较明显的情况。然而,对于复杂的数据或多峰曲线,质心法可能无法准确识别所有峰值,因此在这些情况下可能需要使用更复杂的峰值检测算法。质心法(Centroid Method)是一种寻找峰值的方法,其基本原理是通过计算数据窗口内的质心位置来确定峰值的位置。质心是指在一维数据中,按照数据的幅值对位置进行加权平均的结果,即质心位置为数据幅值加权平均值的位置。变量定义了计算质心的窗口大小。最后,绘制了找到的峰值位置和幅值点,并显示了找到的峰值位置和幅值的结果。

走向CTO的路上... 1347

muduo网络库学习之BlockinngQueue<T>类、ThreadPool 类、Singleton类封装中的知识点

一、BlockinngQueue类、BoundedBlockingQueue类 生产者消费者问题,可以用信号量+互斥锁 或者 条件变量+互斥锁 来解决,还分为有界和无界缓冲区两种情形,如下图: 有界缓冲区: 生产者: 信号量+互斥锁:1,2,3,4,5 条件变量+互斥锁:2,1,3,5,4(框框) 消费者: 信号量+互斥锁:1,2,3,

Meditation 3666

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

muduo源码分析2——Singleton分析

1. 一般singleton写法 2. muduo::singleton

weixin_44537992的博客 2245

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

muduo_inspect库源码分析(41)

muduo_inspect库通过HTTP方式为服务器提供监控接口 接受了多少个TCP连接 当前有多少个活动连接 一共响应了多少次请求 每次请求的平均响应时间多少毫秒 。。。 Inspector     // 包含了一个HttpServer对象 ProcessInspector // 通过ProcessInfo返回进程信息 ProcessInfo // 获取进程相关信息

Riak, Spark, Golang, Erlang, 云存储, 云计算, 数据挖掘 1791

muduo源码剖析——Singleton单例模式之懒汉模式与DCL双重检查

0 懒汉与饿汉 对于Singleton单例模式我们并不陌生,但我们常用的多是饿汉模式: Singleton实例的声明和实例化在instance()函数中同时完成。 而懒汉模式要求,Singleton实例的声明和实例化分开: 先声明Singleton实例对象,然后调用时才在instance()中完成实例化。 具体见下面代码。 1 饿汉模式 没有事先声明Log单例对象,Log实例同时完成声明和实例化。 class Log { public: //C++11以后,使用局部变量懒汉不用加锁 st

高自强的博客 451

muduo之Singleton

muduo中的单例模式 Singleton.h // Use of this source code is governed by a BSD-style license // that can be found in the License file. // // Author: Shuo Chen (chenshuo at chenshuo dot com) #ifn...

1万+

muduo事件循环类图简介

muduo事件循环类图简介 1.  总体类图       下图摘自于网上资源: 注意:黑色菱形:组合;白色菱形:聚合;白色三角形:继承;实线:关联 2.

chenglinhust的专栏 1459

muduo 中 has_no_destroy 模板

在学些muduo源码中,单例模式源码中有这么一段 namespace detail { // This doesn't detect inherited member functions! // http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions template&l...

Sweet_Oranges的专栏 806

muduo网络库源码复现笔记(八):base库的Singleton.h

Muduo网络库简介 muduo 是一个基于 Reactor 模式的现代 C++ 网络库,作者陈硕。它采用非阻塞 IO 模型,基于事件驱动和回调,原生支持多核多线程,适合编写 Linux 服务端多线程网络应用程序。 muduo网络库的核心代码只有数千行,在网络编程技术学习的进阶阶段,muduo是一个非常值得学习的开源库。目前我也是刚刚开始学习这个网络库的源码,希望将这个学习过程记录下来。这个网络库的源码已经发布在GitHub上,可以点击这里阅读。目前Github上这份源码已经被作者用c++11重写,我学习的

梁熙民的csdn博客 582

muduo库源码学习(base)singleton

/* SFINAE的意思是这样的,假如有一个特化会导致编译时错误(即出现编译失败),只要还有别的选择可以被选择, 那么就无视这个特化错误而去选择另外的可选选择。 这个示例中,如果我们给传的参数T类型为POD类型, 当调用detail::has_no_destroy::value时,T参数会在has_no_destroy类中实例化模板, 由于是POD类型,不具备no_destroy方法,不

lsaejn的专栏 582

C++模板之SFINAE技术

今天在阅读muduo库的源码时,里面有这样几行代码: template struct has_no_destroy { template static char test(typeof(&C::no_destroy)); // or decltype in C++11 template static int32_t test(...); const static bool val

FreeeLinux's blog 4849

muduo:Singleton类,单例模式

#include <boost/noncopyable.hpp> #include <assert.h> #include <stdlib.h> // atexit #include <pthread.h> template<typename T> class Singleton : boost::noncopyable { public: static T& instance() {

yvhqbat的博客 1202

muduo net库学习笔记2——muduo网络库相关类图的关系、EventLoop、Channel、 Poller

Acceptor接收到客户端请求,调用TcpServer回调函数 TcpServer回调函数中创建TcpConnection对象,代表着一个Tcp连接 TcpConnection构造函数中创建Channel对象,保存客户端套接字fd和关心的事件(可读) Channel 注册自己到所属事件驱动循环(EventLoop)中的Poller上 Poller开始监听,当发现Channel被激活后将其添加到EventLoop的激活队列中 EventLoop在poll返回后处理激活队列中的Channel,调用其处理函数

qq_37299596的博客 907

muduo库源码解析:单例模式singleton

单例模式实现 boost::noncopyable 防止复制,如果是自己实现,那要把构造函数、拷贝构造,复制构造都私有 公有方法: 获取单例对象:instance() 返回 value 引用,(第一次 -->pthread_once --> init  )  私有: 初始化new一单例:init()--并 atexit 注册销毁函数释放delete value 构造函数、拷贝构造,复制

le119126的专栏 1790
上一篇: C++模板之SFINAE技术
下一篇: muduo库的ThreadLocal类剖析
FreeeLinux
博客等级 码龄11年 421粉丝 356原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值