可用于缓存大量数据的模板类

2020年5月21日

上一篇怎样说到下图所示的处理数据的流程,我给出了Sensor类的实现。那么这个类是针对线阵相机的数据结构实现的,如果我现在换成3D相机又该怎么操作,我发现只要更换数据结构体就行,其他都可以不用动。再进一步思考,这个模型适用的情形总可以是“一头高频次的出数据,另一头不断地处理数据”。那我完全可以将这一套逻辑封装成一个模板类。
数据处理流程图

template<typename D>
class proSensor
{
   ......
}

可以将D换成任何类型的数据。

#pragma once
#include <windows.h>

template<typename D>
class proSensor
{
public:
	using DATA = std::shared_ptr<D>;
	using OnData = std::function<int(void* _system, void* _context, DATA _data)>;
	proSensor(void* _system, OnData callback);
	~proSensor();
	void PushDataInQueue(DATA data);
private:

	void ProcessDataQueue(void* para);
	std::mutex m_DataMtx_;
	std::queue<DATA> m_QueCamData_;
	std::condition_variable m_DataVar_;
	bool m_bQueExit_ = false;
	std::shared_ptr<SThreadPool> m_Pool_;
	std::future<void> m_fuProcessDataQue_;
	OnData m_fnData_ = nullptr;
	void* m_System_ = nullptr;
	void* m_Context_ = nullptr;
};

template<typename D >
proSensor<D>::proSensor(void* _system, OnData callback)
{
	m_fuProcessDataQue_ = std::async(std::launch::async, &proSensor<D>::ProcessDataQueue, this, nullptr);
	m_fnData_ = callback;
	m_Context_ = this;
	m_System_ = _system;
}

template<typename D >
proSensor<D>::~proSensor()
{
	{
		std::unique_lock<std::mutex> locker(m_DataMtx_);
		m_bQueExit_ = true;
	}
	m_DataVar_.notify_one();
	m_fuProcessDataQue_.get();
}

template<typename D>
void proSensor<D>::PushDataInQueue(DATA data)
{
	//将数据压入到队列中
	{
		std::unique_lock<std::mutex> lock(m_DataMtx_);
		m_QueCamData_.push(data);
	}
	m_DataVar_.notify_one();//通知另外一个线程进行数据的处理
}

//将队列中的数据弹出,并从回调中获取
template<typename D>
void proSensor<D>::ProcessDataQueue(void* para)
{
	DATA tempdata;
	std::unique_lock<std::mutex> locker(m_DataMtx_);
	while (true)
	{
		try
		{
			if (!m_bQueExit_) m_DataVar_.wait(locker);
			locker.unlock();
			while (true)
			{
				locker.lock();
				if (m_QueCamData_.empty())
				{
					std::cout << "camera set queue is empty.\n";
					break;
				}
				else
				{
					tempdata = m_QueCamData_.front();
					m_QueCamData_.pop();
				}
				locker.unlock();
				if (m_fnData_)
					m_fnData_(m_System_, m_Context_, tempdata);
			}
		}
		catch (const std::exception& e)
		{
			std::cout << e.what() << "\n";
		}
		if (m_bQueExit_)
		{
			break;
		}
	}
}

下面做了个简单实现,详细看注释。

头文件定义

#include <iostream>
#include "proSensorData.h"
#include "SThreadPool.h"

struct BeforeCameraData
{
	int height;
	int width;
	int datasize;
	char* data;
	UINT64 timestamps;
};

struct AfterCameraData
{
	int height;
	int width;
	int datasize;
	std::unique_ptr<char[]> data;
	UINT64 timestamps;
};

class Cameras
{
public:
	Cameras();
	~Cameras() {}

	//相机回调,并在回调中将相机数据压入容器中//
	friend int WINAPI s_ManagaGetImageCallBack(void* _context, void* _system, void* _data);
	friend int WINAPI s_ProcessLineData(void* _system, void* _context, std::shared_ptr<AfterCameraData> data);
	friend void t_SaveImage(void* para, std::shared_ptr<AfterCameraData> data);

private:
	std::shared_ptr<SThreadPool> m_ThreadPool_ = nullptr;
	std::shared_ptr<proSensor<AfterCameraData>> m_proCamera_;
};

实现

int WINAPI s_ManagaGetImageCallBack(void* _context, void* _system, void* _data)
{
	BeforeCameraData* BeData = (BeforeCameraData*)_data;
	Cameras* pThis = (Cameras*)_context;
	//...将BeforeCameraData转化为AfterCameraData
	//为了方便管理将数据地址转化为智能指针

	std::shared_ptr<AfterCameraData> afdata;
	pThis->m_proCamera_->PushDataInQueue(afdata);
	return 0;
}

void t_SaveCameraImage(void* para, std::shared_ptr<AfterCameraData> data)
{
	//do what you want
}

int WINAPI s_ProcessLineData(void* _system, void* _context, std::shared_ptr<AfterCameraData> data)
{
	Cameras* pThis = (Cameras*)_system;

	//多线程的方式处理数据,当然也可以用单线程
	pThis->m_ThreadPool_->enqueue(t_SaveCameraImage, pThis, data);
	return 0;
}

Cameras::Cameras()
{
	//获取系统的"核数",初始化线程池//
	unsigned long hardwares = std::thread::hardware_concurrency();
	m_ThreadPool_ = std::make_shared<SThreadPool>(hardwares);

	//用this指针和回调函数初始化模板类//
	m_proCamera_ = std::make_shared<proSensor<AfterCameraData>>(this, s_ProcessLineData);
}

欢迎留言探讨,有疑问也可加我微信进行交流。

WOODS

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值