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;
}
};