Callbacks

From FlightGear wiki
(Redirected from Timers)
Jump to navigation Jump to search

In FlightGear, a callback is a function that will typically be invoked by either a #Timers or a property #Listeners. One of the most common ways of using timers and listeners is FlightGear scripting via the built-in Nasal scripting language. However, the underlying code is not specific to Nasal scripting, i.e. is also widely used in native/C++ code.

1rightarrow.png See Howto:Troubleshooting Nasal Callbacks for the main article about this subject.

Caution  Improper use of timers and listeners is one of the most common causes for FlightGear performance issues, because function callbacks (code) may be registered to be triggered/executed more often than required (potentially, several times per frame), this problem is not specific to Nasal code written by aircraft developers, but also C++ code written by FlightGear core developers, it's been the source of major resource leaks in FlightGear, causing severe stuttering and performance degradation over time.

The one thing that both timers and listeners have in common is that they're event handlers, i.e. mechanisms that allow custom code to be executed whenever a certain event is triggered, such as a configurable timer expiring and/or a property being updated/modified.

Listeners

Listeners are a way to register event handlers (functions processing/dealing with ann event) to be executed once a property is modified/written to (updated). This is accomplished using the SGProeprtyChangeListener API (link) in SimGear. Listeners are the most common method for running custom Nasal callbacks (functions), the other being Timers.

many subsystems are modifyinig properties, which may in turn invoke Nasal callbacks (possibly even without being aware of the implications).

the settimer() and setlistener() APIs are particularly tedious to manage properly - but the de facto practice is to use those as the main building blocks to write/integrate full subsystems into the FlightGear main loop - tiny coding errors may not have much of an effect, but under certain circumstances, those coding errors will add up (i.e. over time), so that the original "task" of checking your inbox once per hour, ends up being executed hundreds of times per second - the underlying code would still be correct though, it's just the event handling code that is not written correctly, which is often the case when using reset/re-init or when changing locations

In a sense, timers are "active" - while listeners are "passive", because they get only ever invoked once the property is modified. Still, the reason for using timers is usually saving resources - by running certain code at configurable intervals.

In other words, there are subsystems that run Nasal code, without showing up in the Nasal category - such as property tree or events system. Still, that doesn't currently tell you which code (function, loop, file, line number etc) is really adding up/expensive.

Cquote1.png Listeners should be used on properties to get notice about occasional changes. In cases where we *know* when the property changes -- once per loop or more often -- we can have the same result cheaper with a loop. (Listeners on YASim properties are special in that those can change several times per frame, and one may indeed want the listener triggered every time. But this should be a deliberate decision, not an accident.) For some of your listeners it may be enough to set the second optional argument to 0, so that the listener code is only triggered when the node value changes. Just turn on listener logging or put a print() message into it to see the costs.
— Melchior FRANZ (Oct 24th, 2007). Re: [Flightgear-devel] FlightGear/Plib periodic stutter notes.
(powered by Instant-Cquotes)
Cquote2.png

Timers

Timers are a way to register recurring tasks to be executed repeatedly. This is accomplished using the FlightGear event manager. Timers are the most common method for running Nasal callbacks (functions), the other being Listeners. Please noote that that settimer() should be considered deprecated, and maketimer() should be favored instead.


"events" in the performance monitor can usually be attributed to Nasal timers, Nasal is not the only subsystem to use the event manager

there's basically a separate "events" subsystem which is based on FGTimer/SGTimer objects that trigger callbacks - in this case, Nasal callbacks. This can also be seen in the system monitor: http://wiki.flightgear.org/Howto:Use_the_system_monitor

the settimer() and setlistener() APIs are particularly tedious to manage properly - but the de facto practice is to use those as the main building blocks to write/integrate full subsystems into the FlightGear main loop - tiny coding errors may not have much of an effect, but under certain circumstances, those coding errors will add up (i.e. over time), so that the original "task" of checking your inbox once per hour, ends up being executed hundreds of times per second - the underlying code would still be correct though, it's just the event handling code that is not written correctly, which is often the case when using reset/re-init or when changing locations

In a sense, timers are "active" - while listeners are "passive", because they get only ever invoked once the property is modified. Still, the reason for using timers is usually saving resources - by running certain code at configurable intervals.

In other words, there are subsystems that run Nasal code, without showing up in the Nasal category - such as property tree or events system. Still, that doesn't currently tell you which code (function, loop, file, line number etc) is really adding up/expensive.

the event manager subsystem (SGEventMgr) which has two internal "queues" for keeping a list of callbacks that shall be invoked when a certain event (timeout) happens, as well as the property tree interface to register Nasal callbacks via the SGPropertyChangeListener API:

http://api-docs.freeflightsim.org/simge ... ntMgr.html http://api-docs.freeflightsim.org/simge ... tener.html