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"
23 Constructs an instance of the registered application class and runs it. If the
24 application throws a UsageError, the static usage() function is called.
26 This function can only be called once. The global main() function provided by
27 the library normally does it automatically at program startup.
29 int Application::run(int argc, char **argv, void *data)
31 static bool called=false;
34 cerr<<"Trying to call Application::run_app twice!\n";
41 cerr<<"Trying to run with no application class registered!\n";
51 app_=reg_app_->create_app(argc, argv);
53 catch(const UsageError &e)
55 reg_app_->usage(e.what(), argv[0], e.get_brief());
59 int result=app_->main();
63 catch(const exception &e)
65 cerr<<"An uncaught exception occurred.\n";
66 cerr<<" type: "<<Debug::demangle(typeid(e).name())<<'\n';
67 cerr<<" what(): "<<e.what()<<'\n';
69 const Exception *exc=dynamic_cast<const Exception *>(&e);
70 if(exc && !exc->get_backtrace().get_frames().empty())
72 cerr<<" backtrace:\n";
73 const Debug::Backtrace::FrameSeq &frames=exc->get_backtrace().get_frames();
74 for(Debug::Backtrace::FrameSeq::const_iterator i=frames.begin(); i!=frames.end(); ++i)
76 cerr<<" "<<i->address;
77 if(!i->symbol.empty())
78 cerr<<" in "<<i->symbol;
79 cerr<<" from "<<i->file<<'\n';
89 Prints a message describing the usage of the application. The default version
90 will blame the programmer for being lazy.
92 @param reason Why the function was called
93 @param argv0 The value of argv[0], to be used in the message
94 @param brief Whether to print a brief or long usage message
96 void Application::usage(const char *reason, const char *, bool)
99 cerr<<"UsageError: "<<reason<<'\n';
100 cerr<<"The programmer was lazy and didn't write a usage() function for this application.\n";
103 Application::Application():
105 loop_mode_(TICK_SLEEP)
109 Default main loop. Behavior depends on loop_mode_. A custom main loop should
110 monitor the done member variable and return exit_code.
112 int Application::main()
120 if(loop_mode_==SLEEP)
126 else if(loop_mode_==TICK_SLEEP)
129 Time::sleep(Time::msec);
131 else if(loop_mode_==TICK_YIELD)
140 else if(loop_mode_==TICK_BUSY)
148 Sets the specified signal to be delivered to the sighandler member function.
150 void Application::catch_signal(int s)
152 signal(s, &sighandler_);
156 Changes the main loop mode.
158 void Application::set_loop_mode(LoopMode l)
160 LoopMode old_mode=loop_mode_;
167 Causes the tick() function to be executed once if loop mode is SLEEP. Has no
168 effect with other loop modes.
170 void Application::induce_tick()
172 if(loop_mode_==SLEEP)
177 Causes the application to exit gracefully with the given exit code.
179 void Application::exit(int c)
183 if(loop_mode_==SLEEP)
188 Static wrapper function to call a member function of the Application instance.
190 void Application::sighandler_(int s)
195 Application::RegBase::RegBase()
199 cerr<<"Warning: registering the application twice\n";
206 Application *Application::app_=0;
207 Application::RegBase *Application::reg_app_=0;
208 void *Application::data_=0;