tars源码漫谈第28篇------tc_singleton.h(多线程下的单例)

2024-02-06 11:08

本文主要是介绍tars源码漫谈第28篇------tc_singleton.h(多线程下的单例),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

       要写一个单例, 很简单。 但是, 如果考虑多线程, 还真不是容易的事, 来看看tc_singleton.h:

/*** Tencent is pleased to support the open source community by making Tars available.** Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.** Licensed under the BSD 3-Clause License (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at** https://opensource.org/licenses/BSD-3-Clause** Unless required by applicable law or agreed to in writing, software distributed * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License.*/#ifndef __TC_SINGLETON_H__
#define __TC_SINGLETON_H__#include "util/tc_monitor.h"
#include <cassert>
#include <cstdlib>namespace tars
{
/
/** * @file tc_singleton.h * @brief  单件类 .  *  * 单件实现类* * 没有实现对单件生命周期的管理,使用示例代码如下:* * class A : public TC_Singleton<A, CreateStatic,  DefaultLifetime>* * {* *  public:* *    A(){cout << "A" << endl;}* *   ~A()* *   {* *     cout << "~A" << endl;* * *    }**    void test(){cout << "test A" << endl;}* * };* 对象的创建方式由CreatePolicy指定, 有如下方式:* * CreateUsingNew: 在堆中采用new创建* * CreateStatic`: 在栈中采用static创建* * 对象生命周期管理由LifetimePolicy指定, 有如下方式:* * DefaultLifetime:缺省声明周期管理* *如果单件对象已经析够, 但是还有调用, 会触发异常 * * PhoneixLifetime:不死生命周期* * 如果单件对象已经析够, 但是还有调用, 会再创建一个* * NoDestroyLifetime:不析够* * 对象创建后不会调用析够函数析够, 通常采用实例中的方式就可以了**/              
//*** @brief 定义CreatePolicy:定义对象创建策略*/
template<typename T>
class CreateUsingNew
{
public:/*** @brief  创建.*  * @return T**/static T* create() { return new T; }/*** @brief 释放. *  * @param t*/static void destroy(T *t) { delete t; }
};template<typename T>
class CreateStatic
{
public:/*** @brief   最大的空间*/ union MaxAlign { char t_[sizeof(T)]; long double longDouble_; }; /*** @brief   创建. * * @return T**/static T* create() { static MaxAlign t; return new(&t) T; }/*** @brief   释放. *  * @param t*/static void destroy(T *t) {t->~T();}
};/*** @brief 定义LifetimePolicy:定义对象的声明周期管理*/
template<typename T>
class DefaultLifetime
{
public:static void deadReference(){throw std::logic_error("singleton object has dead.");}static void scheduleDestruction(T*, void (*pFun)()){std::atexit(pFun);}
};template<typename T>
class PhoneixLifetime
{
public:static void deadReference(){_bDestroyedOnce = true;}static void scheduleDestruction(T*, void (*pFun)()){if(!_bDestroyedOnce)std::atexit(pFun);}
private:static bool _bDestroyedOnce; 
};
template <class T> 
bool PhoneixLifetime<T>::_bDestroyedOnce = false; template <typename T> 
struct NoDestroyLifetime 
{ static void scheduleDestruction(T*, void (*)()) {} static void deadReference() {} 
}; //
// Singleton
template
<typename T,template<class> class CreatePolicy   = CreateUsingNew,template<class> class LifetimePolicy = DefaultLifetime
>
class TC_Singleton 
{
public:typedef T  instance_type;typedef volatile T volatile_type;/*** @brief 获取实例* * @return T**/static T *getInstance(){//加锁, 双check机制, 保证正确和效率if(!_pInstance){TC_ThreadLock::Lock lock(_tl);if(!_pInstance){if(_destroyed){LifetimePolicy<T>::deadReference();_destroyed = false;}_pInstance = CreatePolicy<T>::create();LifetimePolicy<T>::scheduleDestruction((T*)_pInstance, &destroySingleton);}}return (T*)_pInstance;}virtual ~TC_Singleton(){}; protected:static void destroySingleton(){assert(!_destroyed);CreatePolicy<T>::destroy((T*)_pInstance);_pInstance = NULL;_destroyed = true;}
protected:static TC_ThreadLock    _tl;static volatile T*      _pInstance;static bool             _destroyed;protected:TC_Singleton(){}TC_Singleton (const TC_Singleton &); TC_Singleton &operator=(const TC_Singleton &);
};template <class T, template<class> class CreatePolicy, template<class> class LifetimePolicy> 
TC_ThreadLock TC_Singleton<T, CreatePolicy, LifetimePolicy>::_tl; template <class T, template<class> class CreatePolicy, template<class> class LifetimePolicy> 
bool TC_Singleton<T, CreatePolicy, LifetimePolicy>::_destroyed = false; template <class T, template<class> class CreatePolicy, template<class> class LifetimePolicy> 
volatile T* TC_Singleton<T, CreatePolicy, LifetimePolicy>::_pInstance = NULL; }#endif

        写得够风骚。如果没太读懂, 也没什么关系, 后面主要是单例的使用。 

        如果有必要看多线程单例的具体细节, 再看。

 

 

 

这篇关于tars源码漫谈第28篇------tc_singleton.h(多线程下的单例)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/684117

相关文章

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

Java使用多线程处理未知任务数的方案介绍

《Java使用多线程处理未知任务数的方案介绍》这篇文章主要为大家详细介绍了Java如何使用多线程实现处理未知任务数,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 知道任务个数,你可以定义好线程数规则,生成线程数去跑代码说明:1.虚拟线程池:使用 Executors.newVir

Spring 中 BeanFactoryPostProcessor 的作用和示例源码分析

《Spring中BeanFactoryPostProcessor的作用和示例源码分析》Spring的BeanFactoryPostProcessor是容器初始化的扩展接口,允许在Bean实例化前... 目录一、概览1. 核心定位2. 核心功能详解3. 关键特性二、Spring 内置的 BeanFactory

JAVA封装多线程实现的方式及原理

《JAVA封装多线程实现的方式及原理》:本文主要介绍Java中封装多线程的原理和常见方式,通过封装可以简化多线程的使用,提高安全性,并增强代码的可维护性和可扩展性,需要的朋友可以参考下... 目录前言一、封装的目标二、常见的封装方式及原理总结前言在 Java 中,封装多线程的原理主要围绕着将多线程相关的操

Python中多线程和多进程的基本用法详解

《Python中多线程和多进程的基本用法详解》这篇文章介绍了Python中多线程和多进程的相关知识,包括并发编程的优势,多线程和多进程的概念、适用场景、示例代码,线程池和进程池的使用,以及如何选择合适... 目录引言一、并发编程的主要优势二、python的多线程(Threading)1. 什么是多线程?2.

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2

Java多线程父线程向子线程传值问题及解决

《Java多线程父线程向子线程传值问题及解决》文章总结了5种解决父子之间数据传递困扰的解决方案,包括ThreadLocal+TaskDecorator、UserUtils、CustomTaskDeco... 目录1 背景2 ThreadLocal+TaskDecorator3 RequestContextH

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同

浅析Rust多线程中如何安全的使用变量

《浅析Rust多线程中如何安全的使用变量》这篇文章主要为大家详细介绍了Rust如何在线程的闭包中安全的使用变量,包括共享变量和修改变量,文中的示例代码讲解详细,有需要的小伙伴可以参考下... 目录1. 向线程传递变量2. 多线程共享变量引用3. 多线程中修改变量4. 总结在Rust语言中,一个既引人入胜又可

Go中sync.Once源码的深度讲解

《Go中sync.Once源码的深度讲解》sync.Once是Go语言标准库中的一个同步原语,用于确保某个操作只执行一次,本文将从源码出发为大家详细介绍一下sync.Once的具体使用,x希望对大家有... 目录概念简单示例源码解读总结概念sync.Once是Go语言标准库中的一个同步原语,用于确保某个操