-
Notifications
You must be signed in to change notification settings - Fork 333
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a mechanism so gadgetHandler reordering api can be used safely. #3907
Add a mechanism so gadgetHandler reordering api can be used safely. #3907
Conversation
Why do the raw methods need to be exposed in the |
Yes, they can be made private, they're just the old methods renamed. For now I changed the minimal amount of code to make changes easier to review, but they can be converted into private local methods to the module. To be honest making them private will be a bit of pain since now they are always accessed through gadgethandler, also, most gadgets don't have access unless declaring 'handler' in the gadgetInfo structure, but it can be done for sure. |
Doesn't this still fail with recursive calls? |
I think it should work, check this, as long as the callstack is not exhausted it should be fine. edit: sorry, I thought you mean a reorder that triggers another reorder, if you mean reentrant callins then yes I need to account for that, I'll add a counter to make sure to only reorder after after "main" callin loop. |
Yes, I mean one callin being called from within another, triggering a reorder while the outer loop is stilliterating. Solving it via depth counter sounds good. |
Another remark: widget handler will need the same treatment as gadget handler |
Indeed. Once this is done I intend to implement for widgets too, just wanted to ensure the approach is wanted before doing so, also limiting the PR scope that way. |
Tested before and after ordering (printing all synced and unsynced gadgets at the end of gadgetHandler:Initialize) and I can confirm indeed the ordering doesn't change. Procedure used for test:
Spring.Echo("ORDERING")
for _, g in pairs(self.gadgets) do
Spring.Echo(g.ghInfo.basename, g.ghInfo.layer)
end
Spring.Echo("END ORDERING")
Resulting files: f1.txt, f2.txt (yes they look like the same file) |
…#3947) Fix wrapping of top level callins returning several parameters, this fixes a bug introduced in #3907 Affected methods: GameSetup, AllowWeaponTarget, UnitPreDamaged, FeaturePreDamaged Likely affected gadgets: * GameSetup: none, still it can be affecting some engine calls since it will always return newReady nil, although afaics the engine won't accept the nil value so it shouldn't be affecting it. * AllowWeaponTarget (affects returned priority): unit_aa_targeting_priority. * UnitPreDamaged (affects impulse only): unit_combomb_full_damage, unit_dgun_behaviour, engine_hotfixes, unit_paralyze_damage_multiplier, map_lava, unit_paralyze_on_off, unit_collision_damage_behavior, unit_timeslow, unit_objectify, unit_evolution, unit_commando_watch, unit_shield_behaviour, unit_single_damage_fire, unit_lightning_splash_dmg, mo_preventcombomb, scav_spawner_defense, unit_no_land_damage. * FeaturePreDamaged (affects impulse only): gfx_tree_feller.
Work done
Addresses Issue(s)
Details
NOTE This is changing critical game code so will need some review and testing. I am posting this PR to gather feedback while I can perform some last checks on the operation (like reviewing whether after initialization ordering is still the same for example). Also probably need to add some safeguards against duplicated items in the queue.
This changes all of the following callins:
After reviewing the code I think all those methods can cause unsafe reordering of the callin lists (ie the problem is not just InsertGadget and RemoveGadget), while the callers are iterating them, thus can result in skipped calls.
The solution I propose consists in replacing the callins by queued versions, and providing the old api under ..'Raw' name (not to be used directly). The main handler is augmented to call a reordering method (gadgetHandler:PerformReorders) after callin loops, that will process all methods above in order after the loop is finished.
This solution should make all of the above methods safe to use during execution of any handlers. I tried to make it as efficient as possible, so in the general case after every callin loop just a local bool check is introduced before doing any heavy work.
This could result in slightly different behaviour than before in the case a gadget is removing another one before that one executes. I will also study this closely, but that might be more of a problem with widgets.
The solution can be implemented for widgets as well since handling is very similar, but I think gadgets have a higher requirement for robustness so I implemented it here first.
Test steps