C++单例模式代码实现与分析

目录

1 代码

2 代码剖析

2.1 构造函数私有化

2.2 只能执行一次的代码

2.3 静态成员变量

2.4 智能指针


1 代码

下面的代码是https://github.com/Cambricon/CNStream 中的,

/************************************************************************** Copyright (C) [2022] by Cambricon, Inc. All rights reserved**  Licensed under the Apache License, Version 2.0 (the "License");*  you may not use this file except in compliance with the License.*  You may obtain a Copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* THE SOFTWARE.*************************************************************************/#include "buf_surface.h"#include <algorithm>
#include <cstring>  // for memset
#include <memory>
#include <mutex>
#include <queue>
#include <string>
#include <thread>#include "glog/logging.h"#include "buf_surface_impl.h"
#include "nvis/infer_server.h"
#include "common/utils.hpp"namespace infer_server {class BufSurfaceService {public:static BufSurfaceService &Instance() {static std::once_flag s_flag;std::call_once(s_flag, [&] { instance_.reset(new BufSurfaceService); });return *instance_;}~BufSurfaceService() = default;int BufPoolCreate(void **pool, BufSurfaceCreateParams *params, uint32_t block_num) {if (pool && params && block_num) {MemPool *mempool = new MemPool();if (!mempool) {LOG(ERROR) << "[InferServer] [BufSurfaceService] BufPoolCreate(): new memory pool failed";return -1;}*pool = reinterpret_cast<void *>(mempool);if (mempool->Create(params, block_num) == 0) {return 0;}delete mempool;LOG(ERROR) << "[InferServer] [BufSurfaceService] BufPoolCreate(): Create memory pool failed";return -1;}return -1;}int BufPoolDestroy(void *pool) {if (pool) {MemPool *mempool = reinterpret_cast<MemPool *>(pool);if (mempool) {int ret = mempool->Destroy();if (ret != 0) {VLOG(3) << "[InferServer] [BufSurfaceService] BufPoolDestroy(): Destroy memory pool failed, ret = " << ret;return ret;}delete mempool;}return 0;}LOG(ERROR) << "[InferServer] [BufSurfaceService] BufPoolDestroy(): Pool is not existed";return -1;}int CreateFromPool(BufSurface **surf, void *pool) {if (surf && pool) {BufSurface surface;MemPool *mempool = reinterpret_cast<MemPool *>(pool);if (mempool->Alloc(&surface) < 0) {VLOG(4) << "[InferServer] [BufSurfaceService] CreateFromPool(): Create BufSurface from pool failed";return -1;}*surf = AllocSurface();if (!(*surf)) {mempool->Free(&surface);LOG(WARNING) << "[InferServer] [BufSurfaceService] CreateFromPool(): Alloc BufSurface failed";return -1;}*(*surf) = surface;return 0;}LOG(ERROR) << "[InferServer] [BufSurfaceService] CreateFromPool(): surf or pool is nullptr";return -1;}int Create(BufSurface **surf, BufSurfaceCreateParams *params) {if (surf && params) {if (CheckParams(params) < 0) {LOG(ERROR) << "[InferServer] [BufSurfaceService] Create(): Parameters are invalid";return -1;}BufSurface surface;if (CreateSurface(params, &surface) < 0) {LOG(ERROR) << "[InferServer] [BufSurfaceService] Create(): Create BufSurface failed";return -1;}*surf = AllocSurface();if (!(*surf)) {DestroySurface(&surface);LOG(ERROR) << "[InferServer] [BufSurfaceService] Create(): Alloc BufSurface failed";return -1;}*(*surf) = surface;return 0;}LOG(ERROR) << "[InferServer] [BufSurfaceService] Create(): surf or params is nullptr";return -1;}int Destroy(BufSurface *surf) {if (!surf) {LOG(ERROR) << "[InferServer] [BufSurfaceService] Destroy(): surf is nullptr";return -1;}if (surf->opaque) {MemPool *mempool = reinterpret_cast<MemPool *>(surf->opaque);int ret = mempool->Free(surf);FreeSurface(surf);if (ret) {LOG(ERROR) << "[InferServer] [BufSurfaceService] Destroy(): Free BufSurface back to memory pool failed";}return ret;}// created by BufSurfaceCreate()int ret = DestroySurface(surf);FreeSurface(surf);if (ret) {LOG(ERROR) << "[InferServer] [BufSurfaceService] Destroy(): Destroy BufSurface failed";}return ret;}int Memset(BufSurface *surf, int index, uint8_t value) {if (!surf) {LOG(ERROR) << "[InferServer] [BufSurfaceService] Memset(): BufSurface is nullptr";return -1;}if (index < -1 || index >= static_cast<int>(surf->batch_size)) {LOG(ERROR) << "[InferServer] [BufSurfaceService] Memset(): batch index is invalid";return -1;}for (uint32_t i = 0; i < surf->batch_size; i++) {if (index >= 0 && i != static_cast<uint32_t>(index)) continue;CUDA_SAFECALL(cudaMemset(surf->surface_list[i].data_ptr, value, surf->surface_list[i].data_size), "[InferServer] [BufSurfaceService] Memset(): failed", -1);}return 0;}int Copy(BufSurface *src_surf, BufSurface *dst_surf) {if (!src_surf || !dst_surf) {LOG(ERROR) << "[InferServer] [BufSurfaceService] Copy(): src or dst BufSurface is nullptr";return -1;}// check parameters, must be the same sizeif (src_surf->batch_size != dst_surf->batch_size) {LOG(ERROR) << "[InferServer] [BufSurfaceService] Copy(): src and dst BufSurface has different batch size";return -1;}dst_surf->pts = src_surf->pts;bool src_host = (src_surf->mem_type == BUF_MEMORY_HOST);bool dst_host = (dst_surf->mem_type == BUF_MEMORY_HOST);if ((!dst_host && !src_host) && (src_surf->device_id != dst_surf->device_id)) {LOG(ERROR) << "[InferServer] [BufSurfaceService] Copy(): src and dst BufSurface is on different device";return -1;}for (size_t i = 0; i < src_surf->batch_size; ++i) {CUDA_SAFECALL(MemcpyHD(dst_surf->surface_list[i].data_ptr, dst_surf->mem_type, src_surf->surface_list[i].data_ptr, src_surf->mem_type, dst_surf->surface_list[i].data_size),"[InferServer] [BufSurfaceService] Copy(): failed", -1);}return 0;}private:BufSurfaceService(const BufSurfaceService &) = delete;BufSurfaceService(BufSurfaceService &&) = delete;BufSurfaceService &operator=(const BufSurfaceService &) = delete;BufSurfaceService &operator=(BufSurfaceService &&) = delete;BufSurfaceService() = default;private:std::mutex mutex_;bool initialized_ = false;std::queue<BufSurface *> surfpool_;BufSurface *start_ = nullptr, *end_ = nullptr;static const int k_surfs_num_ = 256 * 1024;private:void CreateSurfsPool() {if (initialized_) return;start_ = reinterpret_cast<BufSurface *>(malloc(sizeof(BufSurface) * k_surfs_num_));if (!start_) {LOG(ERROR) << "[InferServer] [BufSurfaceService] CreateSurfsPool(): Create BufSurface pointers failed";return;}end_ = &start_[k_surfs_num_ - 1];for (int i = 0; i < k_surfs_num_; i++) surfpool_.push(&start_[i]);initialized_ = true;}BufSurface *AllocSurface() {std::unique_lock<std::mutex> lk(mutex_);if (!initialized_) CreateSurfsPool();if (!surfpool_.empty()) {BufSurface *res = surfpool_.front();surfpool_.pop();return res;}return reinterpret_cast<BufSurface *>(malloc(sizeof(BufSurface)));}void FreeSurface(BufSurface *surf) {std::unique_lock<std::mutex> lk(mutex_);if (surf >= start_ && surf <= end_) {surfpool_.push(surf);return;}::free(surf);}private:static std::unique_ptr<BufSurfaceService> instance_;};std::unique_ptr<BufSurfaceService> BufSurfaceService::instance_;}  // namespace extern "C" {int BufPoolCreate(void **pool, BufSurfaceCreateParams *params, uint32_t block_num) {return infer_server::BufSurfaceService::Instance().BufPoolCreate(pool, params, block_num);}int BufPoolDestroy(void *pool) { return infer_server::BufSurfaceService::Instance().BufPoolDestroy(pool); }int BufSurfaceCreateFromPool(BufSurface **surf, void *pool) {return infer_server::BufSurfaceService::Instance().CreateFromPool(surf, pool);}int BufSurfaceCreate(BufSurface **surf, BufSurfaceCreateParams *params) {return infer_server::BufSurfaceService::Instance().Create(surf, params);}int BufSurfaceDestroy(BufSurface *surf) { return infer_server::BufSurfaceService::Instance().Destroy(surf); }int BufSurfaceMemSet(BufSurface *surf, int index, uint8_t value) {return infer_server::BufSurfaceService::Instance().Memset(surf, index, value);}int BufSurfaceCopy(BufSurface *src_surf, BufSurface *dst_surf) {return infer_server::BufSurfaceService::Instance().Copy(src_surf, dst_surf);}};  // extern "C"

