C++软件开发架构

发布于:2025-04-03 ⋅ 阅读:(17) ⋅ 点赞:(0)

文章目录

      • 1.全局消息通信
        • MsgHandler.h
        • 单元测试(QTest)
          • MsgHandlerUnitTest.h
          • MsgHandlerUnitTest.cpp
      • 2.实例间通信
        • InstMsgHandler.h
        • 单元测试
          • InstMsgHandlerUnitTest.h
          • InstMsgHandlerUnitTest.cpp

1.全局消息通信

1. 适用于类与类单个对象实例之间的通信,多个对象需要酌情使用
2. 支持优先级触发
3. 支持附带参数
4. 支持异步执行
5. 使用方式可以查看下方单元测试代码
MsgHandler.h
#pragma once

#include <functional>
#include <unordered_map>
#include <map>
#include <string>
#include "any.h"

class MsgHandler {
#ifdef _DEBUG
	using MsgType = std::string;
#else
	using MsgType = const char*;
#endif
	friend class MsgHandlerUnitTest;
public:
	static MsgHandler* GetInstance() {
		static MsgHandler i;
		return &i;
	}
	void SetAsyncExecFunc(std::function<void(std::function<void()>)> func) { asyncExecFunc_ = func; }
	void SetMainExecFunc(std::function<void(std::function<void()>)> func) { mainExecFunc_ = func; }

	void TriggerMsg_(MsgType msg, std::any info = std::any{}) {
		ExecMsgHandler(msg, defaultExecFunc_, info);
	}
	void AsyncExecMsg_(MsgType msg, std::any info = std::any{}) {
		if(!asyncExecFunc_) throw std::runtime_error("dont set async exec func");
		ExecMsgHandler(msg, asyncExecFunc_, info);
	}
	void MainExecMsg_(MsgType msg, std::any info = std::any{}) {
		if (!mainExecFunc_) throw std::runtime_error("dont set main exec func");
		ExecMsgHandler(msg, mainExecFunc_, info);
	}
	void RegisterMsgHandler_(MsgType msg, void* t, std::function<void(std::any)> func, int priority = 0) {
		globalMsgHandler_[msg][priority].insert({ t, func });
	}
	void RegisterMsgHandler_(MsgType msg, void* t, std::function<void()> func, int priority = 0) {
		globalMsgHandler_[msg][priority].insert({ t, [=](std::any) {func(); } });
	}
	void Deregister_(void* t) {
		for (auto& msgHandler : globalMsgHandler_) {
			PriorityMap& priorityMap = msgHandler.second;
			for (auto& priorityEntry : priorityMap) {
				HandlerMap& handlerMap = priorityEntry.second;
				handlerMap.erase(t);
			}
		}
	}
private:
	void ExecMsgHandler(MsgType msg, std::function<void(std::function<void()>)> func, std::any info = std::any{}) {
		auto it = globalMsgHandler_.find(msg);
		if (it != globalMsgHandler_.end()) {
			PriorityMap& priorityMap = it->second;
			for (auto& priorityEntry : priorityMap) {
				HandlerMap& handlerMap = priorityEntry.second;
				for (auto& handlerEntry : handlerMap) {
					std::function<void(std::any)>& handler = handlerEntry.second;
					func([&handler, info] {handler(info); });
				}
			}
		}
	}
private:
	MsgHandler() = default;
	using HandlerMap = std::unordered_map<void*, std::function<void(std::any)>>;
	using PriorityMap = std::map<int, HandlerMap, std::greater<int>>;
	std::function<void(std::function<void()>)> defaultExecFunc_ = [](std::function<void()> func) { func(); };
	std::function<void(std::function<void()>)> asyncExecFunc_;
	std::function<void(std::function<void()>)> mainExecFunc_;
	std::unordered_map<MsgType, PriorityMap> globalMsgHandler_;
};

#define RegisterMsgHandler(msg, ...) MsgHandler::GetInstance()->RegisterMsgHandler_(#msg, this, __VA_ARGS__)
#define TriggerMsg(msg, ...) MsgHandler::GetInstance()->TriggerMsg_(#msg, __VA_ARGS__)
#define AsyncExecMsg(msg, ...)  MsgHandler::GetInstance()->AsyncExecMsg_(#msg, __VA_ARGS__)
#define MainExecMsg(msg, ...)  MsgHandler::GetInstance()->MainExecMsg_(#msg, __VA_ARGS__)
#define Deregister() MsgHandler::GetInstance()->Deregister_(this)
单元测试(QTest)
MsgHandlerUnitTest.h
#include <QTest>
#include <vector>

class MsgHandlerUnitTest :public QObject {
	Q_OBJECT
private slots:
	void initTestCase();
	void cleanupTestCase();
	void init();
	void cleanup();
	void RegisterTest();
	void DeregisterTest();
	void PriorityPreTest();
	void PriorityTest();
	void TriggerNoParamTest();
	void TriggerHasParamTest();
	void AsyncTriggerTest();
	void MainTriggerTest();
	void MemoryLeakTest();
private:
	bool VarifyResult();
private:
	std::vector<bool> m_results;
};
MsgHandlerUnitTest.cpp
#include "MsgHandlerUnitTest.h"
#include "MsgHandler.h"
#include <QTimer>

class RunnableTask : public QRunnable {
public:
	RunnableTask(std::function<void()> func) : func_(func) {
		setAutoDelete(true);
	}
	void run() { func_(); }
private:
	std::function<void()> func_;
};

