FairMQ  1.3.7
C++ Message Passing Framework
FairMQProgOptions.h
1 /********************************************************************************
2  * Copyright (C) 2014-2018 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 FAIRMQPROGOPTIONS_H
10 #define FAIRMQPROGOPTIONS_H
11 
12 #include <fairmq/EventManager.h>
13 #include "FairMQLogger.h"
14 #include "FairMQChannel.h"
15 #include <fairmq/Tools.h>
16 
17 #include <boost/program_options.hpp>
18 
19 #include <unordered_map>
20 #include <functional>
21 #include <string>
22 #include <vector>
23 #include <mutex>
24 #include <sstream>
25 
26 namespace fair
27 {
28 namespace mq
29 {
30 
31 struct PropertyChange : Event<std::string> {};
32 struct PropertyChangeAsString : Event<std::string> {};
33 
34 } /* namespace mq */
35 } /* namespace fair */
36 
38 {
39  private:
40  using FairMQChannelMap = std::unordered_map<std::string, std::vector<FairMQChannel>>;
41 
42  public:
44  virtual ~FairMQProgOptions();
45 
46  int ParseAll(const std::vector<std::string>& cmdLineArgs, bool allowUnregistered);
47  // parse command line.
48  // default parser for the mq-configuration file (JSON) is called if command line key mq-config is called
49  int ParseAll(const int argc, char const* const* argv, bool allowUnregistered = true);
50 
51  FairMQChannelMap GetFairMQMap() const;
52  std::unordered_map<std::string, int> GetChannelInfo() const;
53 
54  template<typename T>
55  int SetValue(const std::string& key, T val)
56  {
57  std::unique_lock<std::mutex> lock(fConfigMutex);
58 
59  // update variable map
60  UpdateVarMap<typename std::decay<T>::type>(key, val);
61 
62  if (key == "channel-config")
63  {
64  ParseChannelsFromCmdLine();
65  }
66  else if (fChannelKeyMap.count(key))
67  {
68  UpdateChannelValue(fChannelKeyMap.at(key).channel, fChannelKeyMap.at(key).index, fChannelKeyMap.at(key).member, val);
69  }
70 
71  lock.unlock();
72 
73  //if (std::is_same<T, int>::value || std::is_same<T, std::string>::value)//if one wants to restrict type
74  fEvents.Emit<fair::mq::PropertyChange, typename std::decay<T>::type>(key, val);
75  fEvents.Emit<fair::mq::PropertyChangeAsString, std::string>(key, GetStringValue(key));
76 
77  return 0;
78  }
79 
80  template <typename T>
81  void Subscribe(const std::string& subscriber, std::function<void(typename fair::mq::PropertyChange::KeyType, T)> func)
82  {
83  std::unique_lock<std::mutex> lock(fConfigMutex);
84 
85  static_assert(!std::is_same<T,const char*>::value || !std::is_same<T, char*>::value,
86  "In template member FairMQProgOptions::Subscribe<T>(key,Lambda) the types const char* or char* for the calback signatures are not supported.");
87 
88  fEvents.Subscribe<fair::mq::PropertyChange, T>(subscriber, func);
89  }
90 
91  template <typename T>
92  void Unsubscribe(const std::string& subscriber)
93  {
94  std::unique_lock<std::mutex> lock(fConfigMutex);
95 
96  fEvents.Unsubscribe<fair::mq::PropertyChange, T>(subscriber);
97  }
98 
99  void SubscribeAsString(const std::string& subscriber, std::function<void(typename fair::mq::PropertyChange::KeyType, std::string)> func)
100  {
101  std::unique_lock<std::mutex> lock(fConfigMutex);
102 
103  fEvents.Subscribe<fair::mq::PropertyChangeAsString, std::string>(subscriber, func);
104  }
105 
106  void UnsubscribeAsString(const std::string& subscriber)
107  {
108  std::unique_lock<std::mutex> lock(fConfigMutex);
109 
110  fEvents.Unsubscribe<fair::mq::PropertyChangeAsString, std::string>(subscriber);
111  }
112 
113  std::vector<std::string> GetPropertyKeys() const;
114 
115  // get value corresponding to the key
116  template<typename T>
117  T GetValue(const std::string& key) const
118  {
119  std::unique_lock<std::mutex> lock(fConfigMutex);
120 
121  T val = T();
122 
123  if (fVarMap.count(key))
124  {
125  val = fVarMap[key].as<T>();
126  }
127  else
128  {
129  LOG(warn) << "Config has no key: " << key << ". Returning default constructed object.";
130  }
131 
132  return val;
133  }
134 
135  // Given a key, convert the variable value to string
136  std::string GetStringValue(const std::string& key);
137 
138  int Count(const std::string& key) const;
139 
140  template<typename T>
141  T ConvertTo(const std::string& strValue)
142  {
143  if (std::is_arithmetic<T>::value)
144  {
145  std::istringstream iss(strValue);
146  T val;
147  iss >> val;
148  return val;
149  }
150  else
151  {
152  LOG(error) << "the provided string " << strValue << " cannot be converted to the requested type. The target type must be arithmetic type.";
153  }
154  }
155 
156  // add options_description
157  int AddToCmdLineOptions(const boost::program_options::options_description optDesc, bool visible = true);
158  boost::program_options::options_description& GetCmdLineOptions();
159 
160  const boost::program_options::variables_map& GetVarMap() const { return fVarMap; }
161 
162  int PrintOptions();
163  int PrintOptionsRaw();
164 
165  void AddChannel(const std::string& channelName, const FairMQChannel& channel)
166  {
167  fFairMQChannelMap[channelName].push_back(channel);
168  }
169 
170  private:
171  struct ChannelKey
172  {
173  std::string channel;
174  int index;
175  std::string member;
176  };
177 
178  boost::program_options::variables_map fVarMap;
179  FairMQChannelMap fFairMQChannelMap;
180 
181  boost::program_options::options_description fAllOptions;
182  boost::program_options::options_description fGeneralOptions;
183  boost::program_options::options_description fMQOptions;
184  boost::program_options::options_description fParserOptions;
185 
186  mutable std::mutex fConfigMutex;
187 
188  std::unordered_map<std::string, int> fChannelInfo;
189  std::unordered_map<std::string, ChannelKey> fChannelKeyMap;// key=full path - val=key info
190  std::vector<std::string> fUnregisteredOptions;
191 
192  fair::mq::EventManager fEvents;
193 
194  void ParseCmdLine(const int argc, char const* const* argv, bool allowUnregistered = true);
195  void ParseDefaults();
196 
197  // read FairMQChannelMap and insert/update corresponding values in variable map
198  // create key for variable map as follow : channelName.index.memberName
199  void UpdateMQValues();
200  int Store(const FairMQChannelMap& channels);
201 
202  template<typename T>
203  void EmitUpdate(const std::string& key, T val)
204  {
205  // compile time check whether T is const char* or char*, and in that case a compile time error is thrown.
206  static_assert(!std::is_same<T,const char*>::value || !std::is_same<T, char*>::value,
207  "In template member FairMQProgOptions::EmitUpdate<T>(key,val) the types const char* or char* for the calback signatures are not supported.");
208  fEvents.Emit<fair::mq::PropertyChange, T>(key, val);
209  fEvents.Emit<fair::mq::PropertyChangeAsString, std::string>(key, GetStringValue(key));
210  }
211 
212  int UpdateChannelMap(const FairMQChannelMap& map);
213  template<typename T>
214  int UpdateChannelValue(const std::string&, int, const std::string&, T)
215  {
216  LOG(error) << "update of FairMQChannel map failed, because value type not supported";
217  return 1;
218  }
219  int UpdateChannelValue(const std::string& channelName, int index, const std::string& member, const std::string& val);
220  int UpdateChannelValue(const std::string& channelName, int index, const std::string& member, int val);
221  int UpdateChannelValue(const std::string& channelName, int index, const std::string& member, bool val);
222 
223  void UpdateChannelInfo();
224 
225  // helper to modify the value of variable map after calling boost::program_options::store
226  template<typename T>
227  void UpdateVarMap(const std::string& key, const T& val)
228  {
229  std::map<std::string, boost::program_options::variable_value>& vm = fVarMap;
230  vm[key].value() = boost::any(val);
231  }
232 
233  void ParseChannelsFromCmdLine();
234 };
235 
236 #endif /* FAIRMQPROGOPTIONS_H */
Definition: EventManager.h:33
Manages event callbacks from different subscribers.
Definition: EventManager.h:53
Definition: FairMQChannel.h:27
Definition: FairMQProgOptions.h:37
Definition: FairMQProgOptions.h:32
Tools for interfacing containers to the transport via polymorphic allocators.
Definition: DeviceRunner.h:23
Definition: FairMQProgOptions.h:31

privacy