2 代码剖析

简单看一下代码,看一下他怎么实现的单例模式

2.1 构造函数私有化

    private:BufSurfaceService(const BufSurfaceService &) = delete;BufSurfaceService(BufSurfaceService &&) = delete;BufSurfaceService &operator=(const BufSurfaceService &) = delete;BufSurfaceService &operator=(BufSurfaceService &&) = delete;BufSurfaceService() = default;

把所有的构造函数都声明成私有的,这样让用户只能通过下面的函数去实例化

        static BufSurfaceService &Instance() {static std::once_flag s_flag;std::call_once(s_flag, [&] { instance_.reset(new BufSurfaceService); });return *instance_;}

2.2 只能执行一次的代码

        static BufSurfaceService &Instance() {static std::once_flag s_flag;std::call_once(s_flag, [&] { instance_.reset(new BufSurfaceService); });return *instance_;}

这地方用了call_once保证后面的lambda表达式只会被执行一次。

2.3 静态成员变量

    private:static std::unique_ptr<BufSurfaceService> instance_;};std::unique_ptr<BufSurfaceService> BufSurfaceService::instance_;}  // namespace 

类里面声明了一个静态成员变量,并且在类外面对他进行了定义,但是这里只是给这个智能指针本身分配了内存,并没给他赋值,在调用Instance()函数的时候再给他赋值。