class AsyncThreadPool {
public:
	void AddTask(std::function<void()> func) {
		QThreadPool::globalInstance()->start(new RunnableTask(func));
	}
public:
	static AsyncThreadPool* GetInstance() {
		static AsyncThreadPool i;
		return &i;
	}
private:
	AsyncThreadPool() = default;
};
#define GAsyncThreadPool AsyncThreadPool::GetInstance()

int GetCurMemoryKB()
{
	SetProcessWorkingSetSize(GetCurrentProcess(), -1, -1);
	PROCESS_MEMORY_COUNTERS pmc;
	GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
	auto curMemoryKB = pmc.WorkingSetSize / 1024;
	return curMemoryKB;
}

enum Msg {
	A,
	B,
	C,
};

void MsgHandlerUnitTest::RegisterTest()
{
	struct ClassA {
		ClassA() {
			RegisterMsgHandler(Msg::A, [this] {});
			RegisterMsgHandler(Msg::B, [this](const std::any& data) {});
		}
		~ClassA() {
			Deregister();
		}
	};
	struct ClassB {
		ClassB() {
			RegisterMsgHandler(Msg::A, [this] {});
			RegisterMsgHandler(Msg::B, [this](const std::any& data) {});
		}
		~ClassB() {
			Deregister();
		}
	};

	ClassA a1;
	const auto& globalMsgHandler = MsgHandler::GetInstance()->globalMsgHandler_;
	m_results.push_back(globalMsgHandler.size() == 2);
	m_results.push_back(globalMsgHandler.at("Msg::A").size() == 1);
	m_results.push_back(globalMsgHandler.at("Msg::B").size() == 1);
	m_results.push_back(globalMsgHandler.at("Msg::A").at(0).size() == 1);
	m_results.push_back(globalMsgHandler.at("Msg::B").at(0).size() == 1);

	ClassA a2;
	m_results.push_back(globalMsgHandler.size() == 2);
	m_results.push_back(globalMsgHandler.at("Msg::A").size() == 1);
	m_results.push_back(globalMsgHandler.at("Msg::B").size() == 1);
	m_results.push_back(globalMsgHandler.at("Msg::A").at(0).size() == 2);
	m_results.push_back(globalMsgHandler.at("Msg::B").at(0).size() == 2);

	ClassB b1;
	m_results.push_back(globalMsgHandler.size() == 2);
	m_results.push_back(globalMsgHandler.at("Msg::A").size() == 1);
	m_results.push_back(globalMsgHandler.at("Msg::B").size() == 1);
	m_results.push_back(globalMsgHandler.at("Msg::A").at(0).size() == 3);
	m_results.push_back(globalMsgHandler.at("Msg::B").at(0).size() == 3);

	QVERIFY(VarifyResult());
}


void MsgHandlerUnitTest::DeregisterTest() {
	struct ClassA {
		ClassA() {
			RegisterMsgHandler(Msg::A, [this] {});
			RegisterMsgHandler(Msg::B, [this](const std::any& data) {});
		}
		~ClassA() {
			Deregister();
		}
	};
	const auto& globalMsgHandler = MsgHandler::GetInstance()->globalMsgHandler_;
	{
		ClassA a1;
		m_results.push_back(globalMsgHandler.size() == 2);
		m_results.push_back(globalMsgHandler.at("Msg::A").size() == 1);
		m_results.push_back(globalMsgHandler.at("Msg::B").size() == 1);
		m_results.push_back(globalMsgHandler.at("Msg::A").at(0).size() == 1);
		m_results.push_back(globalMsgHandler.at("Msg::B").at(0).size() == 1);
	}
	m_results.push_back(globalMsgHandler.size() == 2);
	m_results.push_back(globalMsgHandler.at("Msg::A").size() == 1);
	m_results.push_back(globalMsgHandler.at("Msg::B").size() == 1);
	m_results.push_back(globalMsgHandler.at("Msg::A").at(0).size() == 0);
	m_results.push_back(globalMsgHandler.at("Msg::B").at(0).size() == 0);
	QVERIFY(VarifyResult());
}

