Out of line some methods of EventManager

This commit is contained in:
Giulio Eulisse 2025-01-06 16:42:53 +01:00
parent e4f258c9ea
commit 93d113a8b6
4 changed files with 95 additions and 54 deletions

View File

@ -119,6 +119,7 @@ if(BUILD_FAIRMQ)
Channel.cxx
Device.cxx
DeviceRunner.cxx
EventManager.cxx
JSONParser.cxx
MemoryResources.cxx
Plugin.cxx

19
fairmq/EventManager.cxx Normal file
View File

@ -0,0 +1,19 @@
/********************************************************************************
* Copyright (C) 2014-2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include "EventManager.h"
#include <string>
template std::shared_ptr<
fair::mq::EventManager::Signal<fair::mq::PropertyChangeAsString, std::string>>
fair::mq::EventManager::GetSignal<fair::mq::PropertyChangeAsString, std::string>(
const std::pair<std::type_index, std::type_index>& key) const;
template void fair::mq::EventManager::Subscribe<fair::mq::PropertyChangeAsString, std::string>(
const std::string& subscriber,
std::function<void(typename fair::mq::PropertyChangeAsString::KeyType, std::string)>);

View File

@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (C) 2014-2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* Copyright (C) 2014-2025 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
@ -9,20 +9,18 @@
#ifndef FAIR_MQ_EVENTMANAGER_H
#define FAIR_MQ_EVENTMANAGER_H
#include <boost/any.hpp>
#include <boost/functional/hash.hpp>
#include <boost/signals2.hpp>
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <typeindex>
#include <unordered_map>
#include <utility>
#include <functional>
#include <boost/any.hpp>
#include <boost/functional/hash.hpp>
#include <boost/signals2.hpp>
namespace fair::mq
{
namespace fair::mq {
// Inherit from this base event type to create custom event types
template<typename K>
@ -54,36 +52,19 @@ class EventManager
// template<typename E, typename ...Args>
// using Callback = std::function<void(typename E::KeyType, Args...)>;
template<typename E, typename ...Args>
template<typename E, typename... Args>
using Signal = boost::signals2::signal<void(typename E::KeyType, Args...)>;
template<typename E, typename ...Args>
auto Subscribe(const std::string& subscriber, std::function<void(typename E::KeyType, Args...)> callback) -> void
{
const std::type_index event_type_index{typeid(E)};
const std::type_index callback_type_index{typeid(std::function<void(typename E::KeyType, Args...)>)};
const auto signalsKey = std::make_pair(event_type_index, callback_type_index);
const auto connectionsKey = std::make_pair(subscriber, signalsKey);
template<typename E, typename... Args>
auto Subscribe(const std::string& subscriber,
std::function<void(typename E::KeyType, Args...)> callback) -> void;
const auto connection = GetSignal<E, Args...>(signalsKey)->connect(callback);
{
std::lock_guard<std::mutex> lock{fMutex};
if (fConnections.find(connectionsKey) != fConnections.end())
{
fConnections.at(connectionsKey).disconnect();
fConnections.erase(connectionsKey);
}
fConnections.insert({connectionsKey, connection});
}
}
template<typename E, typename ...Args>
template<typename E, typename... Args>
auto Unsubscribe(const std::string& subscriber) -> void
{
const std::type_index event_type_index{typeid(E)};
const std::type_index callback_type_index{typeid(std::function<void(typename E::KeyType, Args...)>)};
const std::type_index callback_type_index{
typeid(std::function<void(typename E::KeyType, Args...)>)};
const auto signalsKey = std::make_pair(event_type_index, callback_type_index);
const auto connectionsKey = std::make_pair(subscriber, signalsKey);
@ -93,48 +74,88 @@ class EventManager
fConnections.erase(connectionsKey);
}
template<typename E, typename ...Args>
template<typename E, typename... Args>
auto Emit(typename E::KeyType key, Args... args) const -> void
{
const std::type_index event_type_index{typeid(E)};
const std::type_index callback_type_index{typeid(std::function<void(typename E::KeyType, Args...)>)};
const std::type_index callback_type_index{
typeid(std::function<void(typename E::KeyType, Args...)>)};
const auto signalsKey = std::make_pair(event_type_index, callback_type_index);
(*GetSignal<E, Args...>(signalsKey))(key, std::forward<Args>(args)...);
}
private:
using SignalsKey = std::pair<std::type_index, std::type_index>;
// event , callback
using SignalsKey = std::pair<std::type_index, std::type_index>;
// event , callback
using SignalsValue = boost::any;
using SignalsMap = std::unordered_map<SignalsKey, SignalsValue, boost::hash<SignalsKey>>;
using SignalsMap = std::unordered_map<SignalsKey, SignalsValue, boost::hash<SignalsKey>>;
mutable SignalsMap fSignals;
using ConnectionsKey = std::pair<std::string, SignalsKey>;
// subscriber , event/callback
using ConnectionsKey = std::pair<std::string, SignalsKey>;
// subscriber , event/callback
using ConnectionsValue = boost::signals2::connection;
using ConnectionsMap = std::unordered_map<ConnectionsKey, ConnectionsValue, boost::hash<ConnectionsKey>>;
using ConnectionsMap =
std::unordered_map<ConnectionsKey, ConnectionsValue, boost::hash<ConnectionsKey>>;
ConnectionsMap fConnections;
mutable std::mutex fMutex;
template<typename E, typename ...Args>
auto GetSignal(const SignalsKey& key) const -> std::shared_ptr<Signal<E, Args...>>
template<typename E, typename... Args>
auto GetSignal(const SignalsKey& key) const -> std::shared_ptr<Signal<E, Args...>>;
}; /* class EventManager */
struct PropertyChangeAsString : Event<std::string>
{};
template<typename E, typename... Args>
auto EventManager::GetSignal(const SignalsKey& key) const -> std::shared_ptr<Signal<E, Args...>>
{
std::lock_guard<std::mutex> lock{fMutex};
if (fSignals.find(key) == fSignals.end()) {
// wrapper is needed because boost::signals2::signal is neither copyable nor movable
// and I don't know how else to insert it into the map
auto signal = std::make_shared<Signal<E, Args...>>();
fSignals.insert(std::make_pair(key, signal));
}
return boost::any_cast<std::shared_ptr<Signal<E, Args...>>>(fSignals.at(key));
}
template<typename E, typename... Args>
auto EventManager::Subscribe(const std::string& subscriber,
std::function<void(typename E::KeyType, Args...)> callback) -> void
{
const std::type_index event_type_index{typeid(E)};
const std::type_index callback_type_index{
typeid(std::function<void(typename E::KeyType, Args...)>)};
const auto signalsKey = std::make_pair(event_type_index, callback_type_index);
const auto connectionsKey = std::make_pair(subscriber, signalsKey);
const auto connection = GetSignal<E, Args...>(signalsKey)->connect(callback);
{
std::lock_guard<std::mutex> lock{fMutex};
if (fSignals.find(key) == fSignals.end())
{
// wrapper is needed because boost::signals2::signal is neither copyable nor movable
// and I don't know how else to insert it into the map
auto signal = std::make_shared<Signal<E, Args...>>();
fSignals.insert(std::make_pair(key, signal));
if (fConnections.find(connectionsKey) != fConnections.end()) {
fConnections.at(connectionsKey).disconnect();
fConnections.erase(connectionsKey);
}
return boost::any_cast<std::shared_ptr<Signal<E, Args...>>>(fSignals.at(key));
fConnections.insert({connectionsKey, connection});
}
}; /* class EventManager */
}
} // namespace fair::mq
extern template std::shared_ptr<
fair::mq::EventManager::Signal<fair::mq::PropertyChangeAsString, std::string>>
fair::mq::EventManager::GetSignal<fair::mq::PropertyChangeAsString, std::string>(
const std::pair<std::type_index, std::type_index>& key) const;
extern template void
fair::mq::EventManager::Subscribe<fair::mq::PropertyChangeAsString, std::string>(
const std::string& subscriber,
std::function<void(typename fair::mq::PropertyChangeAsString::KeyType, std::string)>);
} // namespace fair::mq
#endif /* FAIR_MQ_EVENTMANAGER_H */

View File

@ -28,8 +28,8 @@ namespace fair::mq
using Property = boost::any;
using Properties = std::map<std::string, Property>;
struct PropertyChange : Event<std::string> {};
struct PropertyChangeAsString : Event<std::string> {};
struct PropertyChange : Event<std::string>
{};
class PropertyHelper
{