2.4 智能指针

    private:static std::unique_ptr<BufSurfaceService> instance_;};std::unique_ptr<BufSurfaceService> BufSurfaceService::instance_;}  // namespace 

这里的静态成员变量用的智能指针,防止内存泄漏。

参考文献:

C++_单例模式_c++单例模式-CSDN博客

C++ 设计模式——单例模式_c++ 单例模式-CSDN博客

GitHub - Cambricon/CNStream: CNStream is a streaming framework for building Cambricon machine learning pipelines http://forum.cambricon.com https://gitee.com/SolutionSDK/CNStream

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/147885.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

精益生产管理咨询公司哪家好?这份攻略请拿好

面对市场上琳琅满目的精益生产管理咨询公司&#xff0c;企业往往难以抉择&#xff1a;精益生产管理咨询公司哪家好&#xff1f;本文&#xff0c;天行健咨询将从专业性、实战经验、定制化服务、持续支持等多个维度&#xff0c;深入探讨如何评估并选择一家优秀的精益生产管理咨询…

24 C 语言常用的字符串处理函数详解:strlen、strcat、strcpy、strcmp、strchr、strrchr、strstr、strtok

目录 1 strlen 1.1 函数原型 1.2 功能说明 1.3 案例演示 1.4 注意事项 2 strcat 2.1 函数原型 2.2 功能说明 2.3 案例演示 2.4 注意事项 3 strcpy 3.1 函数原型 3.2 功能说明 3.3 案例演示 3.4 注意事项 4 strcmp 4.1 函数原型 4.2 功能说明 4.3 案例演示 …