void MsgHandlerUnitTest::PriorityPreTest() {
	struct ClassA {
		ClassA() {
			RegisterMsgHandler(Msg::A, [this] {});
			RegisterMsgHandler(Msg::B, [this](const std::any& data) {});
		}
		~ClassA() {
			Deregister();
		}
	};
	struct ClassB {
		ClassB() {
			RegisterMsgHandler(Msg::A, [this] {}, 1);
			RegisterMsgHandler(Msg::B, [this](const std::any& data) {}, 1);
		}
		~ClassB() {
			Deregister();
		}
	};

	const auto& globalMsgHandler = MsgHandler::GetInstance()->globalMsgHandler_;
	ClassA a1;
	m_results.push_back(globalMsgHandler.size() == 2);
	m_results.push_back(globalMsgHandler.at("Msg::A").size() == 1);
	m_results.push_back(globalMsgHandler.at("Msg::B").size() == 1);
	m_results.push_back(globalMsgHandler.at("Msg::A").at(0).size() == 1);
	m_results.push_back(globalMsgHandler.at("Msg::B").at(0).size() == 1);

	ClassA a2;
	m_results.push_back(globalMsgHandler.size() == 2);
	m_results.push_back(globalMsgHandler.at("Msg::A").size() == 1);
	m_results.push_back(globalMsgHandler.at("Msg::B").size() == 1);
	m_results.push_back(globalMsgHandler.at("Msg::A").at(0).size() == 2);
	m_results.push_back(globalMsgHandler.at("Msg::B").at(0).size() == 2);

	ClassB b;
	m_results.push_back(globalMsgHandler.size() == 2);
	m_results.push_back(globalMsgHandler.at("Msg::A").size() == 2);
	m_results.push_back(globalMsgHandler.at("Msg::B").size() == 2);
	m_results.push_back(globalMsgHandler.at("Msg::A").at(0).size() == 2);
	m_results.push_back(globalMsgHandler.at("Msg::B").at(0).size() == 2);
	m_results.push_back(globalMsgHandler.at("Msg::A").at(1).size() == 1);
	m_results.push_back(globalMsgHandler.at("Msg::B").at(1).size() == 1);

	QVERIFY(VarifyResult());
}
std::vector<int> priorityTestvec;
void MsgHandlerUnitTest::PriorityTest()
{
	struct ClassA {
		ClassA() {
			RegisterMsgHandler(Msg::A, [this] {
				priorityTestvec.push_back(a);
			});
			RegisterMsgHandler(Msg::B, [this] {
				priorityTestvec.push_back(a);
			}, 1);
		}
		~ClassA() {
			Deregister();
		}
		int a = 5;
	};
	struct ClassB {
		ClassB() {
			RegisterMsgHandler(Msg::A, [this] {
				priorityTestvec.push_back(b);
			}, 1);
			RegisterMsgHandler(Msg::B, [this] {
				priorityTestvec.push_back(b);
			});
		}
		~ClassB() {
			Deregister();
		}
		int b = 10;
	};

	ClassA a;
	ClassB b;

	priorityTestvec.clear();
	TriggerMsg(Msg::A);
	m_results.push_back(priorityTestvec.size() == 2);
	m_results.push_back(priorityTestvec[0] == 10 && priorityTestvec[1] == 5);

	priorityTestvec.clear();
	TriggerMsg(Msg::B);
	m_results.push_back(priorityTestvec.size() == 2);
	m_results.push_back(priorityTestvec[0] == 5 && priorityTestvec[1] == 10);

	QVERIFY(VarifyResult());
}

void MsgHandlerUnitTest::TriggerNoParamTest()
{
	struct ClassA {
		ClassA() {
			RegisterMsgHandler(Msg::A, [this] {
				a = A;
			});
			RegisterMsgHandler(Msg::B, [this] {
				a = B;
			});
		}
		~ClassA() {
			Deregister();
		}
		int a = 0;
	};

	struct ClassB {
		ClassB() {
			RegisterMsgHandler(Msg::A, [this] {
				b = A;
			});
			RegisterMsgHandler(Msg::B, [this] {
				b = B;
			});
		}
		~ClassB() {
			Deregister();
		}
		int b = 0;
	};
	const auto& globalMsgHandler = MsgHandler::GetInstance()->globalMsgHandler_;
	ClassA a1;
	ClassB b1;
	m_results.push_back(a1.a == 0);
	m_results.push_back(b1.b == 0);

	TriggerMsg(Msg::A);
	m_results.push_back(a1.a == A);
	m_results.push_back(b1.b == A);

	TriggerMsg(Msg::B);
	m_results.push_back(a1.a == B);
	m_results.push_back(b1.b == B);

	QVERIFY(VarifyResult());
}

void MsgHandlerUnitTest::TriggerHasParamTest()
{
	struct ClassA {
		ClassA() {
			RegisterMsgHandler(Msg::C, [this](const std::any& data) {
				a = std::any_cast<int>(data);
			});
		}
		~ClassA() {
			Deregister();
		}
		int a = 0;
	};

	struct ClassB {
		ClassB() {
			RegisterMsgHandler(Msg::C, [this](const std::any& data) {
				b = std::any_cast<int>(data);
			});
		}
		~ClassB() {
			Deregister();
		}
		int b = 0;
	};

	const auto& globalMsgHandler = MsgHandler::GetInstance()->globalMsgHandler_;

	ClassA a1;
	ClassB b1;
	m_results.push_back(a1.a == 0);
	m_results.push_back(b1.b == 0);

	TriggerMsg(Msg::C, 5);
	m_results.push_back(a1.a == 5);
	m_results.push_back(b1.b == 5);

	TriggerMsg(Msg::C, 999);
	m_results.push_back(a1.a == 999);
	m_results.push_back(b1.b == 999);

	QVERIFY(VarifyResult());
}

std::vector<std::thread::id> AsyncTriggerTestVec;
void MsgHandlerUnitTest::AsyncTriggerTest()
{
	AsyncTriggerTestVec.push_back(std::this_thread::get_id());
	struct ClassA {
		ClassA() {
			RegisterMsgHandler(Msg::A, [this] {
				AsyncTriggerTestVec.push_back(std::this_thread::get_id());
			});
		}
		~ClassA() {
			Deregister();
		}
	};
	ClassA a;
	AsyncExecMsg(Msg::A);

	while (AsyncTriggerTestVec.size() != 2) {
		QCoreApplication::processEvents();
	}
	m_results.push_back(AsyncTriggerTestVec[0] != AsyncTriggerTestVec[1]);
	QVERIFY(VarifyResult());
}

