3 This file is part of libmspcore
4 Copyright © 2006 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
9 #include "../debug/backtrace.h"
10 #include "../debug/demangle.h"
11 #include "../time/units.h"
12 #include "../time/utils.h"
13 #include "application.h"
21 Constructs an instance of the registered application class and runs it. If the
22 application throws a UsageError, the static usage() function is called.
24 This function can only be called once. The global main() function provided by
25 the library normally does it automatically at program startup.
27 int Application::run(int argc, char **argv, void *data)
29 static bool called=false;
32 cerr<<"Trying to call Application::run_app twice!\n";
39 cerr<<"Trying to run with no application class registered!\n";
49 app_=reg_app_->create_app(argc, argv);
51 catch(const UsageError &e)
53 reg_app_->usage(e.what(), argv[0], e.get_brief());
57 int result=app_->main();
61 catch(const exception &e)
63 cerr<<"An uncaught exception occurred.\n";
64 cerr<<" type: "<<Debug::demangle(typeid(e).name())<<'\n';
65 cerr<<" what(): "<<e.what()<<'\n';
67 const Exception *exc=dynamic_cast<const Exception *>(&e);
68 if(exc && !exc->get_backtrace().get_frames().empty())
70 cerr<<" backtrace:\n";
71 const Debug::Backtrace::FrameSeq &frames=exc->get_backtrace().get_frames();
72 for(Debug::Backtrace::FrameSeq::const_iterator i=frames.begin(); i!=frames.end(); ++i)
74 cerr<<" "<<i->address;
75 if(!i->symbol.empty())
76 cerr<<" in "<<i->symbol;
77 cerr<<" from "<<i->file<<'\n';
87 Prints a message describing the usage of the application. The default version
88 will blame the programmer for being lazy.
90 @param reason Why the function was called
91 @param argv0 The value of argv[0], to be used in the message
92 @param brief Whether to print a brief or long usage message
94 void Application::usage(const char *reason, const char *, bool)
97 cerr<<"UsageError: "<<reason<<'\n';
98 cerr<<"The programmer was lazy and didn't write a usage() function for this application.\n";
101 Application::Application():
103 loop_mode_(TICK_SLEEP)
107 Default main loop. Behavior depends on loop_mode_. A custom main loop should
108 monitor the done member variable and return exit_code.
110 int Application::main()
118 if(loop_mode_==SLEEP)
124 else if(loop_mode_==TICK_SLEEP)
127 Time::sleep(Time::msec);
129 else if(loop_mode_==TICK_YIELD)
138 else if(loop_mode_==TICK_BUSY)
146 Sets the specified signal to be delivered to the sighandler member function.
148 void Application::catch_signal(int s)
150 signal(s, &sighandler_);
154 Changes the main loop mode.
156 void Application::set_loop_mode(LoopMode l)
158 LoopMode old_mode=loop_mode_;
165 Causes the tick() function to be executed once if loop mode is SLEEP. Has no
166 effect with other loop modes.
168 void Application::induce_tick()
170 if(loop_mode_==SLEEP)
175 Causes the application to exit gracefully with the given exit code.
177 void Application::exit(int c)
181 if(loop_mode_==SLEEP)
186 Static wrapper function to call a member function of the Application instance.
188 void Application::sighandler_(int s)
193 Application::RegBase::RegBase()
197 cerr<<"Warning: registering the application twice\n";
204 Application *Application::app_=0;
205 Application::RegBase *Application::reg_app_=0;
206 void *Application::data_=0;