C++11 MessageBus--消息队列实现

Any.h:

#pragma once
#include <memory>
#include <typeindex>
/*
	类似于boost Any类的实现
*/
using namespace std;
struct Any {
public:
	Any(void) :m_tpIndex(type_index(typeid(void))) {}
	Any(Any& that) :m_ptr(that.Clone()), m_tpIndex(that.m_tpIndex) {}
	Any(Any&& that) :m_ptr(move(that.m_ptr)), m_tpIndex(that.m_tpIndex) {}
	// 创建智能指针时,对于一般的类型,通过decay来移除引用和CV符,从而获取原始类型
	template<typename U, class = typename enable_if<!is_same<typename decay<U>::type, Any>::value, U>::type>
	Any(U &&value) : m_ptr(new Derived<typename decay<U>::type>(forward<U>(value))), m_tpIndex(type_index(typeid(typename decay<U>::type))) {}

	bool IsNull() const { return !bool(m_ptr); }
	template<class U>bool Is() const {
		return m_tpIndex == type_index(typeid(U));
	}

	// 将Any转换成实际的类型
	template<class U>
	U& AnyCast()
	{
		if (!Is<U>())
		{
			cout << "can not cast " << typeid(U).name() << " to " << m_tpIndex.name() << endl;
			throw bad_cast();
		}
		auto derived = dynamic_cast<Derived<U>*> (m_ptr.get());
		return derived->m_value;
	}

	Any operator=(const Any& a)
	{
		if (m_ptr == a.m_ptr)
			return *this;
		m_ptr = a.Clone();
		m_tpIndex = a.m_tpIndex;
		return *this;
	}
private:
	struct Base;
	typedef unique_ptr<Base> BasePtr;
	struct Base
	{
		virtual ~Base() {}
		virtual BasePtr Clone() const = 0;
	};

	template<typename T>
	struct Derived :Base
	{
		template<typename U>
		Derived(U&& value) :m_value(forward<U>(value)) {}
		BasePtr Clone() const {
			return BasePtr(new Derived<T>(m_value));
		}
		T m_value;
	};

	BasePtr Clone() const
	{
		if (m_ptr != nullptr)
		{
			return m_ptr->Clone();
		}
		return nullptr;
	}

	BasePtr m_ptr;
	type_index m_tpIndex;
};

function_traits.h:

#pragma once
#include <functional>
#include <tuple>
#include <iostream>
using namespace std;

template <typename T>
struct function_traits;

template<typename Ret,typename...Args>
struct function_traits<Ret(Args...)>
{
public:
	enum{arity=sizeof...(Args) };
	typedef Ret function_type(Args...);
	typedef Ret return_type;
	using stl_function_type = function<function_type>;
	typedef Ret(*pointer)(Args...);

	template<size_t I>
	struct args
	{
		static_assert(I < arity, "index is out of range,index must less than sizeof Args");
		using type = typename tuple_element<I, tuple<Args...>>::type;
	};
};


//函数指针
template<typename Ret,typename...Args>
struct function_traits<Ret(*)(Args...)>:function_traits<Ret(Args...)>{};
// std::function
template <typename Ret,typename... Args>
struct function_traits<function<Ret(Args...)>>:function_traits<Ret(Args...)>{};

//member function
#define FUNCTION_TRAITS(...) \
	template<typename ReturnType,typename ClassType,typename...Args>\
	struct function_traits<ReturnType(ClassType::*)(Args...) __VA_ARGS__>:\
	function_traits<ReturnType(Args...)>{};

FUNCTION_TRAITS()
FUNCTION_TRAITS(const)
FUNCTION_TRAITS(volatile)
FUNCTION_TRAITS(const volatile)

//函数对象
template<typename Callable>
struct function_traits:function_traits<decltype(&Callable::operator())>{};

template<typename Function>
typename function_traits<Function>::stl_function_type to_function(const Function& lambda)
{
	return  static_cast<typename function_traits<Function>::stl_function_type > (lambda);
}