std::vector<std::thread::id> MainTriggerTestVec;
void MsgHandlerUnitTest::MainTriggerTest()
{
	MainTriggerTestVec.clear();
	MainTriggerTestVec.push_back(std::this_thread::get_id());
	struct ClassA {
		ClassA() {
			RegisterMsgHandler(Msg::A, [this] {
				MainTriggerTestVec.push_back(std::this_thread::get_id());
				MainExecMsg(Msg::B);
			});
			RegisterMsgHandler(Msg::B, [this] {
				MainTriggerTestVec.push_back(std::this_thread::get_id());
			});
		}
		~ClassA() {
			Deregister();
		}
	};
	ClassA a;
	AsyncExecMsg(Msg::A);

	while (MainTriggerTestVec.size() != 3) {
		QCoreApplication::processEvents();
	}
	m_results.push_back(MainTriggerTestVec[0] != MainTriggerTestVec[1] 
		&& MainTriggerTestVec[1] != MainTriggerTestVec[2] 
		&& MainTriggerTestVec[0] == MainTriggerTestVec[2]);
	QVERIFY(VarifyResult());
}

void MsgHandlerUnitTest::MemoryLeakTest()
{
	struct ClassA {
		ClassA() {
			RegisterMsgHandler(Msg::A, [this] {
				a = A;
			});
			RegisterMsgHandler(Msg::B, [this] {
				a = B;
			});
			RegisterMsgHandler(Msg::C, [this](const std::any& data) {
				a = std::any_cast<int>(data);
			});
		}
		~ClassA() {
			Deregister();
		}
		int a = 0;
	};
	const auto& globalMsgHandler = MsgHandler::GetInstance()->globalMsgHandler_;
	auto beginMemory = GetCurMemoryKB();
	{
		std::vector<ClassA*> vec;
		for (int i = 0; i < 100000; ++i) {
			vec.push_back(new ClassA);
		}
		m_results.push_back(globalMsgHandler.size() == 3);
		m_results.push_back(globalMsgHandler.at("Msg::A").size() == 1);
		m_results.push_back(globalMsgHandler.at("Msg::B").size() == 1);
		m_results.push_back(globalMsgHandler.at("Msg::C").size() == 1);
		m_results.push_back(globalMsgHandler.at("Msg::A").at(0).size() == 100000);
		m_results.push_back(globalMsgHandler.at("Msg::B").at(0).size() == 100000);
		m_results.push_back(globalMsgHandler.at("Msg::C").at(0).size() == 100000);
		for (auto& v : vec) {
			delete v;
		}
		vec.clear();
		m_results.push_back(globalMsgHandler.size() == 3);
		m_results.push_back(globalMsgHandler.at("Msg::A").size() == 1);
		m_results.push_back(globalMsgHandler.at("Msg::B").size() == 1);
		m_results.push_back(globalMsgHandler.at("Msg::C").size() == 1);
		m_results.push_back(globalMsgHandler.at("Msg::A").at(0).size() == 0);
		m_results.push_back(globalMsgHandler.at("Msg::B").at(0).size() == 0);
		m_results.push_back(globalMsgHandler.at("Msg::C").at(0).size() == 0);
	}
	auto endMemory = GetCurMemoryKB();
	QVERIFY(endMemory - beginMemory < 30);
}

bool MsgHandlerUnitTest::VarifyResult()
{
	bool result = true;
	for (auto& rlt : m_results) {
		if (!rlt) {
			result = false;
			break;
		}
	}
	return result;
}

void MsgHandlerUnitTest::initTestCase()
{
	MsgHandler::GetInstance()->SetAsyncExecFunc([](std::function<void()> func) { GAsyncThreadPool->AddTask(func); });
	MsgHandler::GetInstance()->SetMainExecFunc([](std::function<void()> func) { QTimer::singleShot(0, qApp, func); });
}

void MsgHandlerUnitTest::cleanupTestCase()
{
}

void MsgHandlerUnitTest::init()
{
	m_results.clear();
	MsgHandler::GetInstance()->globalMsgHandler_.clear();
}

void MsgHandlerUnitTest::cleanup()
{
}

2.实例间通信

1. 适用于类与类相互关联的对象之间的通信
2. 不支持优先级触发
3. 支持附带参数
4. 不支持异步执行
5. 使用方式可以查看下方单元测试代码
InstMsgHandler.h
#pragma once

#include <unordered_map>
#include <functional>
#include <unordered_set>
#include "any.h"

class InstMsgHandler {
#ifdef _DEBUG
	using MsgType = std::string;
#else
	using MsgType = const char*;
#endif
	friend class InstMsgHandlerUnitTest;
public:
	static InstMsgHandler* GetInstance() {
		static InstMsgHandler i;
		return &i;
	}
	void XTriggerMsg_(MsgType msg, void* trigger, std::any info = std::any{}) {
		auto findHandler = globalMsgHandler_.find(msg);
		if (findHandler != globalMsgHandler_.end()) {
			auto& handlers = findHandler->second;
			auto it = communicators_.find(trigger);
			if (it != communicators_.end()) {
				for (const auto& communicator : it->second) {
					auto handler = handlers.find(communicator);
					if (handler != handlers.end()) {
						handler->second(info);
					}
				}
			}
		}
	}
	void XRegisterMsgHandler_(MsgType msg, void* t, std::function<void(std::any)> func) {
		globalMsgHandler_[msg].insert({ t, func });
	}
	void XRegisterMsgHandler_(MsgType msg, void* t, std::function<void()> func) {
		globalMsgHandler_[msg].insert({ t, [=](std::any) {func(); } });
	}
	void XConnect_(void* c1, void* c2) {
		if (c1 == c2) {
			communicators_[c1].insert(c2);
			return;
		}
		communicators_[c1].insert(c2);
		communicators_[c2].insert(c1);
	}
	void XDisconnect_(void* c1, void* c2) {
		if (c1 == c2) {
			communicators_[c1].erase(c2);
			return;
		}
		communicators_[c1].erase(c2);
		communicators_[c2].erase(c1);
	}
	void XDeregister_(void* t) {
		XDisconnect_(t);
		DeregisterMsgHandler(t);
	}
private:
	void XDisconnect_(void* t) {
		auto it = communicators_.find(t);
		if (it != communicators_.end()) {
			auto communicators = it->second;
			for (auto communicator : communicators) {
				communicators_[communicator].erase(t);
			}
		}
		communicators_.erase(t);
	}
	void DeregisterMsgHandler(void* t) {
		for (auto& msgHandler : globalMsgHandler_) {
			HandlerMap& handlerMap = msgHandler.second;
			handlerMap.erase(t);
		}
	}
private:
	InstMsgHandler() = default;
	using HandlerMap = std::unordered_map<void*, std::function<void(std::any)>>;
	std::unordered_map<void*, std::unordered_set<void*>> communicators_;
	std::unordered_map<MsgType, HandlerMap> globalMsgHandler_;
};

