C++ 一个生产者 两个消费者 实现

extract_data.h

#pragma once
#ifndef  _EXTRACT_DATA_H_
#define  _EXTRACT_DATA_H_
#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>


namespace TIEVD {

	//struct 

	class Extract_Data {
	
	public:
		Extract_Data() {
			//mutex_queue = std::mutex();
		}
		void start();
		void stop();
		void set_call_back(void * call_back_func);
		bool add_data2queue(cv::Mat face);

	private:
		//std::mutex mutex_queue;
		const int max_queue_size = 5;
		
		
	};


}



#endif // ! _EXTRACT_DATA_H_

extract_data.cpp   子线程提取数据,处理数据, 等待数据

#include "extract_data.h"

#include <thread>
#include <mutex>

#include <Windows.h>

namespace TIEVD {

	//void(*func_pointer)(std::vector<float> arg1);

	bool _start = false;
	std::mutex mutex_queue;
	std::vector<cv::Mat> queue_datas;

	std::condition_variable syn;

	typedef void(*fun_point)(std::vector<float> arg1);
	void * call_back_func;


	bool get_data_from_queue(std::vector<cv::Mat> &queue_datas, cv::Mat &face) {
		std::lock_guard<std::mutex> lk(mutex_queue);
		if (queue_datas.size() > 0) {
			face = queue_datas[0];
			queue_datas.erase(queue_datas.begin());
			return true;
		}
		else {
			return false;
		}
	}

	void extract_gpu() {
		while (_start) {
			cv::Mat face;
			if (get_data_from_queue(queue_datas, face)) {
				fun_point f = (fun_point)call_back_func;
				std::vector<float> feature = {face.at<float>(0,0), face.at<float>(0,1)};
				f(feature);
				Sleep(20);
			}
			else {
				std::unique_lock<std::mutex> lk(mutex_queue);
				std::cout << "wait gpu." << std::endl;
				syn.wait(lk);
			}
	
		}
		
	}

	void extract_cpu() {
		while (_start) {
			cv::Mat face;
			if (get_data_from_queue(queue_datas, face)) {
				fun_point f = (fun_point)call_back_func;
				std::vector<float> feature = { face.at<float>(0,0), face.at<float>(0,1) };
				f(feature);
				Sleep(10);
			}
			else {
				std::unique_lock<std::mutex> lk(mutex_queue);
				std::cout << "wait cpu." << std::endl;
				syn.wait(lk);
			}
		}
	}


	void Extract_Data::start() {
		_start = true;
		std::thread ex_cpu(extract_cpu);
		std::thread ex_gpu(extract_gpu);


		ex_cpu.detach();
		ex_gpu.detach();

	}

	void Extract_Data::stop() {
		_start = false;
	}

	void Extract_Data::set_call_back(void * call_back) {
		call_back_func = call_back;
	}

	bool Extract_Data::add_data2queue(cv::Mat face) {
		std::lock_guard<std::mutex> lk(mutex_queue);
		if (queue_datas.size() < max_queue_size) {
			queue_datas.push_back(face);
		}
		else {
			queue_datas.erase(queue_datas.begin());
			queue_datas.push_back(face);
		}
        lk.unlock();
		syn.notify_all();
		return true;
	}

}


//class Extract_Data {
//private:
//	std::vector<cv::Mat> datas;
//public:
//	void start();
//	void stop();
//	void set_call_back(void *);
//	bool add_data2queue(cv::Mat face);
//};

main.cpp   主线程负责生产 数据,然后 notify 子线程 取数据。

#include <iostream>
#include <vector>
#include <string>
#include <windows.h>
#include <opencv2/opencv.hpp>

using namespace std;

void call_back(std::vector<float> feature) {

	std::cout << "feature is:"<< feature[0] << std::endl;

}

#include "extract_data.h"
using namespace TIEVD;
int main() {

	Extract_Data ex_data;
	ex_data.set_call_back((void *)call_back);
	

	ex_data.start();

	for (int i = 0; i < 10; i++) {
		cv::Mat face(2,2, CV_32FC1);
		face.at<float>(0, 0) = (float)i;
		face.at<float>(0, 1) = (float)i;
		face.at<float>(1, 0) = (float)i;
		face.at<float>(1, 1) = (float)i;
		ex_data.add_data2queue(face);
		Sleep(10);
	}

	Sleep(5000);


	ex_data.stop();


	system("pause");
	return 0;

}

 

 

原子变量

C++11提供了一个原子类型std::atomic<T>,可以使用任意类型作为模板参数,C++11内置了整型的原子变量,可以更方便地使用原子变量,使用原子变量就不需要使用互斥量来保护该变量了,因为对该变量的操作保证其是原子的,是不可中断的。用起来更简洁。 
要做一个计时器,使用mutex时,代码如下:
 

#include<iostream>
#include<mutex>
using namespace std;



struct Counter
{
    public:
    int value;
    std::mutex m_mutex;

    void increment()
    {
        std::lock_guard<std::mutex> lock(mutex);
        value++;
    }

    void decrement()
    {
        std::lock_guard<std::mutex> lock(mutex);
        value--;
    }

    int get()
    {
        return value;
    }
};

如果使用原子变量,就不需要再定义互斥量了,使用更简便。

#include<iostream>
#include<mutex>
using namespace std;



struct Counter
{
    public:

    std::atomic<int> value;

    void increment()
    {
        value++;
    }

    void decrement()
    {
        value--;
    }

    int get()
    {
        return value;
    }
};

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NineDays66

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值