#ifndef __MESSAGEMANAGER_INL__ #define __MESSAGEMANAGER_INL__ #include "BoostLog.h" #include "FunctionTraits.h" #include "MessageManager.h" #include #include template class Signature; template class Signature> { public: using Type = std::tuple...>; }; template static void formatSignature(std::ostringstream &oss, Type &&type) { oss << boost::typeindex::type_id(); } template static void formatSignature(std::ostringstream &oss, Type &&type, Args &&...args) { oss << boost::typeindex::type_id() << ","; formatSignature(oss, args...); } template static void formatSignature(std::ostringstream &oss, ArgTuple &&args, std::index_sequence) { formatSignature(oss, std::get(args)...); } template static std::string formatTopicWithFunction(const std::string_view &topic) { std::ostringstream oss; using Arguments = typename FunctionTraits>::Arguments; using Sigs = typename Signature::Type; oss << topic << "###["; if constexpr (std::tuple_size::value > 0) { formatSignature(oss, Sigs{}, std::make_index_sequence::value>{}); } else { oss << "void"; } oss << "]"; return oss.str(); } template static std::string formatTopicWithParameters(const std::string_view &topic, Args &&...args) { std::ostringstream oss; oss << topic << "###["; if constexpr (sizeof...(Args) > 0) { formatSignature(oss, std::forward(args)...); } else { oss << "void"; } oss << "]"; return oss.str(); } template void MessageManager::registerTopic(const std::string_view &topic, Function &&f) { auto signature = formatTopicWithFunction(topic); m_executors.emplace(signature, executorWrapper(std::move(f))); LOG(debug) << "register message,topic: " << signature; } template void MessageManager::registerTopic(const Message &topic, Function &&f) { using Arguments = typename FunctionTraits>::Arguments; static_assert(std::is_same_v>, "arguments not same..."); registerTopic(topic.topic, std::forward(f)); } template size_t MessageManager::topicCount(const std::string_view &topic) { auto signature = formatTopicWithFunction(topic); return m_executors.count(signature); } template void MessageManager::removeTopic(const std::string_view &topic) { auto signature = formatTopicWithFunction(topic); m_executors.erase(signature); } template void MessageManager::sendMessage(const std::string_view &topic, Args &&...args) { auto signature = formatTopicWithParameters(topic, std::forward(args)...); callExecutor(signature, std::make_tuple(std::forward(args)...)); } template void MessageManager::sendMessage(const std::string_view &topic, Args &&...args) { using Arguments = typename FunctionTraits>::Arguments; // LOG(debug) << boost::typeindex::type_id(); auto signature = formatTopicWithFunction(topic); callExecutor(signature, Arguments{std::forward(args)...}); } template void MessageManager::sendMessage(const Message &topic, Args &&...args) { using Arguments = typename FunctionTraits::Arguments; auto signature = formatTopicWithFunction(topic.topic); callExecutor(signature, Arguments{std::forward(args)...}); } template void MessageManager::sendAsyncMessage(const std::string_view &topic, Args &&...args) { auto signature = formatTopicWithParameters(topic, std::forward(args)...); m_params.push({signature, std::make_tuple(std::forward(args)...)}); LOG(debug) << "call async message,topic: " << signature; } template void MessageManager::sendAsyncMessage(const std::string_view &topic, Args &&...args) { using Arguments = typename FunctionTraits>::Arguments; auto signature = formatTopicWithFunction(topic); m_params.push({signature, Arguments{std::forward(args)...}}); } template void MessageManager::sendAsyncMessage(const Message &topic, Args &&...args) { using Function = void(TArgs...); using Arguments = typename FunctionTraits::Arguments; auto signature = formatTopicWithFunction(topic.topic); m_params.push({signature, Arguments{std::forward(args)...}}); } template MessageManager::Executor MessageManager::executorWrapper(Function &&f) { return [executor(std::move(f))](const std::any &args) -> bool { using Arguments = typename FunctionTraits::Arguments; auto arguments = std::any_cast(&args); if (arguments != nullptr) { std::apply(executor, *arguments); return true; } using Signature = typename Signature::Type; auto signature = std::any_cast(&args); if (signature != nullptr) { std::apply(executor, *signature); return true; } return false; }; } #endif // __MESSAGEMANAGER_H__