#define EXPAND(...) __VA_ARGS__
#define COUNT_ARGS_IMPL(_1, _2, _3, N, ...) N
#define COUNT_ARGS(...) EXPAND(COUNT_ARGS_IMPL(__VA_ARGS__, 3, 2, 1, 0))
#define XCONNECT_IMPL_1(a) InstMsgHandler::GetInstance()->XConnect_(this, a)
#define XCONNECT_IMPL_2(a, b) InstMsgHandler::GetInstance()->XConnect_(a, b)
#define XCONNECT_IMPL(n) XCONNECT_IMPL_##n
#define XCONNECT_DISPATCH(n, ...) EXPAND(XCONNECT_IMPL(n)(__VA_ARGS__))
#define XConnect(...) XCONNECT_DISPATCH(EXPAND(COUNT_ARGS(__VA_ARGS__)), __VA_ARGS__)

#define XDISCONNECT_IMPL_1(a) InstMsgHandler::GetInstance()->XDisconnect_(this, a)
#define XDISCONNECT_IMPL_2(a, b) InstMsgHandler::GetInstance()->XDisconnect_(a, b)
#define XDISCONNECT_IMPL(n) XDISCONNECT_IMPL_##n
#define XDISCONNECT_DISPATCH(n, ...) EXPAND(XDISCONNECT_IMPL(n)(__VA_ARGS__))
#define XDisconnect(...) XDISCONNECT_DISPATCH(EXPAND(COUNT_ARGS(__VA_ARGS__)), __VA_ARGS__)

#define XRegisterMsgHandler(msg, ...) InstMsgHandler::GetInstance()->XRegisterMsgHandler_(#msg, this, __VA_ARGS__)
#define XTriggerMsg(msg, ...) InstMsgHandler::GetInstance()->XTriggerMsg_(#msg, this, __VA_ARGS__)
#define XDeregister() InstMsgHandler::GetInstance()->XDeregister_(this)
单元测试
InstMsgHandlerUnitTest.h
#include <QTest>
#include <vector>

class InstMsgHandlerUnitTest :public QObject {
	Q_OBJECT
private slots:
	void initTestCase();
	void cleanupTestCase();
	void init();
	void cleanup();

	void RegisterTest();
	void DeregisterTest();

	void XConnectABTest();
	void XDisconnectABTest();
	void ABTriggerNoParamTest();
	void ABTriggerHasParamTest();

	void XConnectBaseTest();
	void BaseTriggerNoParamTest();
	void BaseTriggerHasParamTest();

	void MemoryLeakTest();
	void BaseMemoryLeakTest();
private:
	bool VarifyResult();
private:
	std::vector<bool> m_results;
};
InstMsgHandlerUnitTest.cpp
#include "InstMsgHandlerUnitTest.h"
#include "InstMsgHandler.h"

int GetCurMemoryKB()
{
   SetProcessWorkingSetSize(GetCurrentProcess(), -1, -1);
   PROCESS_MEMORY_COUNTERS pmc;
   GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
   auto curMemoryKB = pmc.WorkingSetSize / 1024;
   return curMemoryKB;
}

enum Msg {
   A,
   B,
   C,
};

void InstMsgHandlerUnitTest::RegisterTest()
{
   struct ClassA {
   	ClassA() {
   		XRegisterMsgHandler(Msg::A, [this] {});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {});
   	}
   	~ClassA() {
   		XDeregister();
   	}
   };
   struct ClassB {
   	ClassB() {
   		XRegisterMsgHandler(Msg::A, [this] {});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {});
   	}
   	~ClassB() {
   		XDeregister();
   	}
   };

   ClassA a;
   const auto& globalMsgHandler = InstMsgHandler::GetInstance()->globalMsgHandler_;
   m_results.push_back(globalMsgHandler.size() == 2);
   m_results.push_back(globalMsgHandler.at("Msg::A").size() == 1);
   m_results.push_back(globalMsgHandler.at("Msg::B").size() == 1);

   ClassB b;
   m_results.push_back(globalMsgHandler.size() == 2);
   m_results.push_back(globalMsgHandler.at("Msg::A").size() == 2);
   m_results.push_back(globalMsgHandler.at("Msg::B").size() == 2);

   QVERIFY(VarifyResult());
}

