C++ 模仿Android实现Handler机制

前言:

        一直使用android的Handler,感觉非常好用,但是当我使用C++编程时,想使用Android Handler一样的编程模式,竟不知如何下手,网上找了很久,都没找到具体的实现,能搜索到MFC中使用handler,但是一直不搞windows的开发,也不晓得上哪儿去弄,也可能是我找的不够多吧。这个Handler已经严重的影响了我,没有它左右不舒服。这两天沉下心来自己写了一个,省的自己去找了,以后肯定还能用到,最好有网友也做了类似实现,我可以借鉴下以提升自己。

代码参考Android Handler,有兴趣的朋友可以去看看Android 里面的实现。

Handler.h

#pragma once
#ifndef HANDLER_H
#define HANDLER_H

#include 
#include 
#include 
#include 
#include 


#include "Message.h"

/*
 * Handler will run in it's own thread, you don't want to care about it.
 * Message will be proccess by the Handler. Two ways to add your task to the Handler.
 * 1. send message to the handler
 * 2. post the task(Function) to handler
 */

class Handler{
public:
	Handler();
	virtual ~Handler();

	bool sendMessageAtTime(Message& msg, long uptimeMillis);
	bool sendMessage(Message& msg);
	bool sendEmptyMessage(int what);
	bool sendEmptyMessage(int what, long uptimeMillis);

	bool post(Message::Function f);
	bool postAtTime(Message::Function f, long uptimeMillis);

	void removeMessages(int what);
	void removeCallbackAndMessages();

	void stopSafty(bool stopSafty);

	bool isQuiting();

	virtual void handleMessage(Message& msg);

	void dispatchMessage(Message& msg);

	/*
	 * for msgQueue sorted when insert,
	 * ascending order
	 */
	template
	class ValComp {
	public:
		bool operator()(const T& t1,const T& t2) const {
			return (t1 < t2);
		}

	};

private:
	std::vector msg_Q;

	std::mutex queue_mutex;
	std::condition_variable condition;
	std::thread looper;
	bool stop;
	bool stopWhenEmpty;
};

#endif

Handler.cpp

#include 
#include 
#include 
#include "Handler.h"
#include "Message.h"
#define LOGENTER (std::cout << "This is FUNCTION " << __func__<<  std::endl)
Handler::Handler():stop(false),stopWhenEmpty(false){
	looper = std::thread(
		[this](){
			for(;;)
			{
				Message msg;
				{
					std::unique_lock lock(this->queue_mutex);
					if(this->msg_Q.empty()){
						this->condition.wait(lock, [this]{ return this->stop || this->stopWhenEmpty || !this->msg_Q.empty();});
					}else{
						this->condition.wait_until(lock, this->msg_Q.back().when, [this]{ return this->stop || this->stopWhenEmpty || !this->msg_Q.empty(); });
					}

					if(this->stopWhenEmpty && this->msg_Q.empty())
						return;
					if(stop){
						msg_Q.clear();
						return;
					}

					msg = std::move(msg_Q.back());
					msg_Q.pop_back();
				}
				this->dispatchMessage(msg);
			}
		});
}
Handler::~Handler(){
	{
		std::unique_lock lock(queue_mutex);
		stop = true;
	}
	condition.notify_all();
	looper.join();
	msg_Q.clear();

}

void Handler::handleMessage(Message& msg){
	std::cout << "IN Handler " << __func__<< " what:" << msg.m_what <<  std::endl;
}

bool Handler::sendMessageAtTime(Message& msg, long uptimeMillis){
	if(uptimeMillis < 0 )
		return false;

	msg.setWhen(uptimeMillis);

	std::unique_lock lock(queue_mutex);
	auto i = std::find(msg_Q.begin(),msg_Q.end(),msg);
	msg_Q.erase(i);

	msg_Q.push_back(msg);
	std::sort(msg_Q.begin(), msg_Q.end(),std::greater());
	condition.notify_one();
	return true;
}
bool Handler::sendMessage(Message& msg){
	return false;

	std::unique_lock lock(queue_mutex);
	auto i = find(msg_Q.begin(),msg_Q.end(),msg);
	if(i != msg_Q.end())
		msg_Q.erase(i);

	msg_Q.push_back(msg);
	std::sort(msg_Q.begin(), msg_Q.end(),std::greater());
	condition.notify_one();
	return true;
}

