154 lines
5.6 KiB
C++
154 lines
5.6 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)));
|
|
LOG(debug) << "register message,topic: " << signature;
|
|
}
|
|
|
|
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)...)});
|
|
LOG(debug) << "call async message,topic: " << signature;
|
|
}
|
|
|
|
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__
|