void InstMsgHandlerUnitTest::DeregisterTest() 
{
   struct ClassA {
   	ClassA() {
   		XRegisterMsgHandler(Msg::A, [this] {});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {});
   	}
   	~ClassA() {
   		XDeregister();
   	}
   };
   struct ClassB {
   	ClassB() {
   		XRegisterMsgHandler(Msg::A, [this] {});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {});
   	}
   	~ClassB() {
   		XDeregister();
   	}
   };
   const auto& globalMsgHandler = InstMsgHandler::GetInstance()->globalMsgHandler_;
   const auto& communicators = InstMsgHandler::GetInstance()->communicators_;
   {
   	ClassA a;
   	m_results.push_back(globalMsgHandler.size() == 2);
   	m_results.push_back(globalMsgHandler.at("Msg::A").size() == 1);
   	m_results.push_back(globalMsgHandler.at("Msg::B").size() == 1);
   	m_results.push_back(communicators.size() == 0);
   	{
   		ClassB b;
   		m_results.push_back(globalMsgHandler.size() == 2);
   		m_results.push_back(globalMsgHandler.at("Msg::A").size() == 2);
   		m_results.push_back(globalMsgHandler.at("Msg::B").size() == 2);
   		XConnect(&a, &b);
   		m_results.push_back(communicators.size() == 2);
   		m_results.push_back(communicators.at(&a).size() == 1);
   		m_results.push_back(communicators.at(&b).size() == 1);
   	}
   	m_results.push_back(globalMsgHandler.size() == 2);
   	m_results.push_back(globalMsgHandler.at("Msg::A").size() == 1);
   	m_results.push_back(globalMsgHandler.at("Msg::B").size() == 1);
   	m_results.push_back(communicators.size() == 1);
   	m_results.push_back(communicators.at(&a).size() == 0);
   }

   m_results.push_back(communicators.size() == 0);
   m_results.push_back(globalMsgHandler.size() == 2);
   m_results.push_back(globalMsgHandler.at("Msg::A").size() == 0);
   m_results.push_back(globalMsgHandler.at("Msg::B").size() == 0);
   QVERIFY(VarifyResult());
}

void InstMsgHandlerUnitTest::XConnectABTest()
{
   struct ClassA {
   	ClassA() {
   		XRegisterMsgHandler(Msg::A, [this] {});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {});
   	}
   	~ClassA() {
   		XDeregister();
   	}
   };
   struct ClassB {
   	ClassB() {
   		XRegisterMsgHandler(Msg::A, [this] {});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {});
   	}
   	~ClassB() {
   		XDeregister();
   	}
   };

   ClassA a;
   ClassB b;
   XConnect(&a, &b);

   const auto& globalMsgHandler = InstMsgHandler::GetInstance()->globalMsgHandler_;
   const auto& communicators = InstMsgHandler::GetInstance()->communicators_;

   m_results.push_back(globalMsgHandler.size() == 2);
   m_results.push_back(globalMsgHandler.at("Msg::A").size() == 2);
   m_results.push_back(globalMsgHandler.at("Msg::B").size() == 2);

   m_results.push_back(communicators.size() == 2);
   m_results.push_back(communicators.at(&a).size() == 1);
   m_results.push_back(communicators.at(&b).size() == 1);
   QVERIFY(VarifyResult());
}

void InstMsgHandlerUnitTest::XDisconnectABTest()
{
   struct ClassA {
   	ClassA() {
   		XRegisterMsgHandler(Msg::A, [this] {});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {});
   	}
   	~ClassA() {
   		XDeregister();
   	}
   };
   struct ClassB {
   	ClassB() {
   		XRegisterMsgHandler(Msg::A, [this] {});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {});
   	}
   	~ClassB() {
   		XDeregister();
   	}
   };

   ClassA a;
   ClassB b;
   XConnect(&a, &b);

   const auto& globalMsgHandler = InstMsgHandler::GetInstance()->globalMsgHandler_;
   const auto& communicators = InstMsgHandler::GetInstance()->communicators_;

   m_results.push_back(globalMsgHandler.size() == 2);
   m_results.push_back(globalMsgHandler.at("Msg::A").size() == 2);
   m_results.push_back(globalMsgHandler.at("Msg::B").size() == 2);

   m_results.push_back(communicators.size() == 2);
   m_results.push_back(communicators.at(&a).size() == 1);
   m_results.push_back(communicators.at(&b).size() == 1);

   XDisconnect(&a, &b);
   m_results.push_back(globalMsgHandler.size() == 2);
   m_results.push_back(globalMsgHandler.at("Msg::A").size() == 2);
   m_results.push_back(globalMsgHandler.at("Msg::B").size() == 2);

   m_results.push_back(communicators.size() == 2);
   m_results.push_back(communicators.at(&a).size() == 0);
   m_results.push_back(communicators.at(&b).size() == 0);
   QVERIFY(VarifyResult());
}

