Howto:Start worker threads using listeners in Nasal

From FlightGear wiki
Jump to: navigation, search

The following snippet of code demonstrates how to run a Nasal function (named "hello") in a dedicated background thread (i.e. asynchronously) once a property listener is fired.

Once invoked, the hello function keeps calling itself asynchronously using a settimer() call at an interval of 5 seconds. After 60 seconds, it is getting terminated by the second listener that registered the "kill_thread" handler to be invoked by settimer after 60 seconds, via another Nasal thread.

 # async_demo.nas
 var cancel_thread=0;
 var l = nil;
 var r = nil;

 # the hello function will only ever be called from the worker thread
 var hello = func {
   print("Hello world from the background thread\n");
   if(!cancel_thread) settimer(hello,5,1);
 }

 # these are helpers to create a new thread
 var spawn = func(c) return func {thread.newthread(c)};

 # and to spawn a thread once a listener is fired
 var setlistener_job = func(p,f) setlistener(p, spawn(f) );

 # this will kill the running thread by removing the listener
 # and setting a global variable to 1 that is checked by the listener
 # finally, it will remove the listener that invoked the kill_thread function, too
 var kill_thread = func {
   removelistener(l);
   print("Killing background thread");
   cancel_thread=1;
   removelistener(r);
 }
 
 _setlistener("/sim/signals/nasal-dir-initialized", func {
   l=setlistener_job("/nasal-threading/test", hello);
   r=setlistener_job("/nasal-threading/test", func { settimer(kill_thread, 60, 1); });
   print("async_demo.nas loaded");
 });

To run the demo, copy/paste the code to a file in $FG_ROOT/Nasal, start up fgfs and modify the property "/nasal-threading/test" using the built-in property browser.