Kylin/Universal/MessageManager.inl
2024-09-16 01:32:40 +08:00

158 lines
5.7 KiB
C++

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