bool Handler::sendEmptyMessage(int what){
	return sendEmptyMessage(what ,0);
}

bool Handler::sendEmptyMessage(int what,long uptimeMillis){

	if(what < 0 || uptimeMillis < 0)
		return false;

	Message msg(what);
	msg.setWhen(uptimeMillis);

	std::unique_lock lock(queue_mutex);

	std::vector::iterator i = find(msg_Q.begin(),msg_Q.end(),msg);
	if (i != msg_Q.end()){
		msg_Q.erase(i);
	}

	msg_Q.push_back(msg);
//	std::sort(msg_Q.begin(), msg_Q.end(),ValComp());
	// 跟进时间进行降序排列
	std::sort(msg_Q.begin(), msg_Q.end(),std::greater());

	condition.notify_one();
	return true;
}

bool Handler::post(Message::Function f){
	return postAtTime(f,0);
}
bool Handler::postAtTime(Message::Function f, long uptimeMillis){

	if(f == nullptr || uptimeMillis < 0){
		return false;
	}

	std::unique_lock lock(queue_mutex);
	Message msg;
	msg.setWhen(uptimeMillis);
	msg.setFunction(f);
	msg_Q.push_back(msg);
	std::sort(msg_Q.begin(), msg_Q.end(),std::greater());

	return true;
}

void Handler::removeMessages(int what){
	if(what < 0)
		return;

	std::unique_lock lock(queue_mutex);

	auto i = find(msg_Q.begin(),msg_Q.end(),what);
	if (i != msg_Q.end()){
		msg_Q.erase(i);
	}

	condition.notify_one();
}

void Handler::removeCallbackAndMessages(){
	std::unique_lock lock(queue_mutex);
	msg_Q.clear();
}

void Handler::stopSafty(bool stopSafty){
	std::unique_lock lock(queue_mutex);
	if(stopSafty){
		stopWhenEmpty = true;
	}else{
		stop = true;
	}
}


bool Handler::isQuiting(){
	std::unique_lock lock(queue_mutex);
	if(stop || stopWhenEmpty)
		return true;
	return false;
}

void Handler::dispatchMessage(Message& msg){
	if(msg.task != nullptr){
		msg.task();
	}else{
		if(msg.m_what < 0)
			return;
		handleMessage(msg);
	}
}


使用:

class myHandler : public Handler{
	virtual void handleMessage(Message& msg) override {
		Handler::handleMessage(msg);
		switch(msg.m_what){
		case 0:

			break;

		case 1:
			break;

		case 2:
			break;

		case 3:
			break;

		case 4:
			break;

		case 5:
			break;

		default:
			break;
		}

		cout << "IN myHandler case: " << msg.m_what << endl;
	}
};
int main(int argc, char **argv)
{
	cout << "IN main" << endl;

	myHandler hdlr;
	for(int i = 0; i < 6; i++){
		hdlr.sendEmptyMessage(i, 100 * i);
	}

	hdlr.postAtTime([](){
		cout << "IN POST call back" << endl;
	}, 230);

	hdlr.stopSafty(true); //停止handler,在停止前处理完所有消息
	while(true){
		std::this_thread::sleep_for(std::chrono::seconds(100000));
	}
	return 1;
}

这里只帖出Handler的实现,还有个配套的Message实现,感兴趣的童鞋自己去下面链接查看吧。


代码链接:https://github.com/feekia/EventServer


另,转载请注明出处:https://mp.csdn.net/postedit/80656503


你可能感兴趣的:(C++)