Nasal Loops: Difference between revisions

Jump to navigation Jump to search
(updated to describe current best practice regarding settimer loops)
(5 intermediate revisions by 2 users not shown)
Line 3: Line 3:
Nasal has several ways to implement an iteration.
Nasal has several ways to implement an iteration.


A polling loop is akin to somebody permanently running to a room to check if the lights are on - a listener is like somebody being INSIDE the room SLEEPING and only WAKING up once the lights are turned on.
A polling loop is akin to somebody permanently running to a room to check if the lights are on - a listener is like somebody being INSIDE the room SLEEPING and only WAKING up once the lights are turned on (there is no active workload involved here, other than basically "watching" the switch).


The {{func link|setlistener()}} API is intended to catch rare events. Avoid complex loops if you don't have to.
The {{func link|setlistener()}} API is intended to catch rare events. Avoid complex loops if you don't have to.


In general, "loops" are not bad or expensive, it really depends on what you're doing inside the loop.
In general, "loops" are not bad or expensive, it really depends on what you're doing inside the loop.
A loop will be executed within a single frame normally - so a long-running loop will add up to the frame spacing.
A loop will be executed within a single frame normally - so a long-running loop will add up to the frame spacing (the time needed to create a single frame).
 
There's nothing magic about timers or listeners - they can just as well inflate your frame spacing.
There's nothing magic about timers or listeners - they can just as well inflate your frame spacing.
It doesn't matter if the code/callback is run inside a loop, timer or a listener - what matter is the complexity of the code that runs.
 
timers or listeners are only really preferable over loops when it comes to checking for some condition, because polling is called "busy-waiting", i.e. more expensive, see my previous analogy.
It doesn't matter if the code/callback is run inside a loop, timer or a listener - what does matter is the complexity of the code that runs.
 
Timers or listeners are only really preferable over loops when it comes to checking for some condition, because polling is called "busy-waiting", i.e. more expensive, see the previous analogy.
 
A listener or timer "waiting" is not resource-hungry, it's not even busy - it's not doing anything until it is "fired".
A listener or timer "waiting" is not resource-hungry, it's not even busy - it's not doing anything until it is "fired".
Regarding {{func link|setprop()}}/{{func link|getprop()}} - they're not as bad as we used to think - in fact, Thorsten has shown that they're preferable over most [[Nasal library/props|props.nas APIs}}, this may however change once the whole thing is replaced with cppbind bindings.
Regarding {{func link|setprop()}}/{{func link|getprop()}} - they're not as bad as we used to think - in fact, Thorsten has shown that they're preferable over most [[Nasal library/props|props.nas APIs]], this may however change once the whole thing is replaced with [[Nasal/CppBind|cppbind bindings]].


Well loops aren't bad necessarily: they can be used in a less-than-optimal manner, but there are often times where they make a lot of sense. Some pros and cons of both:
Thus, loops aren't bad necessarily: they can be used in a less-than-optimal manner, but there are often times where they make a lot of sense. Some pros and cons of both:


Listeners: Pros:
Listeners: Pros:
Line 229: Line 233:
Beginning with FlightGear 2.11+ you should consider using the {{func link|maketimer()}} API instead.
Beginning with FlightGear 2.11+ you should consider using the {{func link|maketimer()}} API instead.


This is because maketimer creates an object that can be managed, rather than as settimer which once called will irrevocably call the method once the duration has elapsed. For this reason settimer is considered to be unmanageable.
This is because maketimer creates an object that can be managed, rather than settimer which once called will irrevocably call the method once the duration has elapsed. For this reason settimer is considered to be unmanageable and has been deprecated.


=== maketimer example ===
=== maketimer example ===
Line 244: Line 248:


mt_loop_exampleTimer = maketimer(0.25, mt_loop_example);
mt_loop_exampleTimer = maketimer(0.25, mt_loop_example);
mt_loop_exampleTimer.simulatedTime = 1; # defaults to using wallclock time and will therefore continue during pause.
mt_loop_exampleTimer.simulatedTime = 1; # use simulated time, as maketimer defaults to using wallclock time and continues during pause.
mt_loop_exampleTimer.start();
mt_loop_exampleTimer.start();
</syntaxhighlight>
</syntaxhighlight>


=== maketimer from FDM Initialized ===
<syntaxhighlight lang="nasal">
var timer_loop = func{
# logic
};
timer_loopTimer = maketimer(0.25, timer_loop);
setlistener("sim/signals/fdm-initialized", func {
    timer_loopTimer.start();
});
</syntaxhighlight>


See also {{func link|maketimer()}} {{func link|settimer()}}
See also {{func link|maketimer()}} {{func link|settimer()}}
306

edits

Navigation menu