我花了几天的搜索我的问题,但找不到任何有效的解决方案。
我有一个名为ServiceEventHub类,它负责在我的应用程序调度事件。该代码是由什么我在网上找到实现事件聚合的启发。该应用程序是一种动态加载不同的dll(插件)插件引擎。这个类是由驻留在应用程序(.EXE)内的发动机提供的服务。
问题是,该类依赖于静态变量来跟踪不同的“事件”发出和注册。 (事件是简单地在一个共同的头文件中定义的结构)。从我underdstand,由于这样的事实,符号不导出默认情况下在Windows上,静态变量不是在应用程序和DLL相同的实例。你可以想像,在“事件类型”是不是发动机和插件之间的相同和预期的不表现。这是我第一次在Windows上开发,我有点失落。
因为有些方法使用的模板,我不能动的实施,一个CPP文件。我曾尝试DLLEXPORT / dllimport的方法,但同样是因为类使用模板这是行不通的。此外,在我的例子中它出口的应用和进口的,如果不知道它应该围绕这种方式工作该DLL。
我又看了看#pragma data_seg
,但我不知道如何使用它..全班?只需使用静态2种方法?
下面是完整的代码:
class ServiceEventHub
{
public:
template <class EventType>
using Slot = std::function<void(const EventType&)>;
ServiceEventHub()
{
}
template <typename EventType>
void subscribe(Slot<EventType> callable)
{
LOG_FUNC_ENTER();
std::lock_guard<std::recursive_mutex> lock(m_mutex);
size_t type = Event<EventType>::type();
if (type >= m_subscribers.size())
{
m_subscribers.resize(type + 1);
}
m_subscribers[type].push_back(CallbackWrapper<EventType>(callable));
}
template <typename EventType>
void emit(EventType&& event)
{
LOG_FUNC_ENTER(typeid(EventType).name());
// Critical section starts
std::lock_guard<std::recursive_mutex> lock(m_mutex);
size_t type = Event<EventType>::type();
if (type >= m_subscribers.size())
{
return;
}
Event<EventType> eventWrapper(std::forward<EventType>(event));
for (auto& receiver : m_subscribers[type])
{
m_ioService.post(boost::bind(receiver, eventWrapper));
}
// Critical section ends
}
private:
struct BaseEvent
{
virtual ~BaseEvent() {}
protected:
static size_t getNextType()
{
static size_t s_typeCount{ 0 };
return s_typeCount++;
}
};
template <typename EventType>
struct Event : BaseEvent
{
static size_t type()
{
static size_t s_type = BaseEvent::getNextType();
return s_type;
}
Event(EventType&& event)
: event_(std::forward<EventType>(event))
{
}
EventType event_;
};
template <typename EventType>
struct CallbackWrapper
{
CallbackWrapper(Slot<EventType> callable)
: m_callable(callable)
{
}
void operator()(const BaseEvent& event)
{
m_callable(static_cast<const Event<EventType>&>(event).event_);
}
Slot<EventType> m_callable;
};
void workerThread(boost::asio::io_service* ioService)
{
LOG_FUNC_ENTER();
ioService->run();
}
std::vector<std::vector<Slot<BaseEvent> > > m_subscribers = {};
std::recursive_mutex m_mutex;
boost::asio::io_service m_ioService{};
boost::asio::io_service::work m_ioWork{m_ioService};
std::thread m_thread{boost::bind(&ServiceEventHub::workerThread, this, &m_ioService)};
};
任何帮助将非常感激。
我设法避免通过使用模板类型信息使用静态计数器:
static size_t type()
{
return typeid(EventType).hash_code();
}
从我可以在线阅读,实施应确保返回的值是唯一的类型和type1.hash_code == type2.hash_code意味着TYPE1 == 2型。
下面是代码:
class ServiceEventHub
{
public:
template <class EventType>
using Slot = std::function<void(const EventType&)>;
template <typename EventType>
void subscribe(Slot<EventType> callable)
{
LOG_FUNC_ENTER();
size_t type = Event<EventType>::type();
// Critical section starts
std::lock_guard<std::recursive_mutex> lock(m_mutex);
auto search = m_subscribers.find(type);
if (search != m_subscribers.cend())
{
search->second.push_back(CallbackWrapper<EventType>(callable));
}
else
{
m_subscribers[type] = { CallbackWrapper<EventType>(callable) };
}
// Critical section ends
}
template <typename EventType>
void emit(EventType&& event)
{
LOG_FUNC_ENTER(typeid(EventType).name());
size_t type = Event<EventType>::type();
// Critical section starts
std::lock_guard<std::recursive_mutex> lock(m_mutex);
auto typeCallbacks = m_subscribers.find(type);
if (typeCallbacks == m_subscribers.cend())
{
return;
}
Event<EventType> eventWrapper(std::forward<EventType>(event));
for (auto& receiver : typeCallbacks->second)
{
m_ioService.post(boost::bind(receiver, eventWrapper));
}
// Critical section ends
}
private:
struct BaseEvent
{
virtual ~BaseEvent() {}
};
template <typename EventType>
struct Event : BaseEvent
{
static size_t type()
{
return typeid(EventType).hash_code();
}
Event(EventType&& event)
: event_(std::forward<EventType>(event))
{
}
EventType event_;
};
template <typename EventType>
struct CallbackWrapper
{
CallbackWrapper(Slot<EventType> callable)
: m_callable(callable)
{
}
void operator()(const BaseEvent& event)
{
m_callable(static_cast<const Event<EventType>&>(event).event_);
}
Slot<EventType> m_callable;
};
void workerThread(boost::asio::io_service* ioService)
{
LOG_FUNC_ENTER();
ioService->run();
}
std::map<size_t, std::vector<Slot<BaseEvent> > > m_subscribers = {};
std::recursive_mutex m_mutex;
boost::asio::io_service m_ioService{};
boost::asio::io_service::work m_ioWork{m_ioService};
std::thread
m_thread{boost::bind(&ServiceEventHub::workerThread, this, &m_ioService)};
};