Better method of preventing duplicate applications
[libs/core.git] / source / core / application.cpp
1 #include <typeinfo>
2 #include <signal.h>
3 #include <msp/debug/demangle.h>
4 #include <msp/debug/errorreporter.h>
5 #include <msp/io/print.h>
6 #include "application.h"
7 #include "getopt.h"
8
9 using namespace std;
10
11 namespace Msp {
12
13 Application *Application::app_ = 0;
14 Application::Starter *Application::starter_ = 0;
15 void *Application::data_ = 0;
16
17 Application::Application():
18         exit_code(0)
19 {
20         if(app_)
21                 throw logic_error("instance already exists");
22 }
23
24 int Application::run(int argc, char **argv, void *data)
25 {
26         if(!starter_)
27         {
28                 IO::cerr.write("Application::run called with no RegisteredApplication class!\n");
29                 return 126;
30         }
31
32         data_ = data;
33
34         try
35         {
36                 try
37                 {
38                         app_ = starter_->create_app(argc, argv);
39                 }
40                 catch(const usage_error &e)
41                 {
42                         IO::print(IO::cerr, "%s\n%s\n", e.what(), e.help());
43                         return 1;
44                 }
45
46                 int result = app_->main();
47                 Application *a = app_;
48                 app_ = 0;
49                 delete a;
50                 return result;
51         }
52         catch(const exception &e)
53         {
54                 bool handled = false;
55                 if(const Debug::ErrorReporter *er = Debug::ErrorReporter::get_current())
56                         handled = er->report_uncaught_exception(e);
57
58                 if(!handled)
59                 {
60                         IO::print(IO::cerr, "An uncaught exception occurred.\n");
61                         IO::print(IO::cerr, "  type:   %s\n", Debug::demangle(typeid(e).name()));
62                         IO::print(IO::cerr, "  what(): %s\n", e.what());
63                 }
64
65                 delete app_;
66                 app_ = 0;
67
68                 return 124;
69         }
70 }
71
72 int Application::main()
73 {
74         done = false;
75         while(!done)
76                 tick();
77
78         return exit_code;
79 }
80
81 void Application::catch_signal(int s)
82 {
83         signal(s, &sighandler_);
84 }
85
86 void Application::exit(int c)
87 {
88         done = true;
89         exit_code = c;
90 }
91
92 void Application::sighandler_(int s)
93 {
94         app_->sighandler(s);
95 }
96
97
98 Application::Starter::Starter()
99 {
100         if(starter_)
101                 throw logic_error("Can't create more than one Starter instance");
102
103         starter_ = this;
104 }
105
106 } // namespace Msp