int TriggerNoParamTestTempVar = 0;
void InstMsgHandlerUnitTest::ABTriggerNoParamTest()
{
   TriggerNoParamTestTempVar = 0;
   struct ClassA {
   	ClassA() {
   		XRegisterMsgHandler(Msg::A, [this] {
   			TriggerNoParamTestTempVar += 1;
   		});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {});
   	}
   	~ClassA() {
   		XDeregister();
   	}
   	void Call() {
   		XTriggerMsg(Msg::A);
   	}
   };
   struct ClassB {
   	ClassB() {
   		XRegisterMsgHandler(Msg::A, [this] {
   			TriggerNoParamTestTempVar += 1;
   		});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {});
   	}
   	~ClassB() {
   		XDeregister();
   	}
   	void Call() {
   		XTriggerMsg(Msg::A);
   	}
   };
   ClassA a;
   ClassB b;
   XConnect(&a, &b);
   const auto& globalMsgHandler = InstMsgHandler::GetInstance()->globalMsgHandler_;
   const auto& communicators = InstMsgHandler::GetInstance()->communicators_;

   m_results.push_back(globalMsgHandler.size() == 2);
   m_results.push_back(globalMsgHandler.at("Msg::A").size() == 2);
   m_results.push_back(globalMsgHandler.at("Msg::B").size() == 2);

   m_results.push_back(communicators.size() == 2);
   m_results.push_back(communicators.at(&a).size() == 1);
   m_results.push_back(communicators.at(&b).size() == 1);

   a.Call();
   m_results.push_back(TriggerNoParamTestTempVar == 1);
   b.Call();
   m_results.push_back(TriggerNoParamTestTempVar == 2);

   XDisconnect(&a, &b);
   a.Call();
   m_results.push_back(TriggerNoParamTestTempVar == 2);
   b.Call();
   m_results.push_back(TriggerNoParamTestTempVar == 2);
   QVERIFY(VarifyResult());
}

int TriggerHasParamTestTempVar = 0;
void InstMsgHandlerUnitTest::ABTriggerHasParamTest()
{
   TriggerHasParamTestTempVar = 0;
   struct ClassA {
   	ClassA() {
   		XRegisterMsgHandler(Msg::A, [this] {});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {
   			TriggerHasParamTestTempVar = std::any_cast<int>(data);
   		});
   	}
   	~ClassA() {
   		XDeregister();
   	}
   	void Call() {
   		XTriggerMsg(Msg::B, 100);
   	}
   };
   struct ClassB {
   	ClassB() {
   		XRegisterMsgHandler(Msg::A, [this] {});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {
   			TriggerHasParamTestTempVar = std::any_cast<int>(data);
   		});
   	}
   	~ClassB() {
   		XDeregister();
   	}
   	void Call() {
   		XTriggerMsg(Msg::B, -100);
   	}
   };
   ClassA a;
   ClassB b;
   XConnect(&a, &b);
   const auto& globalMsgHandler = InstMsgHandler::GetInstance()->globalMsgHandler_;
   const auto& communicators = InstMsgHandler::GetInstance()->communicators_;

   m_results.push_back(globalMsgHandler.size() == 2);
   m_results.push_back(globalMsgHandler.at("Msg::A").size() == 2);
   m_results.push_back(globalMsgHandler.at("Msg::B").size() == 2);

   m_results.push_back(communicators.size() == 2);
   m_results.push_back(communicators.at(&a).size() == 1);
   m_results.push_back(communicators.at(&b).size() == 1);

   a.Call();
   m_results.push_back(TriggerHasParamTestTempVar == 100);
   b.Call();
   m_results.push_back(TriggerHasParamTestTempVar == -100);
   QVERIFY(VarifyResult());
}

void InstMsgHandlerUnitTest::XConnectBaseTest()
{
   struct ClassA {
   	ClassA() {
   		XRegisterMsgHandler(Msg::A, [this] {});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {});
   	}
   	~ClassA() {
   		XDeregister();
   	}
   };
   struct ClassB : ClassA {
   	ClassB() {
   		XConnect(this);
   	}
   	~ClassB() {
   		XDeregister();
   	}
   };

   ClassB b;

   const auto& globalMsgHandler = InstMsgHandler::GetInstance()->globalMsgHandler_;
   const auto& communicators = InstMsgHandler::GetInstance()->communicators_;

   m_results.push_back(globalMsgHandler.size() == 2);
   m_results.push_back(globalMsgHandler.at("Msg::A").size() == 1);
   m_results.push_back(globalMsgHandler.at("Msg::B").size() == 1);

   m_results.push_back(communicators.size() == 1);
   m_results.push_back(communicators.at(&b).size() == 1);
}

int BaseTriggerNoParamTestTempVar = 0;
void InstMsgHandlerUnitTest::BaseTriggerNoParamTest()
{
   BaseTriggerNoParamTestTempVar = 0;
   struct ClassA {
   	ClassA() {
   		XRegisterMsgHandler(Msg::A, [this] {
   			BaseTriggerNoParamTestTempVar += 1;
   		});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {});
   	}
   	~ClassA() {
   		XDeregister();
   	}
   	void CallBase() {
   		XTriggerMsg(Msg::A);
   	}
   };
   struct ClassB : ClassA {
   	ClassB() {
   		XConnect(this);
   	}
   	~ClassB() {
   		XDeregister();
   	}
   	void CallDriver() {
   		XTriggerMsg(Msg::A);
   	}
   };

   ClassB b;
   const auto& globalMsgHandler = InstMsgHandler::GetInstance()->globalMsgHandler_;
   const auto& communicators = InstMsgHandler::GetInstance()->communicators_;

   m_results.push_back(globalMsgHandler.size() == 2);
   m_results.push_back(globalMsgHandler.at("Msg::A").size() == 1);
   m_results.push_back(globalMsgHandler.at("Msg::B").size() == 1);

   m_results.push_back(communicators.size() == 1);
   m_results.push_back(communicators.at(&b).size() == 1);

   b.CallBase();
   m_results.push_back(BaseTriggerNoParamTestTempVar == 1);
   b.CallDriver();
   m_results.push_back(BaseTriggerNoParamTestTempVar == 2);
   QVERIFY(VarifyResult());
}

