]> git.tdb.fi Git - libs/core.git/blob - source/core/application.cpp
36621e92ae99af9b74a2726263fd3b8176cbd020
[libs/core.git] / source / core / application.cpp
1 #include <signal.h>
2 #include <msp/io/print.h>
3 #include "application.h"
4 #include "getopt.h"
5
6 using namespace std;
7
8 namespace Msp {
9
10 Application *Application::app_ = 0;
11 Application::Starter *Application::starter_ = 0;
12 void *Application::data_ = 0;
13
14 Application::Application():
15         exit_code(0)
16 { }
17
18 /**
19 Constructs an instance of the registered application class and runs it.  If the
20 application throws a usage_error, a help message is printed.  The GetOpt class
21 will throw such exceptions automatically in error conditions.
22
23 This function can only be called once.  The global main() function provided by
24 the library normally does it automatically at program startup.
25 */
26 int Application::run(int argc, char **argv, void *data)
27 {
28         static bool called = false;
29         if(called)
30         {
31                 IO::cerr.write("Trying to call Application::run_app twice!\n");
32                 return 125;
33         }
34         called = true;
35
36         if(!starter_)
37         {
38                 IO::cerr.write("Trying to run with no RegisteredApplication class!\n");
39                 return 126;
40         }
41
42         data_ = data;
43
44         try
45         {
46                 try
47                 {
48                         app_ = starter_->create_app(argc, argv);
49                 }
50                 catch(const usage_error &e)
51                 {
52                         IO::print(IO::cerr, "%s\n%s\n", e.what(), e.help());
53                         return 1;
54                 }
55
56                 int result = app_->main();
57                 Application *a = app_;
58                 app_ = 0;
59                 delete a;
60                 return result;
61         }
62         catch(const exception &e)
63         {
64                 delete app_;
65
66                 display_exception(e);
67
68                 return 124;
69         }
70 }
71
72 /**
73 Default main loop.  Calls tick() repeatedly until exit() is called.  A custom
74 main loop should monitor the done member variable and return exit_code.
75 */
76 int Application::main()
77 {
78         done = false;
79         while(!done)
80                 tick();
81
82         return exit_code;
83 }
84
85 /**
86 Sets the specified signal to be delivered to the sighandler member function.
87 */
88 void Application::catch_signal(int s)
89 {
90         signal(s, &sighandler_);
91 }
92
93 /**
94 Causes the application to exit gracefully with the given exit code.
95 */
96 void Application::exit(int c)
97 {
98         done = true;
99         exit_code = c;
100 }
101
102 /**
103 Static wrapper function to call a member function of the Application instance.
104 */
105 void Application::sighandler_(int s)
106 {
107         app_->sighandler(s);
108 }
109
110
111 Application::Starter::Starter()
112 {
113         if(starter_)
114                 throw logic_error("Can't create more than one Starter instance");
115
116         starter_ = this;
117 }
118
119 } // namespace Msp