前言:异步执行经常要用到2个函数,一个函数处理UI线程的调用,另外一个函数处理内核线程调用。并且中间要用很多命令来转接不同的函数。这样函数的代码量和处理要麻烦很多。可以用模板函数做一下转接。
模板函数如下:(用到的函数打包知:std::bind与std::function详解)
#pragma once
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <functional>
#include <vector>
#include <mutex>
class CPerformFunction
{
public:
class CQueueCmd {
public:
CQueueCmd(void* cmd, bool sync)
{
_data = cmd;
m_isSync = sync;
_isFinish = false;
m_isDel = false;
}
~CQueueCmd()
{}
void wait()
{
if (!m_isSync)
return;
std::unique_lock<std::mutex> lock(_mutex);
if (!_isFinish)
_cond.wait(lock);
lock.unlock();
}
void notify()
{
if (!m_isSync)
return;
std::unique_lock<std::mutex> lock(_mutex);
_isFinish = true;
_cond.notify_one();
lock.unlock();
}
void* getCmd()
{
return _data;
}
public:
bool m_isSync;
bool m_isDel;
private:
void* _data;
std::mutex _mutex;
std::condition_variable _cond;
bool _isFinish; //命令執行完成
};
public:
CPerformFunction() {}
virtual ~CPerformFunction()
{
std::unique_lock<std::mutex> lock(m_mtxCmd);
auto iterCmd = m_vecCmd.begin();
for (; iterCmd != m_vecCmd.end(); iterCmd++)
{
std::function<void()> *f = (std::function<void()>*)(*iterCmd)->getCmd();
if (f)
{
//释放这里不需要执行函数
delete f;
f = NULL;
}
(*iterCmd)->notify();
if (!(*iterCmd)->m_isSync)
{
m_vecDelCmd.push_back((*iterCmd));
}
}
m_vecCmd.clear();
auto iterDelCmd = m_vecDelCmd.begin();
while (iterDelCmd != m_vecDelCmd.end())
{
while (!(*iterDelCmd)->m_isDel)
{
Sleep(1);
}
delete (*iterDelCmd);
m_vecDelCmd.erase(iterDelCmd);
}
}
template<class Object, class T, class... Args>
T performStdObjectFuncWithReturn(Object* object, T(__stdcall Object::*method)(Args...), Args... args)
{
return performClosureWithReturn<T>(std::bind(method, object, args...));
}
template<class Object, class T, class... Args>
T performObjectFuncWithReturn(Object* object, T (Object::*method)(Args...), Args... args)
{
return performClosureWithReturn<T>(std::bind(method, object, args...));
}
template<class T>
T performClosureWithReturn(std::function<T()> closure)
{
T* return_value = new T;
std::function<void()> func = std::bind(&CPerformFunction::wrap<T>, this, closure, return_value);
exec(func);
T value = *(T*)return_value;
delete return_value;
return value;
}
template<class T, class... Args>
T performStdFuncWithReturn(T(__stdcall *method)(Args...), Args... args)
{
return performClosureWithReturn<T>(std::bind(method, args...));
}
template<class T, class... Args>
T performFuncWithReturn(T(*method)(Args...), Args... args)
{
return performClosureWithReturn<T>(std::bind(method, args...));
}
template<class Object, class... Args>
void performStdObjectFuncWithoutReturn(Object* object, void(__stdcall Object::*method)(Args...), Args... args)
{
std::function<void()> func = std::bind(method, object, args...);
exec(func);
}
template<class Object, class... Args>
void performObjectFuncWithoutReturn(Object* object, void(Object::*method)(Args...), Args... args)
{
std::function<void()> func = std::bind(method, object, args...);
exec(func);
}
template<class... Args>
void performStdFuncWithoutReturn(void(__stdcall *method)(Args...), Args... args)
{
std::function<void()> func = std::bind(method, args...);
exec(func);
}
template<class... Args>
void performFuncWithoutReturn(void(*method)(Args...), Args... args)
{
std::function<void()> func = std::bind(method, args...);
exec(func);
}
template<class Object, class T, class... Args>
void asyncPerformStdObjectFunc(Object* object, T(_stdcall Object::*method)(Args...), Args... args)
{
std::function<void()> func = std::bind(method, object, args...);
exec(func, false);
}
template<class Object, class T, class... Args>
void asyncPerformObjectFunc(Object* object, T(Object::*method)(Args...), Args... args)
{
std::function<void()> func = std::bind(method, object, args...);
exec(func, false);
}
template<class T, class... Args>
void asyncPerformStdFunc(T(__stdcall *method)(Args...), Args... args)
{
std::function<void()> func = std::bind(method, args...);
exec(func, false);
}
template<class T, class... Args>
void asyncPerformFunc(T(*method)(Args...), Args... args)
{
std::function<void()> func = std::bind(method, args...);
exec(func, false);
}
virtual bool EndPerformCmd()
{
return false;
}
virtual void processCmd()
{
std::unique_lock<std::mutex> lock(m_mtxCmd);
auto iterDelCmd = m_vecDelCmd.begin();
while(iterDelCmd != m_vecDelCmd.end())
{
if ((*iterDelCmd)->m_isDel)
{
delete (*iterDelCmd);
m_vecDelCmd.erase(iterDelCmd);
}
else
{
iterDelCmd++;
}
}
auto iterCmd = m_vecCmd.begin();
while(iterCmd != m_vecCmd.end())
{
std::function<void()> *f = (std::function<void()>*)(*iterCmd)->getCmd();
if (f)
{
(*f)();
delete f;
f = NULL;
}
if (!(*iterCmd)->m_isSync)
{
m_vecDelCmd.push_back((*iterCmd));
}
(*iterCmd)->notify();
iterCmd=m_vecCmd.erase(iterCmd);
if (EndPerformCmd())
{
return;
}
}
}
protected:
virtual void exec(std::function<void()> func,bool isSync=true)
{
std::function<void()> *f = new std::function<void()>(func);
CQueueCmd *pCmd = new CQueueCmd(f, isSync);
do
{
std::unique_lock<std::mutex> lock(m_mtxCmd);
m_vecCmd.push_back(pCmd);
} while (0);
pCmd->wait();
if (isSync)
{
delete pCmd;
}
else
{
pCmd->m_isDel = true;
}
}
private:
template<class T>
void wrap(std::function<T()> f, T* value)
{
*value = f();
}
private:
std::vector<CQueueCmd*> m_vecCmd; //函数调用命令参数
std::vector<CQueueCmd*> m_vecDelCmd; //删除命令队列
std::mutex m_mtxCmd; //互斥量
};