forked from pboettch/cxx_argp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cxx_argp_application.h
104 lines (84 loc) · 2.51 KB
/
cxx_argp_application.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Header-only, modern C++ main-application-class using
// an arguemnt-parser based on ARGP
//
// Copyright (C) 2018-2019 Patrick Boettcher <[email protected]>
//
// SPDX-License-Identifier: LGPL-3.0
//
// Version: 1.0.0
//
// Project website: https://github.com/pboettch/cxx_argp
#ifndef CXX_ARGP_APPLICATION_H__
#define CXX_ARGP_APPLICATION_H__
#include "cxx_argp_parser.h"
#include <condition_variable>
#include <mutex>
#include <csignal>
namespace cxx_argp
{
class application
{
protected:
cxx_argp::parser arg_parser;
application(size_t expected_argument_count = 0)
: arg_parser(expected_argument_count)
{
std::signal(SIGINT, application::signal_hanlder);
std::signal(SIGTERM, application::signal_hanlder);
}
~application()
{
std::signal(SIGTERM, SIG_DFL);
std::signal(SIGINT, SIG_DFL);
}
// method to be overridden
virtual int main() = 0;
virtual bool check_arguments() { return true; }
static std::mutex main_event_mutex_; //< mutex for signal handling
static std::condition_variable main_event_; //< conditional variable to wakeup the application
static bool interrupted_; //< used by signal handlers
public:
const cxx_argp::parser &arguments() const { return arg_parser; }
// call this the start the application
int operator()(int argc, char *argv[])
{
if (!arg_parser.parse(argc, argv))
return EXIT_FAILURE;
if (!check_arguments())
return EXIT_FAILURE;
return main();
}
static void interrupt()
{
std::lock_guard<std::mutex> lk__(application::main_event_mutex_);
application::interrupted_ = true;
application::main_event_.notify_all();
}
static bool interrupted() { return application::interrupted_; }
static void wait()
{
std::unique_lock<std::mutex> lk(application::main_event_mutex_);
application::main_event_.wait(lk, [] { return application::interrupted_; });
}
static void signal_hanlder(int sig)
{
std::lock_guard<std::mutex> lk__(application::main_event_mutex_);
switch (reinterpret_cast<std::sig_atomic_t>(sig)) {
case SIGINT:
case SIGTERM:
application::interrupted_ = true;
application::main_event_.notify_all();
break;
default:
// ("unhandled process-signal")
break;
}
}
};
} // namespace cxx_argp
// to be included once per application - just before main() - at global scope
#define CXX_ARGP_APPLICATION_BOILERPLATE \
std::mutex cxx_argp::application::main_event_mutex_; \
std::condition_variable cxx_argp::application::main_event_; \
bool cxx_argp::application::interrupted_ = false;
#endif