3 This file is part of libmspcore
4 Copyright © 2006 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
11 #include "../debug/backtrace.h"
12 #include "../debug/demangle.h"
13 #include "../time/units.h"
14 #include "../time/utils.h"
15 #include "application.h"
22 Application::Application():
24 loop_mode_(TICK_SLEEP)
28 Constructs an instance of the registered application class and runs it. If the
29 application throws a UsageError, the static usage() function is called.
31 This function can only be called once. The global main() function provided by
32 the library normally does it automatically at program startup.
34 int Application::run(int argc, char **argv, void *data)
36 static bool called=false;
39 cerr<<"Trying to call Application::run_app twice!\n";
46 cerr<<"Trying to run with no application class registered!\n";
56 app_=reg_app_->create_app(argc, argv);
58 catch(const UsageError &e)
60 reg_app_->usage(e.what(), argv[0], e.get_brief());
64 int result=app_->main();
68 catch(const exception &e)
73 string msg=Debug::demangle(typeid(e).name())+":\n"+e.what();
74 MessageBoxA(0, msg.c_str(), "Uncaught exception", MB_OK|MB_ICONERROR);
76 cerr<<"An uncaught exception occurred.\n";
77 cerr<<" type: "<<Debug::demangle(typeid(e).name())<<'\n';
78 cerr<<" what(): "<<e.what()<<'\n';
80 const Exception *exc=dynamic_cast<const Exception *>(&e);
81 if(exc && !exc->get_backtrace().get_frames().empty())
83 cerr<<" backtrace:\n";
84 const list<Debug::Backtrace::StackFrame> &frames=exc->get_backtrace().get_frames();
85 for(list<Debug::Backtrace::StackFrame>::const_iterator i=frames.begin(); i!=frames.end(); ++i)
95 Prints a message describing the usage of the application. The default version
96 will blame the programmer for being lazy.
98 @param reason Why the function was called
99 @param argv0 The value of argv[0], to be used in the message
100 @param brief Whether to print a brief or long usage message
102 void Application::usage(const char *reason, const char *, bool)
105 cerr<<"UsageError: "<<reason<<'\n';
106 cerr<<"The programmer was lazy and didn't write a usage() function for this application.\n";
110 Default main loop. Behavior depends on loop_mode_. A custom main loop should
111 monitor the done member variable and return exit_code.
113 int Application::main()
121 if(loop_mode_==SLEEP)
127 else if(loop_mode_==TICK_SLEEP)
130 Time::sleep(Time::msec);
132 else if(loop_mode_==TICK_YIELD)
141 else if(loop_mode_==TICK_BUSY)
149 Sets the specified signal to be delivered to the sighandler member function.
151 void Application::catch_signal(int s)
153 signal(s, &sighandler_);
157 Changes the main loop mode.
159 void Application::set_loop_mode(LoopMode l)
161 LoopMode old_mode=loop_mode_;
168 Causes the tick() function to be executed once if loop mode is SLEEP. Has no
169 effect with other loop modes.
171 void Application::induce_tick()
173 if(loop_mode_==SLEEP)
178 Causes the application to exit gracefully with the given exit code.
180 void Application::exit(int c)
184 if(loop_mode_==SLEEP)
189 Static wrapper function to call a member function of the Application instance.
191 void Application::sighandler_(int s)
197 Application::RegBase::RegBase()
201 cerr<<"Warning: registering the application twice\n";
208 Application *Application::app_=0;
209 Application::RegBase *Application::reg_app_=0;
210 void *Application::data_=0;