Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
application.hpp
Go to the documentation of this file.
1#pragma once
2#include <appbase/plugin.hpp>
3#include <appbase/channel.hpp>
4#include <appbase/method.hpp>
6#include <boost/filesystem/path.hpp>
7#include <boost/core/demangle.hpp>
8#include <typeindex>
9
10namespace appbase {
11 namespace bpo = boost::program_options;
12 namespace bfs = boost::filesystem;
13
14 using config_comparison_f = std::function<bool(const boost::any& a, const boost::any& b)>;
15
17 {
18 public:
20
21
31 uint64_t version() const;
36 string version_string() const;
39 void set_version_string(std::string v);
44 string full_version_string() const;
47 void set_full_version_string(std::string v);
53 void set_default_data_dir(const bfs::path& data_dir = "data-dir");
58 bfs::path data_dir() const;
64 void set_default_config_dir(const bfs::path& config_dir = "etc");
69 bfs::path config_dir() const;
74 bfs::path get_logging_conf() const;
80 bfs::path full_config_file_path() const;
90 void set_sighup_callback(std::function<void()> callback);
98 template<typename... Plugin>
99 bool initialize(int argc, char** argv) {
100 return initialize_impl(argc, argv, {find_plugin<Plugin>()...});
101 }
102
103 void startup();
104 void shutdown();
105
110 void exec();
111 void quit();
112
117 bool is_quiting()const;
118
123 template <typename T> void register_config_type() {
124 register_config_type_comparison(typeid(T), [](const auto& a, const auto& b) {
125 return boost::any_cast<const T&>(a) == boost::any_cast<const T&>(b);
126 });
127 }
128 void register_config_type_comparison(std::type_index, config_comparison_f comp);
129
130 static application& instance();
131
132 abstract_plugin* find_plugin(const string& name)const;
133 abstract_plugin& get_plugin(const string& name)const;
134
135 template<typename Plugin>
137 auto existing = find_plugin<Plugin>();
138 if(existing)
139 return *existing;
140
141 auto plug = new Plugin();
142 plugins[plug->name()].reset(plug);
143 plug->register_dependencies();
144 return *plug;
145 }
146
147 template<typename Plugin>
148 Plugin* find_plugin()const {
149 string name = boost::core::demangle(typeid(Plugin).name());
150 return dynamic_cast<Plugin*>(find_plugin(name));
151 }
152
153 template<typename Plugin>
154 Plugin& get_plugin()const {
155 auto ptr = find_plugin<Plugin>();
156 return *ptr;
157 }
158
166 template<typename MethodDecl>
167 auto get_method() -> std::enable_if_t<is_method_decl<MethodDecl>::value, typename MethodDecl::method_type&>
168 {
169 using method_type = typename MethodDecl::method_type;
170 auto key = std::type_index(typeid(MethodDecl));
171 auto itr = methods.find(key);
172 if(itr != methods.end()) {
173 return *method_type::get_method(itr->second);
174 } else {
175 methods.emplace(std::make_pair(key, method_type::make_unique()));
176 return *method_type::get_method(methods.at(key));
177 }
178 }
179
187 template<typename ChannelDecl>
188 auto get_channel() -> std::enable_if_t<is_channel_decl<ChannelDecl>::value, typename ChannelDecl::channel_type&>
189 {
190 using channel_type = typename ChannelDecl::channel_type;
191 auto key = std::type_index(typeid(ChannelDecl));
192 auto itr = channels.find(key);
193 if(itr != channels.end()) {
194 return *channel_type::get_channel(itr->second);
195 } else {
196 channels.emplace(std::make_pair(key, channel_type::make_unique()));
197 return *channel_type::get_channel(channels.at(key));
198 }
199 }
200
205 boost::asio::io_service& get_io_service() { return *io_serv; }
206
214 template <typename Func>
215 auto post( int priority, Func&& func ) {
216 return boost::asio::post(*io_serv, pri_queue.wrap(priority, std::forward<Func>(func)));
217 }
218
228 return pri_queue;
229 }
230
231 const bpo::variables_map& get_options() const;
232
238
239 protected:
240 template<typename Impl>
241 friend class plugin;
242
243 bool initialize_impl(int argc, char** argv, vector<abstract_plugin*> autostart_plugins);
244
249 void plugin_initialized(abstract_plugin& plug){ initialized_plugins.push_back(&plug); }
250 void plugin_started(abstract_plugin& plug){ running_plugins.push_back(&plug); }
252
253 private:
254 application();
255 map<string, std::unique_ptr<abstract_plugin>> plugins;
256 vector<abstract_plugin*> initialized_plugins;
257 vector<abstract_plugin*> running_plugins;
258
259 std::function<void()> sighup_callback;
260 map<std::type_index, erased_method_ptr> methods;
261 map<std::type_index, erased_channel_ptr> channels;
262
263 std::shared_ptr<boost::asio::io_service> io_serv;
264 execution_priority_queue pri_queue;
265
266 void start_sighup_handler( std::shared_ptr<boost::asio::signal_set> sighup_set );
267 void set_program_options();
268 void write_default_config(const bfs::path& cfg_file);
269 void print_default_config(std::ostream& os);
270
271 void wait_for_signal(std::shared_ptr<boost::asio::signal_set> ss);
272 void setup_signal_handling_on_ios(boost::asio::io_service& ios, bool startup);
273
274 std::unique_ptr<class application_impl> my;
275
276 };
277
278 application& app();
279
280
281 template<typename Impl>
282 class plugin : public abstract_plugin {
283 public:
284 plugin():_name(boost::core::demangle(typeid(Impl).name())){}
285 virtual ~plugin(){}
286
287 virtual state get_state()const override { return _state; }
288 virtual const std::string& name()const override { return _name; }
289
290 virtual void register_dependencies() {
291 static_cast<Impl*>(this)->plugin_requires([&](auto& plug){});
292 }
293
294 virtual void initialize(const variables_map& options) override {
295 if(_state == registered) {
296 _state = initialized;
297 static_cast<Impl*>(this)->plugin_requires([&](auto& plug){ plug.initialize(options); });
298 static_cast<Impl*>(this)->plugin_initialize(options);
299 //ilog( "initializing plugin ${name}", ("name",name()) );
300 app().plugin_initialized(*this);
301 }
302 assert(_state == initialized);
303 }
304
305 virtual void handle_sighup() override {
306 }
307
308 virtual void startup() override {
309 if(_state == initialized) {
310 _state = started;
311 static_cast<Impl*>(this)->plugin_requires([&](auto& plug){ plug.startup(); });
312 static_cast<Impl*>(this)->plugin_startup();
313 app().plugin_started(*this);
314 }
315 assert(_state == started); // if initial state was not initialized, final state cannot be started
316 }
317
318 virtual void shutdown() override {
319 if(_state == started) {
320 _state = stopped;
321 //ilog( "shutting down plugin ${name}", ("name",name()) );
322 static_cast<Impl*>(this)->plugin_shutdown();
323 }
324 }
325
326 protected:
327 plugin(const string& name) : _name(name){}
328
329 private:
331 std::string _name;
332 };
333
334 template<typename Data, typename DispatchPolicy>
336 if (has_subscribers()) {
337 // this will copy data into the lambda
338 app().post( priority, [this, data]() {
339 _signal(data);
340 });
341 }
342 }
343
344}
std::string name
@ stopped
the plugin is no longer running
Definition plugin.hpp:34
@ started
the plugin is actively running
Definition plugin.hpp:33
@ initialized
the plugin has initialized any state required but is idle
Definition plugin.hpp:32
@ registered
the plugin is constructed but doesn't do anything
Definition plugin.hpp:31
void plugin_initialized(abstract_plugin &plug)
const bpo::variables_map & get_options() const
void set_version_string(std::string v)
User provided version string for version_string() which overrides git describe value.
void set_version(uint64_t version)
Set version.
bool initialize(int argc, char **argv)
Looks for the –plugin commandline / config option and calls initialize on those plugins.
void set_default_config_dir(const bfs::path &config_dir="etc")
Set default config directory.
bfs::path data_dir() const
Get data directory.
bfs::path full_config_file_path() const
Get full config.ini path.
void register_config_type_comparison(std::type_index, config_comparison_f comp)
void set_sighup_callback(std::function< void()> callback)
Set function pointer invoked on receipt of SIGHUP.
auto post(int priority, Func &&func)
string version_string() const
Get version string; generated from git describe if available.
auto get_method() -> std::enable_if_t< is_method_decl< MethodDecl >::value, typename MethodDecl::method_type & >
boost::asio::io_service & get_io_service()
bfs::path get_logging_conf() const
Get logging configuration path.
bfs::path config_dir() const
Get config directory.
Plugin & get_plugin() const
bool is_quiting() const
string full_version_string() const
Get full version string; same as version_string() unless set differently.
static application & instance()
auto get_channel() -> std::enable_if_t< is_channel_decl< ChannelDecl >::value, typename ChannelDecl::channel_type & >
void plugin_started(abstract_plugin &plug)
Plugin * find_plugin() const
bool initialize_impl(int argc, char **argv, vector< abstract_plugin * > autostart_plugins)
uint64_t version() const
Get version.
void set_full_version_string(std::string v)
User provided full version string for full_version_string()
void set_default_data_dir(const bfs::path &data_dir="data-dir")
Set default data directory.
void publish(int priority, const Data &data)
boost::asio::executor_binder< Function, executor > wrap(int priority, Function &&func)
virtual void startup() override
virtual void shutdown() override
virtual const std::string & name() const override
plugin(const string &name)
virtual void register_dependencies()
virtual state get_state() const override
virtual void handle_sighup() override
virtual void initialize(const variables_map &options) override
os_t os
char ** argv
std::function< bool(const boost::any &a, const boost::any &b)> config_comparison_f
application & app()
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
#define T(meth, val, expected)
void write_default_config(const bfs::path &cfg_file, const options_description &cfg)
Definition main.cpp:1941
unsigned __int64 uint64_t
Definition stdint.h:136
Definition zm2.cpp:48