V12 wrote in Wed Nov 20, 2019 8:47 am:Not, FGFS is singlethreaded
. All NASAL things should be executed in other thread than main loop. FDM should be in another thread.
Flightgear does uses multiple threads, Nasal scripting is not run in one of those however - for the reasons that Thorsten outlined.
It is trivial to run Nasal in another thread, and even to thread out algorithms using Nasal.
Nasal itself was designed with thread-safety in mind, by an enormously talented software engineer with a massive track record doing this kind of thing (background in embedded engineering at the time).
FlightGear however was never "designed" like Thorsten alluded to, rather its architecture "happened" by dozens of people over the course of almost 2 decades meanwhile.
The bottleneck when it comes to threading in Nasal is indeed FlightGear, the very instant you access any non-native Nasal APIs, i.e. anything that is FlightGear specific (property tree, extension functions, fgcommands, canvas) - the whole thing is no longer easy to make work correctly, without re-architecting the corresponding component (think Canvas).
In the case of Canvas, it would be relatively straight-forward to do just that, by introducing a new canvas mode, where each canvas (texture) gets its own private property tree node (SGPropertyNode) that is part of simgear::canvas, at that point, you can also add a dedicated FGNasalSys instance to each canvas texture (Nasal interpreter), and that could be threaded out using either Nasal's threading support or using simgear's SGThread API.
Obviously, there would remain synchronization points, where this "canvas process" (thread) would fetch data from FlightGear (properties) and also send back its output to FlightGear (aka the final texture).
Other than that, it really is surprisingly straightforward to come up with a thread-safe version of the Canvas system by making these two major changes - the FGNasalSys interpreter would then no longer have access to the global namespace or any of the standard extension functions, it could only manipulate its own canvas property tree - all I/O between the canvas texture thread (Nasal) and the main loop (thread) would have to take place using a well defined I/O mechanism, in its simplest form a simple network protocol (even telnet/props or Torsten's AJAX/mongoose layer would work "as is") - more likely, this would evolve into something like Richard's Emesary system.
Like Thorsten said already, you cannot "simply" thread out "all nasal" without either changing all existing Nasal code or without re-architecting FlightGear along the way.
Based on my own understanding of FlightGear, its main loop and the scripting layer, the most promising way forward would indeed be to tinker with a new addon-mode where scripts could be run inside such a sandboxed environment, using a background thread. This would be akin to firefox web extensions, that basically hit the same restrictions because of the proliferation of javascript in browsers - so, this kind of model has been demonstrated to work: one background thread for the work, and main loop scripts for the interaction with the rest of the environment.
This kind of thing can be worked on without breaking things, and it is largely facilitated by bugman's unit testing work, i.e. being able to start independent instances of the Nasal interpreter and test these outside the sim.
Once you are able to do just that, you can also easily take FGNasalSys and come up with a stripped-down version to remove all the stuff that makes such an instance thread-unsafe, and re-add what's useful later on. Probably, using some kind of RPC/IPC mechanism - socket I/O for starters should do.
The very moment you see bugman making reports about testing Nasal standalone in conjunction with certain FG APIs, all the building blocks will be in place.
A new addon mode/version could be added to support threaded addons, which is a no-brainer to do, because it cannot break anything, since we don't have any threaded addons yet.
And at that point, it would also be trivial to tinker with a new canvas mode, that has its own private property tree and its own private Nasal instance.
This is a really low-hanging fruit to be honest, and it's straightforward path to provide FlightGear with better threading support, so that anything involving
new Nasal work, can be made to live inside separate threads, i.e. using such addons or canvas textures that are updated asynchronously, and which are only synchronized at certain time steps.
In addition, from a canvas standpoint this would provide for an excellent mechanism to bring unit testing to canvas-based avionics, because those can then trivially be executed outside the main loop, so that we could even run a batch job on the build server to create screen shots of avionics (say a PFD or ND) purely based on hooking them up to a pre-recorded flight or some other stored state vector containing all the properties/data.
Just running "all of Nasal" outside the main loop is going to be much more work, than being smart about it, and by preparing the hooks to thread out the interesting stuff, and provide an infrastructure to port/implement new features in the future.
Such a modified/modernized Canvas system would then contain its own private property tree for each instance and its own scripting interpreter (context), which would mean that it could even be compiled into a standalone executable, and even be executed in a headless fashion:
http://wiki.flightgear.org/Canvas_Devel ... FlightGearhttp://wiki.flightgear.org/FlightGear_Headless