2021 电子设计大赛-周期信号波形识别及参数测量装置( j 题)-SZPT领跑团队-凌云

目录 一、团队介绍 二、队伍介绍 三、题目要求 四、设计摘要 五、题目分析 1.基本要求 2.发挥部分 六、总体设计框图 七、硬件电路组成 &#xff08;1&#xff09;挡位检测 &#xff08;2&#xff09;挡位选择 &#xff08;3&#xff09;电压抬升电路 &#xff08;…

商标管理软件如何实现高效商标申请与管理?

在数字化时代&#xff0c;商标管理正逐步向智能化、自动化转型。企业对于商标管理软件的需求不再仅仅局限于内部流程的优化&#xff0c;更希望这些软件能够与外部系统无缝对接&#xff0c;实现一键递交官方的高效体验。启服云商标管理软件凭借其强大的技术实力和丰富的行业经验…

Python之一些列表的练习题

1.比较和对比字符串、列表和元组。例如&#xff0c;它们可以容纳哪类内容以及在数据结构上可以做哪些操作。 1. 内容类型:- 字符串: 只能包含字符(文本)。- 列表: 可以包含任意类型的数据,如数字、字符串、其他列表等。- 元组: 可以包含任意类型的数据,与列表类似。3. 操作:(1…

RK3568教学实验箱_操作教程:5-15 直流电机控制实验

一、产品简介 TL3568-PlusTEB人工智能实验箱 国产高性能处理器 64 位 4 核低功耗 2.0 GHz超高主频 1T 超高算力 NPU 兼容鸿蒙等国产操作系统 二、实验目的 1、熟悉Qt程序的开发流程&#xff1b; 2、掌握Qt Creator的基础开发使用&#xff1b; 3、通过编写Qt程序实现直流…

操作无法完成,因为文件已在 SWVisualize2022.BoostService 中打开

在使用 Windows 卸载文件的时候&#xff0c;会出现下面的情况 类似于Linux的强制删除&#xff0c;我们需要首先停止服务&#xff0c;解决方案如下&#xff0c; 进入 cmd 命令行窗口&#xff0c;首先停止服务 net stop "SWVisualize2022.BoostService" 如果需要&am…

ANSYS Workbench三维随机多面体骨料混凝土细观

在三维混凝土细观的有限元模拟中&#xff0c;混凝土细观几何模型的建立是仿真前提&#xff0c;也是其难点。在ANSYS内高效的建立三维几何模型以匹配混凝土中多面体骨料的外形、分布、级配等参数&#xff0c;是三维混凝土细观有限元仿真模拟的关键。 随机多面体骨料3D模型的建…

香港科技大学广州|金融科技学域博士招生宣讲会——武汉大学、华中科技大学

&#x1f514;&#x1f514;&#x1f514;明日宣讲&#x1f514;&#x1f514;&#x1f514; &#x1f490;香港科技大学广州&#xff5c;金融科技学域博士招生宣讲会 &#x1f4cd;武汉大学专场 &#x1f559;时间&#xff1a;2024年9月24日&#xff08;星期二&#xff09;1…

fmql之字符驱动设备(1)

上一篇文章&#xff0c;记录了模块入口和出口函数的编写。 这一篇要继续编写字符驱动程序了。 仍然参考正点原子&#xff1a; 第3.3讲 我的第一个Linux驱动-字符设备驱动框架搭建实验_哔哩哔哩_bilibili 驱动注册和卸载 字符驱动设备的注册函数位register_chrdev 卸载函数…

让PlatformIO支持ESP32C3 SuperMini

