异步执行如何在一个函数中实现

前言:异步执行经常要用到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;		//互斥量
};

猜你喜欢

转载自blog.csdn.net/xiaoyafang123/article/details/80539927