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

server/2024/9/23 17:32:51/

目录

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.ppmy.cn/server/120893.html

相关文章

使用Redis实现用户关注博客的推模式

目录 一、思路 二、实现代码&#xff1a; 一、思路 发布者&#xff1a; 这里采用redis的zset结构&#xff0c;将键设置为被推送用户id&#xff0c;值设置为博客id&#xff0c;score设置为时间戳 推送之前先查到当前发布博客用户的粉丝有哪些&#xff0c;然后去循环挨个推送…

如何将 java.nio.ByteBuffer 转为 String

如何将 java.nio.ByteBuffer 转为 String 方法1: newString()方法结合ByteBuffer的array()方法, 忽略是否flip()过 用String的 public String(byte[] bytes, int offset, int length, Charset charset)方法 和 ByteBuffer的array()方法 长度在取 bbf.position()0?bbf.limit(…

银河麒麟桌面操作系统V10(SP1)离线升级SSH(OpenSSH)服务

目录 前言 准备工作 准备与目标服务器相同版本的操作系统 准备编译依赖包 下载OpenSSL源码包 下载OpenSSH源码包 升级OpenSSH服务 查看当前版本信息 安装编译依赖包 安装OpenSSL 安装OpenSSH 前言 OpenSSH是一个广泛使用的开源SSH(安全壳)协议的实现,它提供了安…

Android对象池的深入理解和使用

参考文献&#xff1a;https://www.jianshu.com/p/eb04e4e1869d 判断对象是否可以被回收 垃圾收集算法 内存分配与回收策略

安卓13长按电源按键直接关机 andriod13不显示关机对话框直接关机

总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析4.代码修改5.编译6.彩蛋1.前言 有些设备需要在长按电源键的时候,直接关机。不需要弹出对话框进行询问。 2.问题分析 过滤电源按键,需要在系统里面处理的话,那么我们需要熟悉android的事件分发,然后再…

ARM概念

一.CPU CPU&#xff1a;计算机的核心部件&#xff0c;负责执行指令和处理数据。它可以被视为计算机的“大脑”&#xff0c;负责运算、控制和数据传输等任务。 SoC&#xff08;系统级芯片&#xff09;是将多个组件集成在一个芯片上的设计&#xff0c;通常包括CPU、GPU、内存、…

关于less的基本使用

1、介绍及概述 1.1、解释 less 是方便开发人员书写CSS的一门预处理语言。浏览器只认识html /css /js格式的文件&#xff0c;所以直接引入.less文件&#xff0c;没有任何的效果&#xff0c;需要把less文件转换成css文件 1.2、概述 CSS弊端&#xff1a; 没有逻辑性、变量、函…

[数据集][目标检测]棉花叶子病害检测数据集VOC+YOLO格式977张22类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;977 标注数量(xml文件个数)&#xff1a;977 标注数量(txt文件个数)&#xff1a;977 标注类别…