JayBeams  0.1
Another project to have fun coding.
configuration.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  *
4  * This is an example of how to create and use configuration objects in
5  * JayBeams.
6  */
7 #include <jb/config_object.hpp>
8 #include <jb/strtonum.hpp>
9 
10 #include <iostream>
11 
12 // ... creating configuration components takes very little boiler
13 // plate code... first your class must derive from config_object:
14 /// A configuration class for threads
16 public:
17  // ... you must describe how the attributes are mapped to
18  // names, if you want you can set the default value ...
20  : name(desc("name"), this, "")
21  , scheduler(desc("scheduler"), this, "OTHER")
22  , priority(desc("priority"), this, "MIN")
23  , affinity(desc("affinity"), this, ~0) {
24  }
25  // ... this makes your class behave like a canonical object, i.e.,
26  // it has copy constructor, move constructor, and the corresponding
27  // assighment operators ...
29 
30  // ... all your attributes are defined as elements next ...
34  // ... you can use different types ...
36 
37  // ... you can add convenience functions to make the configuration
38  // class easier to use ...
39  int native_scheduling_policy() const;
40  int native_priority() const;
41 };
42 
43 // ... config objects can be composed ...
44 /// A configuration class for a worker with two threads.
46 public:
47  // ... the description of the attributes can include a help
48  // message, as well as a "class", allowing you to change all the
49  // attributes with that class in a single configuration section
50  // (more on this later) ...
52  : cl_device_name(
53  desc("cl-device-name")
54  .help("The name of the CL device used by this worker"),
55  this)
56  , reader(desc("reader", "thread_config"), this)
57  , writer(desc("writer", "thread_config"), this) {
58  }
60 
62  // ... just create an attribute that holds a config object ...
65 };
66 
67 // ... the composition can be arbitrarily deeep ...
68 /// The main configuration class for this example program.
70 public:
72  : securities(
73  desc("securities").help("The list of securities to process"), this)
74  , workers(desc("workers", "worker_config"), this) {
75  }
76 
77  // ... notice how we can have lists (or vectors) of attributes ...
80 };
81 
82 int main(int argc, char* argv[]) try {
83  // ... to use your configuration just create one, it is initialized
84  // to whatever defaults you defined ...
85  program_config config;
86 
87  // ... you can change parts of the configuration programatically ...
88  std::vector<worker_config> v;
89  v.push_back(std::move(worker_config().cl_device_name("Tahiti")));
90  config.workers(std::move(v));
91 
92  // ... and/or load the rest from a configuration file ...
93  config.load_overrides(argc, argv, "my_program.yaml", "MY_PROGRAM_ROOT");
94 
95  // ... and then access them as usual ...
96  std::cout << "securities = [";
97  char const* sep = "";
98  for (auto s : config.securities()) {
99  std::cout << sep << s;
100  sep = ", ";
101  }
102  std::cout << "]\n";
103  int cnt = 0;
104  for (auto w : config.workers()) {
105  std::cout << "worker." << cnt << ".cl-device-name = " << w.cl_device_name()
106  << std::endl;
107  cnt++;
108  }
109 
110  return 0;
111 } catch (jb::usage const& ex) {
112  std::cerr << ex.what() << std::endl;
113  return ex.exit_status();
114 } catch (std::exception const& ex) {
115  std::cerr << "standard exception raised: " << ex.what() << std::endl;
116  return 1;
117 } catch (...) {
118  std::cerr << "unknown exception raised" << std::endl;
119  return 1;
120 }
121 
123  if (scheduler() == "RR") {
124  return SCHED_RR;
125  }
126  if (scheduler() == "FIFO") {
127  return SCHED_FIFO;
128  }
129  if (scheduler() == "OTHER") {
130  return SCHED_OTHER;
131  }
132  if (scheduler() == "BATCH") {
133  return SCHED_BATCH;
134  }
135  if (scheduler() == "IDLE") {
136  return SCHED_IDLE;
137  }
138  std::string msg("Unknown scheduling policy: ");
139  msg += scheduler();
140  throw std::runtime_error(msg);
141 }
142 
144  int policy = native_scheduling_policy();
145  if (priority() == "MIN") {
146  return sched_get_priority_min(policy);
147  }
148  if (priority() == "MAX") {
149  return sched_get_priority_max(policy);
150  }
151  if (priority() == "MID") {
152  return (sched_get_priority_max(policy) + sched_get_priority_min(policy)) /
153  2;
154  }
155  int prio;
156  if (jb::strtonum(priority(), prio)) {
157  return prio;
158  }
159  std::string msg("Invalid scheduling priority: ");
160  msg += priority();
161  throw std::runtime_error(msg);
162 }
The main configuration class for this example program.
Base class for all configuration objects.
int exit_status() const
Definition: usage.hpp:21
jb::config_attribute< worker_config, std::string > cl_device_name
A configuration class for a worker with two threads.
jb::config_attribute< thread_config, std::string > scheduler
config_object_constructors(thread_config)
int native_scheduling_policy() const
jb::config_attribute< program_config, std::vector< worker_config > > workers
A configuration class for threads.
void load_overrides(int &argc, char *argv[], std::string const &filename, char const *environment_variable_name)
Read the configuration file and load the overrides defined therein.
int native_priority() const
jb::config_attribute< worker_config, thread_config > writer
int main(int argc, char *argv[])
jb::config_attribute< thread_config, std::string > name
jb::config_attribute< worker_config, thread_config > reader
bool strtonum(std::string const &s, T &r)
Generic string to number conversion with validation.
Definition: strtonum.hpp:40
A simple class to communicate the result of parsing the options.
Definition: usage.hpp:11
static attribute_descriptor desc(std::string const &name)
Convenience function to create attribute descriptors with less typing.
jb::config_attribute< thread_config, std::string > priority
jb::config_attribute< program_config, std::vector< std::string > > securities
jb::config_attribute< thread_config, int > affinity