Skip to content

Source · fairmq/

ProgOptions.hpublic header

Defines class fair::mq::ProgOptions, struct fair::mq::PropertyNotFoundError.

Described in Configuration and properties, Threads in a device, 1-1: sampler and sink, qc: quality control on demand, Control a device from code, Command-line options, Logging.

fairmq/ProgOptions.h284 lines · C++API: ProgOptionsAPI: PropertyNotFoundErrorGitHub ↗
1/********************************************************************************2 * Copyright (C) 2014-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH  *3 *                                                                              *4 *              This software is distributed under the terms of the             *5 *              GNU Lesser General Public Licence (LGPL) version 3,             *6 *                  copied verbatim in the file "LICENSE"                       *7 ********************************************************************************/8 9#ifndef FAIR_MQ_PROGOPTIONS_H10#define FAIR_MQ_PROGOPTIONS_H11 12#include <boost/program_options.hpp>13#include <fairlogger/Logger.h>14#include <fairmq/Channel.h>15#include <fairmq/EventManager.h>16#include <fairmq/ProgOptionsFwd.h>17#include <fairmq/Properties.h>18#include <fairmq/tools/Strings.h>19#include <functional>20#include <map>21#include <mutex>22#include <stdexcept>23#include <string>24#include <unordered_map>25#include <vector>26 27namespace fair::mq28{29 30struct PropertyNotFoundError : std::runtime_error { using std::runtime_error::runtime_error; };31 32class ProgOptions33{34  public:35    ProgOptions();36    ProgOptions(const ProgOptions&) = delete;37    ProgOptions(ProgOptions&&) = delete;38    ProgOptions& operator=(const ProgOptions&) = delete;39    ProgOptions& operator=(ProgOptions&&) = delete;40    ~ProgOptions() = default;41 42    void ParseAll(const std::vector<std::string>& cmdArgs, bool allowUnregistered);43    void ParseAll(int argc, char const* const* argv, bool allowUnregistered = true);44    void Notify();45 46    void AddToCmdLineOptions(boost::program_options::options_description optDesc, bool visible = true);47    boost::program_options::options_description& GetCmdLineOptions();48 49    /// @brief Checks a property with the given key exist in the configuration50    /// @param key51    /// @return 1 if it exists, 0 otherwise52    int Count(const std::string& key) const;53 54    /// @brief Retrieve current channel information55    /// @return a map of <channel name, number of subchannels>56    std::unordered_map<std::string, int> GetChannelInfo() const;57    /// @brief Discover the list of property keys58    /// @return list of property keys59    std::vector<std::string> GetPropertyKeys() const;60 61    /// @brief Read config property, throw if no property with this key exists62    /// @param key63    /// @return config property64    template<typename T>65    T GetProperty(const std::string& key) const66    {67        std::lock_guard<std::mutex> lock(fMtx);68        if (fVarMap.count(key)) {69            return fVarMap[key].as<T>();70        } else {71            throw PropertyNotFoundError(fair::mq::tools::ToString("Config has no key: ", key));72        }73    }74 75    /// @brief Read config property, return provided value if no property with this key exists76    /// @param key77    /// @param ifNotFound value to return if key is not found78    /// @return config property79    template<typename T>80    T GetProperty(const std::string& key, const T& ifNotFound) const81    {82        std::lock_guard<std::mutex> lock(fMtx);83        if (fVarMap.count(key)) {84            return fVarMap[key].as<T>();85        }86        return ifNotFound;87    }88 89    /// @brief Read config property as string, throw if no property with this key exists90    /// @param key91    /// @return config property converted to string92    ///93    /// Supports conversion to string for a fixed set of types,94    /// for custom/unsupported types add them via `fair::mq::PropertyHelper::AddType<MyType>("optional label")`95    /// the provided type must then be convertible to string via operator<<96    std::string GetPropertyAsString(const std::string& key) const;97    /// @brief Read config property, return provided value if no property with this key exists98    /// @param key99    /// @param ifNotFound value to return if key is not found100    /// @return config property converted to string101    ///102    /// Supports conversion to string for a fixed set of types,103    /// for custom/unsupported types add them via `fair::mq::PropertyHelper::AddType<MyType>("optional label")`104    /// the provided type must then be convertible to string via operator<<105    std::string GetPropertyAsString(const std::string& key, const std::string& ifNotFound) const;106 107    /// @brief Read several config properties whose keys match the provided regular expression108    /// @param q regex string to match for109    /// @return container with properties (fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any)110    fair::mq::Properties GetProperties(const std::string& q) const;111    /// @brief Read several config properties whose keys start with the provided string112    /// @param q string to match for113    /// @return container with properties (fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any)114    ///115    /// Typically more performant than GetProperties with regex116    fair::mq::Properties GetPropertiesStartingWith(const std::string& q) const;117    /// @brief Read several config properties as string whose keys match the provided regular expression118    /// @param q regex string to match for119    /// @return container with properties (fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any)120    std::map<std::string, std::string> GetPropertiesAsString(const std::string& q) const;121    /// @brief Read several config properties as string whose keys start with the provided string122    /// @param q string to match for123    /// @return container with properties (fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any)124    ///125    /// Typically more performant than GetPropertiesAsString with regex126    std::map<std::string, std::string> GetPropertiesAsStringStartingWith(const std::string& q) const;127 128    /// @brief Set config property129    /// @param key130    /// @param val131    template<typename T>132    void SetProperty(const std::string& key, T val);133 134    /// @brief Updates an existing config property (or fails if it doesn't exist)135    /// @param key136    /// @param val137    template<typename T>138    bool UpdateProperty(const std::string& key, T val)139    {140        std::unique_lock<std::mutex> lock(fMtx);141 142        if (fVarMap.count(key)) {143            SetVarMapValue<typename std::decay<T>::type>(key, val);144 145            lock.unlock();146 147            fEvents.Emit<fair::mq::PropertyChange, typename std::decay<T>::type>(key, val);148            fEvents.Emit<fair::mq::PropertyChangeAsString, std::string>(key, GetPropertyAsString(key));149            return true;150        } else {151            LOG(debug) << "UpdateProperty failed, no property found with key '" << key << "'";152            return false;153        }154    }155 156    /// @brief Set multiple config properties157    /// @param props fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any158    void SetProperties(const fair::mq::Properties& input);159    /// @brief Updates multiple existing config properties (or fails of any of then do not exist, leaving property store unchanged)160    /// @param props (fair::mq::Properties as an alias for std::map<std::string, Property>, where property is boost::any)161    bool UpdateProperties(const fair::mq::Properties& input);162    /// @brief Deletes a property with the given key from the config store163    /// @param key164    void DeleteProperty(const std::string& key);165 166    /// @brief Takes the provided channel and creates properties based on it167    /// @param name channel name168    /// @param channel FairMQChannel reference169    void AddChannel(const std::string& name, const Channel& channel);170 171    /// @brief Subscribe to property updates of type T172    /// @param subscriber173    /// @param callback function174    ///175    /// Subscribe to property changes with a callback to monitor property changes in an event based fashion.176    template<typename T>177    void Subscribe(const std::string& subscriber, std::function<void(typename fair::mq::PropertyChange::KeyType, T)> func) const178    {179        std::lock_guard<std::mutex> lock(fMtx);180        static_assert(!std::is_same<T,const char*>::value || !std::is_same<T, char*>::value,181            "In template member ProgOptions::Subscribe<T>(key,Lambda) the types const char* or char* for the calback signatures are not supported.");182        fEvents.Subscribe<fair::mq::PropertyChange, T>(subscriber, func);183    }184 185    /// @brief Unsubscribe from property updates of type T186    /// @param subscriber187    template<typename T>188    void Unsubscribe(const std::string& subscriber) const189    {190        std::lock_guard<std::mutex> lock(fMtx);191        fEvents.Unsubscribe<fair::mq::PropertyChange, T>(subscriber);192    }193 194    /// @brief Subscribe to property updates, with values converted to string195    /// @param subscriber196    /// @param callback function197    ///198    /// Subscribe to property changes with a callback to monitor property changes in an event based fashion. Will convert the property to string.199    void SubscribeAsString(const std::string& subscriber, std::function<void(typename fair::mq::PropertyChange::KeyType, std::string)> func) const200    {201        std::lock_guard<std::mutex> lock(fMtx);202        fEvents.Subscribe<fair::mq::PropertyChangeAsString, std::string>(subscriber, func);203    }204 205    /// @brief Unsubscribe from property updates that convert to string206    /// @param subscriber207    void UnsubscribeAsString(const std::string& subscriber) const208    {209        std::lock_guard<std::mutex> lock(fMtx);210        fEvents.Unsubscribe<fair::mq::PropertyChangeAsString, std::string>(subscriber);211    }212 213    /// @brief prints full options description214    void PrintHelp() const;215    /// @brief prints properties stored in the property container216    void PrintOptions() const;217    /// @brief prints full options description in a compact machine-readable format218    void PrintOptionsRaw() const;219 220    /// @brief returns the property container221    const boost::program_options::variables_map& GetVarMap() const222    {223        std::lock_guard<std::mutex> lock(fMtx);224        return fVarMap;225    }226 227    /// @brief Read config property, return default-constructed object if key doesn't exist228    /// @param key229    /// @return config property230    template<typename T>231    T GetValue(const std::string& key) const /* TODO: deprecate this */232    {233        std::lock_guard<std::mutex> lock(fMtx);234        if (fVarMap.count(key)) {235            return fVarMap[key].as<T>();236        } else {237            LOG(warn) << "Config has no key: " << key << ". Returning default constructed object.";238            return T();239        }240    }241    template<typename T>242    int SetValue(const std::string& key, T val) /* TODO: deprecate this */ { SetProperty(key, val); return 0; }243    /// @brief Read config property as string, return default-constructed object if key doesn't exist244    /// @param key245    /// @return config property246    std::string GetStringValue(const std::string& key) const; /* TODO: deprecate this */247 248  private:249    void ParseDefaults();250    std::unordered_map<std::string, int> GetChannelInfoImpl() const;251 252    template<typename T>253    void SetVarMapValue(const std::string& key, const T& val)254    {255        std::map<std::string, boost::program_options::variable_value>& vm = fVarMap;256        vm[key].value() = boost::any(val);257    }258 259    boost::program_options::variables_map fVarMap; ///< options container260    boost::program_options::options_description fAllOptions; ///< all options descriptions261    std::vector<std::string> fUnregisteredOptions; ///< container with unregistered options262 263    mutable fair::mq::EventManager fEvents;264    mutable std::mutex fMtx;265};266 267} // namespace fair::mq268template <typename T>269void fair::mq::ProgOptions::SetProperty(const std::string& key, T val)270{271    std::unique_lock<std::mutex> lock(fMtx);272 273    SetVarMapValue<typename std::decay<T>::type>(key, val);274 275    lock.unlock();276 277    fEvents.Emit<fair::mq::PropertyChange, typename std::decay<T>::type>(key, val);278    fEvents.Emit<fair::mq::PropertyChangeAsString, std::string>(key, GetPropertyAsString(key));279}280 281extern template void fair::mq::ProgOptions::SetProperty<int>(const std::string& key, int val);282extern template void fair::mq::ProgOptions::SetProperty<std::string>(const std::string& key, std::string val);283 284#endif /* FAIR_MQ_PROGOPTIONS_H */