int BaseTriggerHasParamTestTempVar = 0;
void InstMsgHandlerUnitTest::BaseTriggerHasParamTest()
{
   BaseTriggerHasParamTestTempVar = 0;
   struct ClassA {
   	ClassA() {
   		XRegisterMsgHandler(Msg::A, [this] {});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {
   			BaseTriggerHasParamTestTempVar = std::any_cast<int>(data);
   		});
   	}
   	~ClassA() {
   		XDeregister();
   	}
   	void CallBase() {
   		XTriggerMsg(Msg::B, 100);
   	}
   };
   struct ClassB : ClassA {
   	ClassB() {
   		XConnect(this);
   	}
   	~ClassB() {
   		XDeregister();
   	}
   	void CallDriver() {
   		XTriggerMsg(Msg::B, -100);
   	}
   };

   ClassB b;
   const auto& globalMsgHandler = InstMsgHandler::GetInstance()->globalMsgHandler_;
   const auto& communicators = InstMsgHandler::GetInstance()->communicators_;

   m_results.push_back(globalMsgHandler.size() == 2);
   m_results.push_back(globalMsgHandler.at("Msg::A").size() == 1);
   m_results.push_back(globalMsgHandler.at("Msg::B").size() == 1);

   m_results.push_back(communicators.size() == 1);
   m_results.push_back(communicators.at(&b).size() == 1);

   b.CallBase();
   m_results.push_back(BaseTriggerHasParamTestTempVar == 100);
   b.CallDriver();
   m_results.push_back(BaseTriggerHasParamTestTempVar == -100);
   QVERIFY(VarifyResult());
}

void InstMsgHandlerUnitTest::MemoryLeakTest()
{
   struct ClassA {
   	ClassA() {
   		XRegisterMsgHandler(Msg::A, [this] {});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {});
   	}
   	~ClassA() {
   		XDeregister();
   	}
   	int a = 0;
   };
   struct ClassB {
   	ClassB() {
   		XRegisterMsgHandler(Msg::A, [this] {});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {});
   	}
   	~ClassB() {
   		XDeregister();
   	}
   	int b = 0;
   };
   auto beginMemory = GetCurMemoryKB();
   {
   	std::vector<ClassA*> veca;
   	std::vector<ClassB*> vecb;
   	for (int i = 0; i < 10000; ++i) {
   		ClassA* a = new ClassA;
   		ClassB* b = new ClassB;
   		XConnect(a, b);
   		veca.push_back(a);
   		vecb.push_back(b);
   	}

   	const auto& globalMsgHandler = InstMsgHandler::GetInstance()->globalMsgHandler_;
   	const auto& communicators = InstMsgHandler::GetInstance()->communicators_;

   	m_results.push_back(globalMsgHandler.size() == 2);
   	m_results.push_back(globalMsgHandler.at("Msg::A").size() == 20000);
   	m_results.push_back(globalMsgHandler.at("Msg::B").size() == 20000);
   	m_results.push_back(communicators.size() == 20000);
   	for (auto& communicator : communicators) {
   		QVERIFY(communicator.second.size() == 1);
   	}
   	for (auto& v : veca) {
   		delete v;
   	}
   	for (auto& v : vecb) {
   		delete v;
   	}
   	veca.clear();
   	vecb.clear();
   	m_results.push_back(globalMsgHandler.size() == 2);
   	m_results.push_back(globalMsgHandler.at("Msg::A").size() == 0);
   	m_results.push_back(globalMsgHandler.at("Msg::B").size() == 0);
   	m_results.push_back(communicators.size() == 0);
   }
   auto endMemory = GetCurMemoryKB();
   QVERIFY(endMemory - beginMemory < 30);
}

void InstMsgHandlerUnitTest::BaseMemoryLeakTest()
{
   struct ClassA {
   	ClassA() {
   		XRegisterMsgHandler(Msg::A, [this] {});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {});
   	}
   	~ClassA() {
   		XDeregister();
   	}
   	int a = 0;
   };
   struct ClassB : ClassA {
   	ClassB() {
   		XRegisterMsgHandler(Msg::A, [this] {});
   		XRegisterMsgHandler(Msg::B, [this](const std::any& data) {});
   		XConnect(this);
   	}
   	~ClassB() {
   		XDeregister();
   	}
   	int b = 0;
   };
   auto beginMemory = GetCurMemoryKB();
   {
   	std::vector<ClassB*> vecb;
   	for (int i = 0; i < 10000; ++i) {
   		vecb.push_back(new ClassB);
   	}
   	for (auto& v : vecb) {
   		delete v;
   	}
   	vecb.clear();
   }
   auto endMemory = GetCurMemoryKB();
   QVERIFY(endMemory - beginMemory < 30);
}

bool InstMsgHandlerUnitTest::VarifyResult()
{
   bool result = true;
   for (auto& rlt : m_results) {
   	if (!rlt) {
   		result = false;
   		break;
   	}
   }
   return result;
}

void InstMsgHandlerUnitTest::initTestCase()
{
}

void InstMsgHandlerUnitTest::cleanupTestCase()
{
}

void InstMsgHandlerUnitTest::init()
{
   m_results.clear();
   InstMsgHandler::GetInstance()->globalMsgHandler_.clear();
   InstMsgHandler::GetInstance()->communicators_.clear();
}

void InstMsgHandlerUnitTest::cleanup()
{
}