C++生产消费平衡问题

一、背景

通过USB3.0获取数据,速度可达30帧,获取数据后解析处理,将处理后的数据保存在磁盘中,如果保存操作放置于生产所在线程,则会影响数据的获取,进而导致帧率变慢,所以要保证生产消费平衡,即消费的操作在另外的线程执行,且不能够导致生产阻塞。

二、验证

数据保存在磁盘所需的时间,记录每一帧写入的时间以及1000帧所需时间,不同的磁盘数据如下:

处理后的数据需要经过压缩,压缩耗时90多ms,如果要确保帧率,则需要消费线程能够及时消费完成,不能阻塞到生产线程。

三、方案

思路:启用三种线程来实现,线程1:产生数据,并将数据拷贝后启动线程2;线程2为工作线程(压缩工作);线程3:负责通过文件映射写入压缩后的数据;

具体实现如下:

1.使用定时器模拟获取数据,在定时器中断函数中拷贝数据,同时启动压缩工作线程,压缩工作线程放置于线程池中;

2.压缩工作线程获得帧序和数据,以及数据大小,压缩后将压缩后的数据,大小和帧序组合插入到保存线程的Map中。

3.保存线程按帧序查找Map中已经压缩好的帧后数据进行保存,保存后从Map中移除。

关键代码如下:

线程1:

	qint64 size = m_pointCountPerLine * m_lineCountPerFrame;

	int *InputBuffer = new int[size];
	memcpy(InputBuffer, m_pInputBuffer, m_frameSizeByte);
	ZlibWorker *worker = new ZlibWorker(m_frameIndex, m_frameSizeByte, InputBuffer,&m_frameBufferMap);
	QObject::connect(worker, &ZlibWorker::finished,
		this, &FileMapWrite::SlotZlibFinished, Qt::QueuedConnection);

	m_frameIndex++;
	QThreadPool::globalInstance()->start(worker);
	ui.m_frameCountLbl->setText(QString::number(m_frameIndex));

线程2:

void ZlibWorker::run()
{
	if (m_pFrameDataBuffer == NULL)
	{
		return;
	}
	unsigned long afterCompresssize = compressBound(m_frameByteSize);
	unsigned char *desbuf = new unsigned char[afterCompresssize];
	
	unsigned long deslenth = afterCompresssize;
	unsigned char* sourceBuf = (unsigned char*)m_pFrameDataBuffer;


	int rlt = compress2(desbuf, &deslenth, sourceBuf, m_frameByteSize, m_compressLevel);

	if (Z_OK ==rlt)
	{
		tCompressFrame *frameInfo = new tCompressFrame;
		frameInfo->ready = true;
		frameInfo->buffer = desbuf;
		frameInfo->byteSize = deslenth;
		frameInfo->frameIndex = m_frameIndex;
		m_mutex.lock();
		m_pFrameBufferMap->insert(m_frameIndex, frameInfo);
		m_mutex.unlock();
	}
	else {
		
		m_pFrameBufferMap->insert(m_frameIndex, NULL);
	}
	if (m_notify == false)
	{
		m_notify = true;
		emit finished(m_frameIndex, NULL);
	}
	delete[]m_pFrameDataBuffer;
	m_pFrameDataBuffer = NULL;
}

线程3:

	do
	{
		m_mutex.lock();
		auto itor = m_frameBufferMap.find(m_curSaveFrameIndex);
		m_mutex.unlock();

		if (itor != m_frameBufferMap.end())
		{
			
			tCompressFrame *frameInfo = itor.value();
			if (frameInfo)
			{
				m_fileSizeByte += frameInfo->byteSize + sizeof(int);

				DWORD hignSize = 0;
				DWORD lowValue = 0;
				unsigned long long  fileSizeByte = m_fileSizeByte;
				lowValue = fileSizeByte;
				hignSize = fileSizeByte >> 32;

				m_mapFile = CreateFileMapping(m_file, NULL, PAGE_READWRITE, hignSize, lowValue, LPCWCHAR("Resource"));
				m_openMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, true, LPCWCHAR("Resource"));
				m_mapFilePtr = static_cast<int*>(MapViewOfFile(m_openMap, FILE_MAP_ALL_ACCESS, 0, 0, 0));

				int*mapLength = m_mapFilePtr + 1;

				unsigned char *mapData = (unsigned char*)m_mapFilePtr + sizeof(int);
				memcpy(mapLength, &frameInfo->byteSize, sizeof(int));
				memcpy(mapData, frameInfo->buffer, frameInfo->byteSize);
				delete[]frameInfo->buffer;

				UnmapViewOfFile(m_mapFilePtr);
				CloseHandle(m_openMap);
				CloseHandle(m_mapFile);
				m_frameBufferMap.erase(itor);
			}
		
			m_curSaveFrameIndex++;			
			emit finished(m_curSaveFrameIndex);
			
		}
		else {
			Sleep(10);
		}


	}while ((!m_stopRecord)||(m_curSaveFrameIndex < m_frameIndex));
	CloseMapResource();

注意:线程3启动的时间要在线程2处理一帧后才开始启动;

           线程2中的插入Map操作需要加锁,不然会导致Map中Find不到情况,

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值