/******************************************************************************** * Copyright (C) 2014-2018 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 FAIRMQPROGOPTIONS_H #define FAIRMQPROGOPTIONS_H #include #include "FairMQLogger.h" #include "FairMQChannel.h" #include "Properties.h" #include #include #include #include #include #include #include #include #include #include #include #include #include // pair #include namespace fair { namespace mq { struct PropertyChange : Event {}; struct PropertyChangeAsString : Event {}; } /* namespace mq */ } /* namespace fair */ class FairMQProgOptions { public: FairMQProgOptions(); virtual ~FairMQProgOptions() {} struct PropertyNotFoundException : std::runtime_error { using std::runtime_error::runtime_error; }; int ParseAll(const std::vector& cmdArgs, bool allowUnregistered); int ParseAll(const int argc, char const* const* argv, bool allowUnregistered = true); std::unordered_map GetChannelInfo() const; std::vector GetPropertyKeys() const; template T GetProperty(const std::string& key) const { std::lock_guard lock(fMtx); if (fVarMap.count(key)) { return fVarMap[key].as(); } throw PropertyNotFoundException(fair::mq::tools::ToString("Config has no key: ", key)); } template T GetProperty(const std::string& key, const T& ifNotFound) const { std::lock_guard lock(fMtx); if (fVarMap.count(key)) { return fVarMap[key].as(); } return ifNotFound; } fair::mq::Properties GetProperties(const std::string& q) const; std::map GetPropertiesAsString(const std::string& q) const; fair::mq::Properties GetPropertiesStartingWith(const std::string& q) const; template T GetValue(const std::string& key) const // TODO: deprecate this { return GetProperty(key); } std::string GetPropertyAsString(const std::string& key) const; std::string GetStringValue(const std::string& key) const // TODO: deprecate this { return GetPropertyAsString(key); } template void SetProperty(const std::string& key, T val) { std::unique_lock lock(fMtx); SetVarMapValue::type>(key, val); if (key == "channel-config") { ParseChannelsFromCmdLine(); } lock.unlock(); fEvents.Emit::type>(key, val); fEvents.Emit(key, GetStringValue(key)); } template int SetValue(const std::string& key, T val) // TODO: deprecate this { SetProperty(key, val); return 0; } void SetProperties(const fair::mq::Properties& input); void DeleteProperty(const std::string& key); template void Subscribe(const std::string& subscriber, std::function func) const { std::lock_guard lock(fMtx); static_assert(!std::is_same::value || !std::is_same::value, "In template member FairMQProgOptions::Subscribe(key,Lambda) the types const char* or char* for the calback signatures are not supported."); fEvents.Subscribe(subscriber, func); } template void Unsubscribe(const std::string& subscriber) const { std::lock_guard lock(fMtx); fEvents.Unsubscribe(subscriber); } void SubscribeAsString(const std::string& subscriber, std::function func) const { std::lock_guard lock(fMtx); fEvents.Subscribe(subscriber, func); } void UnsubscribeAsString(const std::string& subscriber) const { std::lock_guard lock(fMtx); fEvents.Unsubscribe(subscriber); } int Count(const std::string& key) const; // add options_description int AddToCmdLineOptions(const boost::program_options::options_description optDesc, bool visible = true); boost::program_options::options_description& GetCmdLineOptions(); int PrintOptions(); int PrintOptionsRaw(); void AddChannel(const std::string& name, const FairMQChannel& channel); template static void AddType(std::string label = "") { if (label == "") { label = boost::core::demangle(typeid(T).name()); } fTypeInfos[std::type_index(typeid(T))] = [label](const fair::mq::Property& p) { std::stringstream ss; ss << boost::any_cast(p); return std::pair{ss.str(), label}; }; } static std::unordered_map(const fair::mq::Property&)>> fTypeInfos; static std::unordered_map fEventEmitters; private: boost::program_options::variables_map fVarMap; ///< options container boost::program_options::options_description fAllOptions; ///< all options descriptions boost::program_options::options_description fGeneralOptions; ///< general options descriptions boost::program_options::options_description fMQOptions; ///< MQ options descriptions boost::program_options::options_description fParserOptions; ///< MQ Parser options descriptions mutable std::mutex fMtx; std::vector fUnregisteredOptions; ///< container with unregistered options mutable fair::mq::EventManager fEvents; void ParseCmdLine(const int argc, char const* const* argv, bool allowUnregistered = true); void ParseDefaults(); std::unordered_map GetChannelInfoImpl() const; // modify the value of variable map after calling boost::program_options::store template void SetVarMapValue(const std::string& key, const T& val) { std::map& vm = fVarMap; vm[key].value() = boost::any(val); } void ParseChannelsFromCmdLine(); }; #endif /* FAIRMQPROGOPTIONS_H */