diff --git a/fairmq/CMakeLists.txt b/fairmq/CMakeLists.txt index 52cc8fce..0f864aee 100644 --- a/fairmq/CMakeLists.txt +++ b/fairmq/CMakeLists.txt @@ -95,6 +95,7 @@ set(FAIRMQ_HEADER_FILES tools/Network.h tools/runSimpleMQStateMachine.h tools/Strings.h + tools/Version.h zeromq/FairMQMessageZMQ.h zeromq/FairMQPollerZMQ.h zeromq/FairMQSocketZMQ.h diff --git a/fairmq/FairMQDevice.cxx b/fairmq/FairMQDevice.cxx index a4a56401..830088cd 100644 --- a/fairmq/FairMQDevice.cxx +++ b/fairmq/FairMQDevice.cxx @@ -854,7 +854,7 @@ int FairMQDevice::GetProperty(const int key, const int default_ /*= 0*/) shared_ptr FairMQDevice::AddTransport(const string& transport) { - unordered_map>::const_iterator i = fTransports.find(FairMQ::TransportTypes.at(transport)); + auto i = fTransports.find(FairMQ::TransportTypes.at(transport)); if (i == fTransports.end()) { diff --git a/fairmq/FairMQTransports.h b/fairmq/FairMQTransports.h index 2cfc89ab..5095476f 100644 --- a/fairmq/FairMQTransports.h +++ b/fairmq/FairMQTransports.h @@ -8,6 +8,7 @@ #ifndef FAIRMQTRANSPORTS_H_ #define FAIRMQTRANSPORTS_H_ +#include #include #include @@ -22,6 +23,7 @@ enum class Transport SHM }; + static std::unordered_map TransportTypes { { "default", Transport::DEFAULT }, { "zeromq", Transport::ZMQ }, @@ -34,14 +36,9 @@ static std::unordered_map TransportTypes { namespace std { -template <> -struct hash -{ - size_t operator()(const FairMQ::Transport& v) const - { - return hash()(static_cast(v)); - } -}; +template<> +struct hash : fair::mq::tools::HashEnum {}; + +} /* namespace std */ -} #endif /* FAIRMQTRANSPORTS_H_ */ diff --git a/fairmq/Plugin.cxx b/fairmq/Plugin.cxx index ce854334..55b9cd10 100644 --- a/fairmq/Plugin.cxx +++ b/fairmq/Plugin.cxx @@ -11,9 +11,9 @@ using namespace std; -fair::mq::Plugin::Plugin(const string name, const Version version, const string maintainer, const string homepage, PluginServices& pluginServices) +fair::mq::Plugin::Plugin(const string name, const Version version, const string maintainer, const string homepage, PluginServices* pluginServices) : fkName{name} -, fkVersion{version} +, fkVersion(version) , fkMaintainer{maintainer} , fkHomepage{homepage} , fPluginServices{pluginServices} diff --git a/fairmq/Plugin.h b/fairmq/Plugin.h index b1cdb928..f2ba0bd2 100644 --- a/fairmq/Plugin.h +++ b/fairmq/Plugin.h @@ -38,21 +38,10 @@ class Plugin using ProgOptions = boost::optional; - struct Version - { - const int fkMajor, fkMinor, fkPatch; - - friend auto operator< (const Version& lhs, const Version& rhs) -> bool { return std::tie(lhs.fkMajor, lhs.fkMinor, lhs.fkPatch) < std::tie(rhs.fkMajor, rhs.fkMinor, rhs.fkPatch); } - friend auto operator> (const Version& lhs, const Version& rhs) -> bool { return rhs < lhs; } - friend auto operator<=(const Version& lhs, const Version& rhs) -> bool { return !(lhs > rhs); } - friend auto operator>=(const Version& lhs, const Version& rhs) -> bool { return !(lhs < rhs); } - friend auto operator==(const Version& lhs, const Version& rhs) -> bool { return std::tie(lhs.fkMajor, lhs.fkMinor, lhs.fkPatch) == std::tie(rhs.fkMajor, rhs.fkMinor, rhs.fkPatch); } - friend auto operator!=(const Version& lhs, const Version& rhs) -> bool { return !(lhs == rhs); } - friend auto operator<<(std::ostream& os, const Version& v) -> std::ostream& { return os << v.fkMajor << "." << v.fkMinor << "." << v.fkPatch; } - }; + using Version = tools::Version; Plugin() = delete; - Plugin(const std::string name, const Version version, const std::string maintainer, const std::string homepage, PluginServices& pluginServices); + Plugin(const std::string name, const Version version, const std::string maintainer, const std::string homepage, PluginServices* pluginServices); virtual ~Plugin(); auto GetName() const -> const std::string& { return fkName; } @@ -75,24 +64,24 @@ class Plugin // see for docs using DeviceState = fair::mq::PluginServices::DeviceState; using DeviceStateTransition = fair::mq::PluginServices::DeviceStateTransition; - auto ToDeviceState(const std::string& state) const -> fair::mq::PluginServices::DeviceState { return fPluginServices.ToDeviceState(state); } - auto ToStr(fair::mq::PluginServices::DeviceState state) const -> std::string { return fPluginServices.ToStr(state); } - auto GetCurrentDeviceState() const -> fair::mq::PluginServices::DeviceState { return fPluginServices.GetCurrentDeviceState(); } - auto ChangeDeviceState(const fair::mq::PluginServices::DeviceStateTransition next) -> void { fPluginServices.ChangeDeviceState(next); } - auto SubscribeToDeviceStateChange(std::function callback) -> void { fPluginServices.SubscribeToDeviceStateChange(fkName, callback); } - auto UnsubscribeFromDeviceStateChange() -> void { fPluginServices.UnsubscribeFromDeviceStateChange(fkName); } + auto ToDeviceState(const std::string& state) const -> DeviceState { return fPluginServices->ToDeviceState(state); } + auto ToStr(DeviceState state) const -> std::string { return fPluginServices->ToStr(state); } + auto GetCurrentDeviceState() const -> DeviceState { return fPluginServices->GetCurrentDeviceState(); } + auto ChangeDeviceState(const DeviceStateTransition next) -> void { fPluginServices->ChangeDeviceState(next); } + auto SubscribeToDeviceStateChange(std::function callback) -> void { fPluginServices->SubscribeToDeviceStateChange(fkName, callback); } + auto UnsubscribeFromDeviceStateChange() -> void { fPluginServices->UnsubscribeFromDeviceStateChange(fkName); } // device config API // see for docs template - auto SetProperty(const std::string& key, T val) -> void { fPluginServices.SetProperty(key, val); } + auto SetProperty(const std::string& key, T val) -> void { fPluginServices->SetProperty(key, val); } template - auto GetProperty(const std::string& key) const -> T { return fPluginServices.GetProperty(key); } - auto GetPropertyAsString(const std::string& key) const -> std::string { return fPluginServices.GetPropertyAsString(key); } - template - auto SubscribeToPropertyChange(std::function callback) const -> void { fPluginServices.SubscribeToPropertyChange(fkName, callback); } - template - auto UnsubscribeFromPropertyChange() -> void { fPluginServices.UnsubscribeFromPropertyChange(fkName); } + auto GetProperty(const std::string& key) const -> T { return fPluginServices->GetProperty(key); } + auto GetPropertyAsString(const std::string& key) const -> std::string { return fPluginServices->GetPropertyAsString(key); } + // template + // auto SubscribeToPropertyChange(std::functionkey*/, const T /*newValue<])> callback) const -> void { fPluginServices.SubscribeToPropertyChange(fkName, callback); } + // template + // auto UnsubscribeFromPropertyChange() -> void { fPluginServices.UnsubscribeFromPropertyChange(fkName); } private: @@ -100,7 +89,7 @@ class Plugin const Version fkVersion; const std::string fkMaintainer; const std::string fkHomepage; - PluginServices& fPluginServices; + PluginServices* fPluginServices; }; /* class Plugin */ @@ -108,7 +97,7 @@ class Plugin } /* namespace fair */ #define REGISTER_FAIRMQ_PLUGIN(KLASS, NAME, VERSION, MAINTAINER, HOMEPAGE, PROGOPTIONS) \ -static auto Make_##NAME##_Plugin(fair::mq::PluginServices& pluginServices) -> std::shared_ptr \ +static auto Make_##NAME##_Plugin(fair::mq::PluginServices* pluginServices) -> std::shared_ptr \ { \ return std::make_shared(std::string{#NAME}, VERSION, std::string{MAINTAINER}, std::string{HOMEPAGE}, pluginServices); \ } \ diff --git a/fairmq/PluginServices.cxx b/fairmq/PluginServices.cxx index 619a0f17..1df410c1 100644 --- a/fairmq/PluginServices.cxx +++ b/fairmq/PluginServices.cxx @@ -8,7 +8,7 @@ #include -using fair::mq::PluginServices; +using namespace fair::mq; const std::unordered_map PluginServices::fkDeviceStateStrMap = { {"OK", DeviceState::Ok}, @@ -24,7 +24,7 @@ const std::unordered_map PluginService {"RESETTING DEVICE", DeviceState::ResettingDevice}, {"EXITING", DeviceState::Exiting} }; -const std::unordered_map PluginServices::fkStrDeviceStateMap = { +const std::unordered_map> PluginServices::fkStrDeviceStateMap = { {DeviceState::Ok, "OK"}, {DeviceState::Error, "ERROR"}, {DeviceState::Idle, "IDLE"}, @@ -49,7 +49,7 @@ const std::unordered_map Plu {"END", DeviceStateTransition::End}, {"ERROR FOUND", DeviceStateTransition::ErrorFound}, }; -const std::unordered_map PluginServices::fkStrDeviceStateTransitionMap = { +const std::unordered_map> PluginServices::fkStrDeviceStateTransitionMap = { {DeviceStateTransition::InitDevice, "INIT DEVICE"}, {DeviceStateTransition::InitTask, "INIT TASK"}, {DeviceStateTransition::Run, "RUN"}, @@ -60,7 +60,7 @@ const std::unordered_map Plu {DeviceStateTransition::End, "END"}, {DeviceStateTransition::ErrorFound, "ERROR FOUND"}, }; -const std::unordered_map PluginServices::fkDeviceStateMap = { +const std::unordered_map> PluginServices::fkDeviceStateMap = { {FairMQDevice::OK, DeviceState::Ok}, {FairMQDevice::ERROR, DeviceState::Error}, {FairMQDevice::IDLE, DeviceState::Idle}, @@ -74,7 +74,7 @@ const std::unordered_map Plugi {FairMQDevice::RESETTING_DEVICE, DeviceState::ResettingDevice}, {FairMQDevice::EXITING, DeviceState::Exiting} }; -const std::unordered_map PluginServices::fkDeviceStateTransitionMap = { +const std::unordered_map> PluginServices::fkDeviceStateTransitionMap = { {DeviceStateTransition::InitDevice, FairMQDevice::INIT_DEVICE}, {DeviceStateTransition::InitTask, FairMQDevice::INIT_TASK}, {DeviceStateTransition::Run, FairMQDevice::RUN}, diff --git a/fairmq/PluginServices.h b/fairmq/PluginServices.h index cb7d781b..c183f111 100644 --- a/fairmq/PluginServices.h +++ b/fairmq/PluginServices.h @@ -32,8 +32,15 @@ class PluginServices { public: + PluginServices() = delete; + PluginServices(FairMQProgOptions* config, std::shared_ptr device) + : fDevice{device} + , fConfig{config} + { + } + /// See https://github.com/FairRootGroup/FairRoot/blob/dev/fairmq/docs/Device.md#13-state-machine - enum class DeviceState + enum class DeviceState : int { Ok, Error, @@ -48,7 +55,8 @@ class PluginServices ResettingDevice, Exiting }; - enum class DeviceStateTransition // transition event between DeviceStates + + enum class DeviceStateTransition : int // transition event between DeviceStates { InitDevice, InitTask, @@ -61,13 +69,6 @@ class PluginServices ErrorFound }; - PluginServices() = delete; - PluginServices(FairMQProgOptions& config, FairMQDevice& device) - : fDevice{device} - , fConfig{config} - { - } - // Control API /// @brief Convert string to DeviceState @@ -86,23 +87,24 @@ class PluginServices /// @param state to convert /// @return string representation of DeviceState enum entry static auto ToStr(DeviceState state) -> std::string { return fkStrDeviceStateMap.at(state); } - friend auto operator<<(std::ostream& os, const DeviceState& state) -> std::ostream& { return os << ToStr(state); } /// @brief Convert DeviceStateTransition to string /// @param transition to convert /// @return string representation of DeviceStateTransition enum entry static auto ToStr(DeviceStateTransition transition) -> std::string { return fkStrDeviceStateTransitionMap.at(transition); } + + friend auto operator<<(std::ostream& os, const DeviceState& state) -> std::ostream& { return os << ToStr(state); } friend auto operator<<(std::ostream& os, const DeviceStateTransition& transition) -> std::ostream& { return os << ToStr(transition); } /// @return current device state - auto GetCurrentDeviceState() const -> DeviceState { return fkDeviceStateMap.at(static_cast(fDevice.GetCurrentState())); } + auto GetCurrentDeviceState() const -> DeviceState { return fkDeviceStateMap.at(static_cast(fDevice->GetCurrentState())); } /// @brief Request a device state transition /// @param next state transition /// /// The state transition may not happen immediately, but when the current state evaluates the /// pending transition event and terminates. In other words, the device states are scheduled cooperatively. - auto ChangeDeviceState(const DeviceStateTransition next) -> void { fDevice.ChangeState(fkDeviceStateTransitionMap.at(next)); } + auto ChangeDeviceState(const DeviceStateTransition next) -> void { fDevice->ChangeState(fkDeviceStateTransitionMap.at(next)); } /// @brief Subscribe with a callback to device state changes /// @param subscriber id @@ -112,14 +114,14 @@ class PluginServices /// the state is running in. auto SubscribeToDeviceStateChange(const std::string& subscriber, std::function callback) -> void { - fDevice.SubscribeToStateChange(subscriber, [&,callback](FairMQDevice::State newState){ + fDevice->SubscribeToStateChange(subscriber, [&,callback](FairMQDevice::State newState){ callback(fkDeviceStateMap.at(newState)); }); } /// @brief Unsubscribe from device state changes /// @param subscriber id - auto UnsubscribeFromDeviceStateChange(const std::string& subscriber) -> void { fDevice.UnsubscribeFromStateChange(subscriber); } + auto UnsubscribeFromDeviceStateChange(const std::string& subscriber) -> void { fDevice->UnsubscribeFromStateChange(subscriber); } // Config API @@ -137,7 +139,7 @@ class PluginServices auto currentState = GetCurrentDeviceState(); if (currentState == DeviceState::InitializingDevice) { - fConfig.SetValue(key, val); + fConfig->SetValue(key, val); } else { @@ -153,14 +155,14 @@ class PluginServices /// TODO Currently, if a non-existing key is requested and a default constructed object is returned. /// This behaviour will be changed in the future to throw an exception in that case to provide a proper sentinel. template - auto GetProperty(const std::string& key) const -> T { return fConfig.GetValue(key); } + auto GetProperty(const std::string& key) const -> T { return fConfig->GetValue(key); } /// @brief Read config property as string /// @param key /// @return config property value converted to string /// /// If a type is not supported, the user can provide support by overloading the ostream operator for this type - auto GetPropertyAsString(const std::string& key) const -> std::string { return fConfig.GetStringValue(key); } + auto GetPropertyAsString(const std::string& key) const -> std::string { return fConfig->GetStringValue(key); } /// @brief Subscribe to property updates of type T /// @param subscriber @@ -175,31 +177,30 @@ class PluginServices // std::functionkey*/, const T /*newValue<])> callback // ) const -> void // { - // fConfig.Subscribe(subscriber, callback); + // fConfig->Subscribe(subscriber, callback); // } // // /// @brief Unsubscribe from property updates of type T // /// @param subscriber // template - // auto UnsubscribeFromPropertyChange(const std::string& subscriber) -> void { fConfig.Unsubscribe(subscriber); } + // auto UnsubscribeFromPropertyChange(const std::string& subscriber) -> void { fConfig->Unsubscribe(subscriber); } // // TODO Fix property subscription // TODO Property iterator static const std::unordered_map fkDeviceStateStrMap; - static const std::unordered_map fkStrDeviceStateMap; + static const std::unordered_map> fkStrDeviceStateMap; static const std::unordered_map fkDeviceStateTransitionStrMap; - static const std::unordered_map fkStrDeviceStateTransitionMap; - static const std::unordered_map fkDeviceStateMap; - static const std::unordered_map fkDeviceStateTransitionMap; + static const std::unordered_map> fkStrDeviceStateTransitionMap; + static const std::unordered_map> fkDeviceStateMap; + static const std::unordered_map> fkDeviceStateTransitionMap; private: - FairMQProgOptions& fConfig; - FairMQDevice& fDevice; + FairMQProgOptions* fConfig; // TODO make it a shared pointer, once old AliceO2 code is cleaned up + std::shared_ptr fDevice; }; /* class PluginServices */ - } /* namespace mq */ } /* namespace fair */ diff --git a/fairmq/Tools.h b/fairmq/Tools.h index 31aa9a38..9d04afce 100644 --- a/fairmq/Tools.h +++ b/fairmq/Tools.h @@ -13,6 +13,7 @@ #include #include #include +#include // IWYU pragma: end_exports #endif // FAIR_MQ_TOOLS_H diff --git a/fairmq/options/FairMQProgOptions.cxx b/fairmq/options/FairMQProgOptions.cxx index 10cee77e..c56949cb 100644 --- a/fairmq/options/FairMQProgOptions.cxx +++ b/fairmq/options/FairMQProgOptions.cxx @@ -37,7 +37,7 @@ FairMQProgOptions::~FairMQProgOptions() { } -void FairMQProgOptions::ParseAll(const int argc, const char** argv, bool allowUnregistered) +void FairMQProgOptions::ParseAll(const int argc, char const* const* argv, bool allowUnregistered) { // init description InitOptionDescription(); diff --git a/fairmq/options/FairMQProgOptions.h b/fairmq/options/FairMQProgOptions.h index 26cdc705..b24495e5 100644 --- a/fairmq/options/FairMQProgOptions.h +++ b/fairmq/options/FairMQProgOptions.h @@ -39,7 +39,7 @@ class FairMQProgOptions : public FairProgOptions , public FairMQEventManager // parse command line and txt/INI configuration file. // default parser for the mq-configuration file (JSON/XML) is called if command line key mq-config is called - virtual void ParseAll(const int argc, const char** argv, bool allowUnregistered = false); + virtual void ParseAll(const int argc, char const* const* argv, bool allowUnregistered = false); // external parser, store function template diff --git a/fairmq/options/FairProgOptions.cxx b/fairmq/options/FairProgOptions.cxx index 7d36985a..e8b52ec4 100644 --- a/fairmq/options/FairProgOptions.cxx +++ b/fairmq/options/FairProgOptions.cxx @@ -124,7 +124,7 @@ void FairProgOptions::UseConfigFile(const string& filename) /// ////////////////////////////////////////////////////////////////////////////////////////////////////// /// Parser -int FairProgOptions::ParseCmdLine(const int argc, const char** argv, const po::options_description& desc, po::variables_map& varmap, bool allowUnregistered) +int FairProgOptions::ParseCmdLine(const int argc, char const* const* argv, const po::options_description& desc, po::variables_map& varmap, bool allowUnregistered) { // get options from cmd line and store in variable map // here we use command_line_parser instead of parse_command_line, to allow unregistered and positional options @@ -151,7 +151,7 @@ int FairProgOptions::ParseCmdLine(const int argc, const char** argv, const po::o return 0; } -int FairProgOptions::ParseCmdLine(const int argc, const char** argv, const po::options_description& desc, bool allowUnregistered) +int FairProgOptions::ParseCmdLine(const int argc, char const* const* argv, const po::options_description& desc, bool allowUnregistered) { return ParseCmdLine(argc, argv, desc, fVarMap, allowUnregistered); } diff --git a/fairmq/options/FairProgOptions.h b/fairmq/options/FairProgOptions.h index 006931b2..18c60a04 100644 --- a/fairmq/options/FairProgOptions.h +++ b/fairmq/options/FairProgOptions.h @@ -151,8 +151,8 @@ class FairProgOptions const po::variables_map& GetVarMap() const { return fVarMap; } // boost prog options parsers - int ParseCmdLine(const int argc, const char** argv, const po::options_description& desc, po::variables_map& varmap, bool allowUnregistered = false); - int ParseCmdLine(const int argc, const char** argv, const po::options_description& desc, bool allowUnregistered = false); + int ParseCmdLine(const int argc, char const* const* argv, const po::options_description& desc, po::variables_map& varmap, bool allowUnregistered = false); + int ParseCmdLine(const int argc, char const* const* argv, const po::options_description& desc, bool allowUnregistered = false); int ParseCfgFile(const std::string& filename, const po::options_description& desc, po::variables_map& varmap, bool allowUnregistered = false); int ParseCfgFile(const std::string& filename, const po::options_description& desc, bool allowUnregistered = false); @@ -161,7 +161,7 @@ class FairProgOptions int ParseEnvironment(const std::function&); - virtual void ParseAll(const int argc, const char** argv, bool allowUnregistered = false) = 0;// TODO change return type to bool and propagate to executable + virtual void ParseAll(const int argc, char const* const* argv, bool allowUnregistered = false) = 0;// TODO change return type to bool and propagate to executable virtual int PrintOptions(); virtual int PrintOptionsRaw(); diff --git a/fairmq/runFairMQDevice.h b/fairmq/runFairMQDevice.h index 861023c1..a5f1a2c3 100644 --- a/fairmq/runFairMQDevice.h +++ b/fairmq/runFairMQDevice.h @@ -12,6 +12,7 @@ #include #include #include +#include template class GenericFairMQDevice : public FairMQDevice @@ -60,14 +61,14 @@ int main(int argc, const char** argv) config.ParseAll(argc, argv, true); - std::unique_ptr device(getDevice(config)); + std::shared_ptr device{getDevice(config)}; if (!device) { LOG(ERROR) << "getDevice(): no valid device provided. Exiting."; return 1; } - pluginManager->EmplacePluginServices(config, *device); + pluginManager->EmplacePluginServices(&config, device); pluginManager->InstantiatePlugins(); int result = runStateMachine(*device, config); diff --git a/fairmq/test/helper/plugins/dummy.h.in b/fairmq/test/helper/plugins/dummy.h.in index 0bbf34aa..2fb89415 100644 --- a/fairmq/test/helper/plugins/dummy.h.in +++ b/fairmq/test/helper/plugins/dummy.h.in @@ -31,7 +31,7 @@ class DummyPlugin : public fair::mq::Plugin const Version version, const std::string maintainer, const std::string homepage, - PluginServices& pluginServices) + PluginServices* pluginServices) : Plugin(name, version, maintainer, homepage, pluginServices) { SubscribeToDeviceStateChange( @@ -63,7 +63,6 @@ REGISTER_FAIRMQ_PLUGIN( "Mr. Dummy ", // Maintainer "https://git.test.net/dummy.git", // Homepage fair::mq::test::DummyPluginProgramOptions // Free function which declares custom program options for the plugin - // signature: () -> boost::optional ) } /* namespace test */ diff --git a/fairmq/test/helper/plugins/dummy2.h.in b/fairmq/test/helper/plugins/dummy2.h.in index 5ee3bfc4..46d812e6 100644 --- a/fairmq/test/helper/plugins/dummy2.h.in +++ b/fairmq/test/helper/plugins/dummy2.h.in @@ -22,7 +22,7 @@ class Dummy2Plugin : public fair::mq::Plugin { public: - Dummy2Plugin(const std::string name, const Version version, const std::string maintainer, const std::string homepage, PluginServices& pluginServices) + Dummy2Plugin(const std::string name, const Version version, const std::string maintainer, const std::string homepage, PluginServices* pluginServices) : Plugin(name, version, maintainer, homepage, pluginServices) { } diff --git a/fairmq/test/plugins/_plugin.cxx b/fairmq/test/plugins/_plugin.cxx index b4342519..4a9ab9ad 100644 --- a/fairmq/test/plugins/_plugin.cxx +++ b/fairmq/test/plugins/_plugin.cxx @@ -9,8 +9,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -21,27 +23,27 @@ namespace using namespace std; using namespace fair::mq; -auto control(FairMQDevice& device) -> void +auto control(shared_ptr device) -> void { - device.SetTransport("zeromq"); + device->SetTransport("zeromq"); for (const auto event : { FairMQDevice::INIT_DEVICE, FairMQDevice::RESET_DEVICE, FairMQDevice::END, }) { - device.ChangeState(event); - if (event != FairMQDevice::END) device.WaitForEndOfState(event); + device->ChangeState(event); + if (event != FairMQDevice::END) device->WaitForEndOfState(event); } } TEST(Plugin, Operators) { FairMQProgOptions config{}; - FairMQDevice device{}; - PluginServices services{config, device}; - auto p1 = Plugin{"dds", {1, 0, 0}, "Foo Bar ", "https://git.test.net/dds.git", services}; - auto p2 = Plugin{"dds", {1, 0, 0}, "Foo Bar ", "https://git.test.net/dds.git", services}; - auto p3 = Plugin{"file", {1, 0, 0}, "Foo Bar ", "https://git.test.net/file.git", services}; + auto device = make_shared(); + PluginServices services{&config, device}; + auto p1 = Plugin{"dds", {1, 0, 0}, "Foo Bar ", "https://git.test.net/dds.git", &services}; + auto p2 = Plugin{"dds", {1, 0, 0}, "Foo Bar ", "https://git.test.net/dds.git", &services}; + auto p3 = Plugin{"file", {1, 0, 0}, "Foo Bar ", "https://git.test.net/file.git", &services}; EXPECT_EQ(p1, p2); EXPECT_NE(p1, p3); control(device); @@ -50,9 +52,9 @@ TEST(Plugin, Operators) TEST(Plugin, OstreamOperators) { FairMQProgOptions config{}; - FairMQDevice device{}; - PluginServices services{config, device}; - auto p1 = Plugin{"dds", {1, 0, 0}, "Foo Bar ", "https://git.test.net/dds.git", services}; + auto device = make_shared(); + PluginServices services{&config, device}; + auto p1 = Plugin{"dds", {1, 0, 0}, "Foo Bar ", "https://git.test.net/dds.git", &services}; stringstream ss; ss << p1; EXPECT_EQ(ss.str(), string{"'dds', version '1.0.0', maintainer 'Foo Bar ', homepage 'https://git.test.net/dds.git'"}); @@ -61,9 +63,9 @@ TEST(Plugin, OstreamOperators) TEST(PluginVersion, Operators) { - struct Plugin::Version v1{1, 0, 0}; - struct Plugin::Version v2{1, 0, 0}; - struct Plugin::Version v3{1, 2, 0}; + struct fair::mq::tools::Version v1{1, 0, 0}; + struct fair::mq::tools::Version v2{1, 0, 0}; + struct fair::mq::tools::Version v3{1, 2, 0}; EXPECT_EQ(v1, v2); EXPECT_NE(v1, v3); EXPECT_GT(v3, v2); diff --git a/fairmq/test/plugins/_plugin_manager.cxx b/fairmq/test/plugins/_plugin_manager.cxx index 9988ea07..c1cdefc2 100644 --- a/fairmq/test/plugins/_plugin_manager.cxx +++ b/fairmq/test/plugins/_plugin_manager.cxx @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace @@ -23,25 +24,25 @@ using namespace boost::filesystem; using namespace boost::program_options; using namespace std; -auto control(FairMQDevice& device) -> void +auto control(shared_ptr device) -> void { - device.SetTransport("zeromq"); + device->SetTransport("zeromq"); for (const auto event : { FairMQDevice::INIT_DEVICE, FairMQDevice::RESET_DEVICE, FairMQDevice::END, }) { - device.ChangeState(event); - if (event != FairMQDevice::END) device.WaitForEndOfState(event); + device->ChangeState(event); + if (event != FairMQDevice::END) device->WaitForEndOfState(event); } } TEST(PluginManager, LoadPlugin) { FairMQProgOptions config{}; - FairMQDevice device{}; + auto device = make_shared(); auto mgr = PluginManager{}; - mgr.EmplacePluginServices(config, device); + mgr.EmplacePluginServices(&config, device); mgr.PrependSearchPath("./lib"); diff --git a/fairmq/tools/CppSTL.h b/fairmq/tools/CppSTL.h index dca7c700..ab10f64a 100644 --- a/fairmq/tools/CppSTL.h +++ b/fairmq/tools/CppSTL.h @@ -9,7 +9,9 @@ #ifndef FAIR_MQ_TOOLS_CPPSTL_H #define FAIR_MQ_TOOLS_CPPSTL_H +#include #include +#include namespace fair { @@ -25,6 +27,18 @@ std::unique_ptr make_unique(Args&& ...args) return std::unique_ptr(new T(std::forward(args)...)); } +// provide an enum hasher to compensate std::hash not supporting enums in C++11 +template +struct HashEnum +{ + auto operator()(const Enum& e) const noexcept + -> typename std::enable_if::value, std::size_t>::type + { + using _type = typename std::underlying_type::type; + return std::hash<_type>{}(static_cast<_type>(e)); + } +}; + } /* namespace tools */ } /* namespace mq */ } /* namespace fair */ diff --git a/fairmq/tools/FairMQTools.h b/fairmq/tools/FairMQTools.h index 5d7db60d..6c5fb1d1 100644 --- a/fairmq/tools/FairMQTools.h +++ b/fairmq/tools/FairMQTools.h @@ -6,6 +6,7 @@ #include #include #include +#include namespace FairMQ { @@ -13,6 +14,7 @@ namespace tools { using fair::mq::tools::make_unique; +using fair::mq::tools::HashEnum; using fair::mq::tools::getHostIPs; using fair::mq::tools::getInterfaceIP; @@ -20,6 +22,8 @@ using fair::mq::tools::getDefaultRouteNetworkInterface; using fair::mq::tools::S; +using fair::mq::tools::Version; + } // namespace tools } // namespace FairMQ diff --git a/fairmq/tools/Version.h b/fairmq/tools/Version.h new file mode 100644 index 00000000..53d3b37d --- /dev/null +++ b/fairmq/tools/Version.h @@ -0,0 +1,39 @@ +/******************************************************************************** + * Copyright (C) 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" * + ********************************************************************************/ + +#ifndef FAIR_MQ_TOOLS_VERSION_H +#define FAIR_MQ_TOOLS_VERSION_H + +#include +#include + +namespace fair +{ +namespace mq +{ +namespace tools +{ + +struct Version +{ + const int fkMajor, fkMinor, fkPatch; + + friend auto operator< (const Version& lhs, const Version& rhs) -> bool { return std::tie(lhs.fkMajor, lhs.fkMinor, lhs.fkPatch) < std::tie(rhs.fkMajor, rhs.fkMinor, rhs.fkPatch); } + friend auto operator> (const Version& lhs, const Version& rhs) -> bool { return rhs < lhs; } + friend auto operator<=(const Version& lhs, const Version& rhs) -> bool { return !(lhs > rhs); } + friend auto operator>=(const Version& lhs, const Version& rhs) -> bool { return !(lhs < rhs); } + friend auto operator==(const Version& lhs, const Version& rhs) -> bool { return std::tie(lhs.fkMajor, lhs.fkMinor, lhs.fkPatch) == std::tie(rhs.fkMajor, rhs.fkMinor, rhs.fkPatch); } + friend auto operator!=(const Version& lhs, const Version& rhs) -> bool { return !(lhs == rhs); } + friend auto operator<<(std::ostream& os, const Version& v) -> std::ostream& { return os << v.fkMajor << "." << v.fkMinor << "." << v.fkPatch; } +}; + +} /* namespace tools */ +} /* namespace mq */ +} /* namespace fair */ + +#endif /* FAIR_MQ_TOOLS_VERSION_H */