Talk:Nasal Loops

From FlightGear wiki
Jump to navigation Jump to search

Reset/re-init handling (09/2018)

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

prototype UI callback monitor dialog using nasal and canvas
updated screenshot showing the reset/re-init control panel for helping troubleshoot reset/re-init related segfaults

FWIW, I am basically AFK, but referring to the discussion that took place in 09/2018 [1], here's my 2c and a few pointers from a lurking standpoint, based on tinkering with Nasal internals for quite a while, and giving soapbox speeches about im/proper use of timers and listeners:

  • misuse/misunderstanding of Nasal callback registration (Timers & Listeners) is one of the main causes for mistakes made by people using Nasal, reflecting badly upon Nasal/FGNasalSys as a whole, unnecessarily so.
  • The existing timer/listener API is the actual bottleneck when it comes to Nasal code, because it's indeed this very interface that ties everything together at runtime - so that even FGPythonSys would be subject to the same limitations if it were to use the same timer/listener mechanism.
  • mis-using Nasal timers and listeners is extremely easy, using them properly requires enormous familiarity with fgfs internals
  • the settimer/setlistener APIs are extremely low-level APIs that ended up being used to work around internal fgfs limitations (think bootstrapping and lack of run-levels, i.e. no inter-module dependency tracking/resolution)
  • however, as we know, misuse of timers/listeners isn't specific to Nasal at all, cf Torsten's work fixing the effects system, when he introduced the UniformFactory/Cache in conjunction with Stuart
  • fgfs is making extensive use of listeners and timers in tons of places, so that control flow is less and less deterministic because there are countless layers of listeners/timers that may end up doing context switches between Nasal/C++ space numerous times per second, and sometimes even numerous times per frame. Debugging/troubleshooting such issues is enormously difficult, and is becoming even more difficult due to more and more ways to trigger Nasal code (think via the Canvas system, but also through addons, thanks to Torsten's and Florent's work).
  • thus, what is lacking are native hooks to provide "introspection means", i.e. that allow people to look behind the scenes and see what is going on in terms of Nasal callback registration/invocation.
  • for starters, it would be useful to provide cppbind based APIs to get stats for the number of timer/listener callbacks registered, this could be also dumped to the console/STDOUT (fgfs.log), and it would be easy to provide a property that keeps track of such numbers and exposes them in the global property tree, so that a simple listener could monitor these properties and issue a warning whenever an unreasonable number of callbacks is registered/invoked, had we had this a few years ago, the issue that Torsten and Stuart fixed then would not have gone unnoticed for so long.
  • in addition, it is possible to fix up NasalSys.cxx to use the info used by naRuntimeError [2] to get a handle for the registration place of a listener/timer, i.e. using the filename and line number of the corresponding call [1]
  • This would certainly help understand and clean up the existing mess.
  • In the mid-term however, it would make more sense to look at what reset/re-init is all about, and determine if dealing with Nasal callbacks in such coarse fashion is really what we want/need here. In other words, it would seem like a good idea to introduce context-specific callbacks, so that these are scoped - basically the equivalent of maketimer, just scoped for the main simulator contexts (in terms of scripting environments). For instance, consider having scopes for aircraft scripts, scenery scripts and GUI scripts (and maybe other/misc or core scripts). Providing such an API would make it possible for us to review existing scripts and overload the existing settimer/maketimer calls, so that the proper context/scope is used, which would in turn make it possible for reset/re-init to selectively purge/re-init certain scripts or not.
  • Furthermore, this would nicely align with the groundwork done by Torsten and Florent in the addon system, which will sooner or later also require a way to look behind the scenes of addon specific Nasal scripts, analogous to how internet browsers are now using sandboxed JavaScript environments for each open tab/webpage.
  • So, if we were to provide such APIs, it would be easy to change the addon system such that it makes settimer/maketimer unavailvable and only expose addon-specific equivalents of these, that provide built-in introspection mechanism.
  • In addition, such a higher-level maketimer-like equivalent for listeners in in line with James' original idea, discussed here [2] The API could also be extended to support split-frame loops to spread work across several frames more easily.

HTH (if not now, maybe in a few years time ...)

--Hooray (talk) 11:40, 15 September 2018 (EDT)

Deprecation warning

If the API is indeed deprecated, it would make sense to overload settimer() using a maketimer() based wrapper, and maybe rename _settimer() in future releases, showing a log message whenever it is still being used. As I said before, it would not be such a bad idea to introduce a cleaner namespace for addons, where APIs that are known to be problematic are simply removed from the namespace (namely, settimer and setlistener for now), so that best practices can be better enforced - besides, it would not be that much work to review existing addons and fix them up accordingly. Personally, I don't think that aircraft should have access to settimer() at all, it's far too low-level for most aircraft developers - they should have only access to maketimer, and in the interim, settimer() could be wrapped showing a warning that it is in the process of being phased out. People still wanting to use settimer, would have to use the C extension function directly, i.e. __settimer().

--Hooray (talk) 11:52, 15 September 2018 (EDT)