User:Callahanp/Flightgear and Simgear Code/The Event Loop

From FlightGear wiki
Jump to navigation Jump to search
WIP.png Work in progress
This article or section will be worked on in the upcoming hours or days.
See history for the latest developments.

The FlightGear event loop operates during three phases of execution. It continuously operates from shortly after initialization starts, until shortly before the FlightGear program exits. During each cycle of the loop, three things get done: Changing some data; Updating the Display and Recording the Current Time. These three steps are done by these lines of code

Changing some data (*idleFunc)(); For example:
  • Loading the Airport Data or starting a subsystem during initialization
  • Handling User Inputs and Calculating Airspeed and Heading
  • Shutting down subsystems to prepare to re-initialize and keep going
Updating the display globals->get_renderer()->update() This is a complex process that assembles elements of the scene and prepares what is seen on the screen
Record the Current Time viewer->frame( globals->get_sim_time_sec()); This is used to calculate the Frame Rate, among other things.

The entire event loop is reproduced below.

While Updating the Display and Recording the current time always do the same things, the code that changes the data can call two distinct methods. One is used for initialzation and reset, the other for normal operation of the aircraft in the simulator.

During initialization and reset, the code (*idleFunc)() executes fgIdleFunc(). fgIdleFunc is where our subsystems are initializaed or shutdown and restarted once a reset has been requested.* Once initialization or re-initialization is complete, (*idleFunc)() executes a different method: fgOSMainLoop(). FgOSMainLoop handles all the user input and does the calculations of data on which the next frame on the display is based.**



* the name fgIdleFunc() doesn't tell us much. It's being accessed by a method of the renderer, and from the renderer's perspective, execute whatever this is when I'm idle makes some sense, but calling the function that gets called an idle function doesn't cut it. fgInitializeAndResetSubsystems might be a better name.

** the name fgOSMainLoop is another misnomer. It has nothing to do with the "Operating System" and does not contain a loop.
Even if we'd like better names for these two, we have other things to do that have a bigger impact.  I've pointed these two out because you may find other similar examples.  Just get used to it. However, if we're doing major work on a part of the code where these kinds of issues are present, that may be the time to change some names and do other cleanups. In the meantime, maybe make a list and keep them as pet peeves. Or not...


int fgOSMainLoop()
{
   viewer->setReleaseContextAtEndOfFrameHint(false);
   if (!viewer->isRealized()) {
       viewer->realize();
   }

   while (!viewer->done()) {
       fgIdleHandler idleFunc = globals->get_renderer()->getEventHandler()->getIdleHandler();
       if (idleFunc)
           (*idleFunc)();

       globals->get_renderer()->update();
       viewer->frame( globals->get_sim_time_sec());
   }

   return status;
}

Questions to be answered:

  • In idleFunc = globals->get_renderer()->getEventHandler()->getIdleHandler();
    • What does each step of the chain of calls do?
    • How long does each part of the chain take
    • Does the amount of time vary between cycles?
    • What's on the stack at each point.
  • Does fgMain Loop just update globals, including the property tree, or does anything under fgMainLoop do anything else?
  • Is each iteration of fgOSMainLoop a whole single frame?
  • Is fgOSMainLoop the only place where each of the eight calls is done?
  • Is globals->get_sim_time_sec() a function registered in globals or a method of the globals class.