llapp.h

Go to the documentation of this file.
00001 
00032 #ifndef LL_LLAPP_H
00033 #define LL_LLAPP_H
00034 
00035 #include <map>
00036 #include "llapr.h"
00037 #include "llrun.h"
00038 #include "llsd.h"
00039 
00040 // Forward declarations
00041 class LLErrorThread;
00042 class LLApp;
00043 
00044 
00045 typedef void (*LLAppErrorHandler)();
00046 typedef void (*LLAppChildCallback)(int pid, bool exited, int status);
00047 
00048 #if !LL_WINDOWS
00049 extern S32 LL_SMACKDOWN_SIGNAL;
00050 extern S32 LL_HEARTBEAT_SIGNAL;
00051 
00052 // Clear all of the signal handlers (which we want to do for the child process when we fork
00053 void clear_signals();
00054 
00055 class LLChildInfo
00056 {
00057 public:
00058         LLChildInfo() : mGotSigChild(FALSE), mCallback(NULL) {}
00059         BOOL mGotSigChild;
00060         LLAppChildCallback mCallback;
00061 };
00062 #endif
00063 
00064 class LLApp
00065 {
00066         friend class LLErrorThread;
00067 public:
00068         typedef enum e_app_status
00069         {
00070                 APP_STATUS_RUNNING,             // The application is currently running - the default status
00071                 APP_STATUS_QUITTING,    // The application is currently quitting - threads should listen for this and clean up
00072                 APP_STATUS_STOPPED,             // The application is no longer running - tells the error thread it can exit
00073                 APP_STATUS_ERROR                // The application had a fatal error occur - tells the error thread to run
00074         } EAppStatus;
00075 
00076 
00077         LLApp();
00078         virtual ~LLApp();
00079 
00083         static LLApp* instance();
00084 
00091         enum OptionPriority
00092         {
00093                 PRIORITY_RUNTIME_OVERRIDE,
00094                 PRIORITY_COMMAND_LINE,
00095                 PRIORITY_SPECIFIC_CONFIGURATION,
00096                 PRIORITY_GENERAL_CONFIGURATION,
00097                 PRIORITY_DEFAULT,
00098                 PRIORITY_COUNT
00099         };
00100 
00108         LLSD getOption(const std::string& name) const;
00109 
00122         bool parseCommandOptions(int argc, char** argv);
00123 
00134         bool setOptionData(OptionPriority level, LLSD data);
00135 
00144         LLSD getOptionData(OptionPriority level);
00146 
00147 
00148 
00149         //
00150         // Main application logic
00151         //
00152         virtual bool init() = 0;                        // Override to do application initialization
00153 
00154         //
00155         // cleanup()
00156         //
00157         // It's currently assumed that the cleanup() method will only get
00158         // called from the main thread or the error handling thread, as it will
00159         // likely do thread shutdown, among other things.
00160         //
00161         virtual bool cleanup() = 0;                     // Override to do application cleanup
00162 
00163         //
00164         // mainLoop()
00165         //
00166         // Runs the application main loop.  It's assumed that when you exit
00167         // this method, the application is in one of the cleanup states, either QUITTING or ERROR
00168         //
00169         virtual bool mainLoop() = 0; // Override for the application main loop.  Needs to at least gracefully notice the QUITTING state and exit.
00170 
00171 
00172         //
00173         // Application status
00174         //
00175         static void setQuitting();      // Set status to QUITTING, the app is now shutting down
00176         static void setStopped();       // Set status to STOPPED, the app is done running and should exit
00177         static void setError();         // Set status to ERROR, the error handler should run
00178         static bool isStopped();
00179         static bool isRunning();
00180         static bool isQuitting();
00181         static bool isError();
00182         static bool isExiting(); // Either quitting or error (app is exiting, cleanly or not)
00183 #if !LL_WINDOWS
00184         static U32  getSigChildCount();
00185         static void incSigChildCount();
00186 #endif
00187         static int getPid();
00188 
00189         //
00190         // Error handling methods
00191         //
00192         void setErrorHandler(LLAppErrorHandler handler);
00193         void setSyncErrorHandler(LLAppErrorHandler handler);
00194 
00195 #if !LL_WINDOWS
00196         //
00197         // Child process handling (Unix only for now)
00198         //
00199         // Set a callback to be run on exit of a child process
00200         // WARNING!  This callback is run from the signal handler due to the extreme crappiness of
00201         // Linux threading requiring waitpid() to be called from the thread that spawned the process.
00202         // At some point I will make this more behaved, but I'm not going to fix this right now - djs
00203         void setChildCallback(pid_t pid, LLAppChildCallback callback);
00204 
00205     // The child callback to run if no specific handler is set
00206         void setDefaultChildCallback(LLAppChildCallback callback); 
00207         
00208     // Fork and do the proper signal handling/error handling mojo
00209         // WARNING: You need to make sure your signal handling callback is correct after
00210         // you fork, because not all threads are duplicated when you fork!
00211         pid_t fork(); 
00212 #endif
00213 
00223         LLRunner& getRunner() { return mRunner; }
00224 
00225 public:
00226         typedef std::map<std::string, std::string> string_map;
00227         string_map mOptionMap;  // Contains all command-line options and arguments in a map
00228 
00229 protected:
00230 
00231         static void setStatus(EAppStatus status);               // Use this to change the application status.
00232         static EAppStatus sStatus; // Reflects current application status
00233         static BOOL sErrorThreadRunning; // Set while the error thread is running
00234 
00235 #if !LL_WINDOWS
00236         static LLAtomicU32* sSigChildCount; // Number of SIGCHLDs received.
00237         typedef std::map<pid_t, LLChildInfo> child_map; // Map key is a PID
00238         static child_map sChildMap;
00239         static LLAppChildCallback sDefaultChildCallback;
00240 #endif
00241 
00245         void stepFrame();
00246 
00247 private:
00248         void setupErrorHandling();              // Do platform-specific error-handling setup (signals, structured exceptions)
00249 
00250         static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred.
00251         static void runSyncErrorHandler(); // run IMMEDIATELY when we get an error, ran in the context of the faulting thread.
00252 
00253         // *NOTE: On Windows, we need a routine to reset the structured
00254         // exception handler when some evil driver has taken it over for
00255         // their own purposes
00256         typedef int(*signal_handler_func)(int signum);
00257         static LLAppErrorHandler sErrorHandler;
00258         static LLAppErrorHandler sSyncErrorHandler;
00259 
00260         // Default application threads
00261         LLErrorThread* mThreadErrorp;           // Waits for app to go to status ERROR, then runs the error callback
00262 
00263         // This is the application level runnable scheduler.
00264         LLRunner mRunner;
00265 
00268 
00269         // The application options.
00270         LLSD mOptions;
00271 
00273 
00274 private:
00275         // the static application instance if it was created.
00276         static LLApp* sApplication;
00277 
00278 
00279 #if !LL_WINDOWS
00280         friend void default_unix_signal_handler(int signum, siginfo_t *info, void *);
00281 #endif
00282 
00283 public:
00284         static BOOL sLogInSignal;
00285 };
00286 
00287 #endif // LL_LLAPP_H

Generated on Fri May 16 08:32:01 2008 for SecondLife by  doxygen 1.5.5