template<typename Function>
typename function_traits<Function>::stl_function_type to_function(Function&& lambda)
{
	return static_cast<typename function_traits<Function>::stl_function_type>(forward<Function>(lambda));
}

template<typename Function>
typename function_traits<Function>::pointer to_function_pointer(const Function& lambda)
{
	return static_cast<typename function_traits<Function>::pointer>(lambda);
}

NonCopyable.h:

#pragma once

class NonCopyable
{
protected:
	NonCopyable() = default;
	~NonCopyable() = default;
	// 禁用复制构造
	NonCopyable(const NonCopyable&) = delete;
	// 禁用赋值构造
	NonCopyable& operator = (const NonCopyable&) = delete;
};

MessageBus.h:

#pragma once
#include <string>
#include <functional>
#include <map>
#include "Any.h"
#include "function_traits.h"
#include "NonCopyable.h"

using namespace std;

class MessageBus :NonCopyable
{
public:
	//注册消息
	template<typename F>
	void Attach(F&& f, const string& strTopic = "")
	{
		auto func = to_function(forward<F>(f));
		Add(strTopic, move(func));
	}

	// 发送消息
	template<typename R>
	void SendReq(const string& strTopic = "")
	{
		using function_type = function<R()>;
		string strMsgType = strTopic + typeid(function_type).name();
		auto range = m_map.equal_range(strMsgType);
		for (Iterater it = range.first;it!= range.second;++it)
		{
			auto f = it->second.AnyCast<function_type>();
			f();
		}
	}

	template<typename R,typename... Args>
	void SendReq(Args&&...args, const string& strTopic = "")
	{
		using function_type = function<R(Args...)>;
		string strMsgType = strTopic + typeid(function_type).name();
		auto range = m_map.equal_range(strMsgType);
		for (Iterater it = range.first; it != range.second;++it)
		{
			auto f = it->second.AnyCast<function_type>();
			f(forward<Args>(args)...);
		}
	}

	//移除某个主题,需要主题和消息类型
	template<typename R,typename...Args>
	void Remove(const string& strTopic = "")
	{
		using function_type = function<R(Args...)>;//typename function_traits<void(Args)>::stl_function_type;

		string strMsgType = strTopic + typeid(function_type).name();
		int count = m_map.count(strMsgType);
		auto range = m_map.equal_range(strMsgType);
		m_map.erase(range.first, range.second);
	}
private:
	template<typename F>
	void Add(const string& strTopic, F&& f)
	{
		string strMsgType = strTopic + typeid(F).name();
		m_map.emplace(move(strMsgType), forward<F>(f));
	}
private:
	multimap<string, Any> m_map;
	typedef multimap<string, Any>::iterator Iterater;
};

测试代码:

// MessageBus.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include "MesssageBus.h"

using namespace std;
int main()
{
	MessageBus bus;
	// 注册消息
	bus.Attach([](int a) {cout << "no reference" << a << endl; });
	bus.Attach([](int& a) {cout << "lvalue reference" << a << endl; });
	bus.Attach([](int&& a) {cout << "rvalue reference" << a << endl; });
	bus.Attach([](const int& a) {cout << "const lvalue reference" << a << endl; });
	bus.Attach([](int a) {cout << "no reference has return value and key" << a << endl; return a; },"a");

	int i = 2;
	// 发送消息
	bus.SendReq<void,int>(2);
	bus.SendReq<int, int>(2,"a");
	bus.SendReq<void, int&>(i);
	bus.SendReq<void, const int&>(2);
	bus.SendReq<void, int&&>(2);
	// 移除消息
	bus.Remove<void,int>();
	bus.Remove<int, int>("a");
	bus.Remove<void, int&>();
	bus.Remove<void,const int&>();
	bus.Remove<void, int&&>();
	// 发送消息
	bus.SendReq<void, int>(2);
	bus.SendReq<int, int>(2, "a");
	bus.SendReq<void, int&>(i);
	bus.SendReq<void, const int&>(2);
	bus.SendReq<void, int&&>(2);
}


测试结果:

猜你喜欢

转载自blog.csdn.net/zang141588761/article/details/85993202