先介绍一下这块小尺寸板子&#xff1a; ESP32C3SuperMini是一款基于 Espressif ESP32-C3 WiFi/蓝牙双模芯片的 IoT 迷你开发板。ESP32-C3 是一款32 位 RISC-V CPU&#xff0c;包含FPU&#xff08;浮点单元&#xff09;&#xff0c;可进行32 位单精度运算&#xff0c;具有强大的…

如何写出高收录词的listing文案,先做好这一点

在亚马逊上&#xff0c;关键词是连接买家搜索与产品之间的桥梁&#xff0c;超过80%的购买行为都是通过搜索关键词开始的。因此&#xff0c;文案中包含的精准关键词越多&#xff0c;Listing越能匹配买家的需求&#xff0c;从而提高自然排名并优化广告效果。 亚马逊的收录分为静…

vue.js 展示一个树形结构的数据视图,并禁用其中默认选中的节点

功能描述 展示树形结构&#xff1a; 使用 Element UI 的 <el-tree> 组件展示树形结构数据。数据由 content 数组提供&#xff0c;树形结构包含了嵌套的节点及其子节点。 默认选中节点&#xff1a; 使用 defaultCheckedKeys 属性指定默认选中的节点。这些节点在树形结构渲…

基于51单片机控制恒压供水系统设计

文章目录 前言资料获取设计介绍功能介绍设计程序具体实现截图文档目录设计获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师&#xff0c;一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设…

手把手教您轻松实现微信/QQ/TIM多开,消息防撤回!

文章目录 📖 介绍 📖🏡 环境 🏡📒 防回撤 📒🚀 自动补丁工具(支持多开,支持微信、QQ、TIM)🚀 最新版手动补丁📝 步骤一📝 步骤二⚓️ 相关链接 ⚓️📖 介绍 📖 在日常聊天中,微信消息被撤回的情况屡见不鲜,总让人心中充满好奇——那些被删去的内容…

【c数据结构】OJ练习篇 帮你更深层次理解链表!(相交链表、相交链表、环形链表、环形链表之寻找环形入口点、判断链表是否是回文结构、 随机链表的复制)

目录 一. 相交链表 二. 环形链表 三. 环形链表之寻找环形入口点 四. 判断链表是否是回文结构 五. 随机链表的复制 一. 相交链表 最简单粗暴的思路&#xff0c;遍历两个链表&#xff0c;分别寻找是否有相同的对应的结点。 我们对两个链表的每个对应的节点进行判断比较&…

量化交易----数据透视表----融资融券优惠代码

我们在制定和执行量化策略的过程中&#xff0c;常常需要快速检查目标因子组合的分组下portfolio的超额收益&#xff0c;我们来提供一个快速的方法&#xff0c;可以实现单因子分组&#xff0c;双因子分组和三因子分组 比如拿到一个分析师预测的数据库&#xff0c;和A股市场政策…

python:django项目知识点02——搭建简易授权码核销系统

前言 如标题所述&#xff0c;本篇博客主要围绕快速搭建业务系统展开&#xff0c;旨在&#xff1a;快速、逻辑分明。 适用对象 djangomysql&#xff0c;实现一套授权码核销功能&#xff0c;包含用户登录和授权码核销两个方面内容 业务代码 前述 基础代码已在上篇博客中讲述&…

Vue3:provide-inject实现组件通信

目录 一.作用 1.跨层级通信 2.避免重复声明 3.封装通用服务 二.性质 1.非响应式 2.不可选项 3.高级用法 三.使用 1.爷组件 2.父组件 3.子组件 四.代码 1.爷组件代码 2.父组件代码 3.子组件代码 五.效果 Vue3中的provide-inject机制是用于在组件树中进行依赖注…

01【MATLAB】最小二乘系统辨识

目录 1.系统辨识的定义及其分类 1.1 系统辨识的定义 1.2 系统辨识的分类 2.参数模型 3.系统辨识的步骤 一、最小二乘法&#xff08;Least Squares Method&#xff09;一般步骤 二、LSM原理及应用 三、LSM在控制系统建模中的应用 1.系统辨识的定义及其分类 1.1 系统辨识的…