Page 5 of 5

Re: Energy bomb [Solved]

Posted: Tue Jul 10, 2012 11:57 am
by m4r35n357
Well, I did look back when I was writing my OXPs, and decided that awardEquipment() was a simpler way of doing it as it gives a return code for success/failure. No need to check first then do it anyway.

Re: Energy bomb [Solved]

Posted: Thu Jul 12, 2012 4:37 pm
by CommonSenseOTB
I too am guilty of not checking if the equipment can be awarded first. Unfortunately, I learn by example and seeing exactly how a piece of code is used in an oxp is far more useful to me. If I never see a certain command being used but a different one or group that sort of performs the same function and everyone is doing it that way, then that will probably be the way I learn to program.

Now that equipment that is not available to all cannot be awarded by script unless it is listed in the shipyard file and noone was checking in previous oxps if the equipment can be awarded, well, there might be alot of oxps to rewrite for 1.77 and we will all have to be alot less sloppy, especially me. :wink:

Re: Energy bomb [Solved]

Posted: Fri Jul 13, 2012 10:28 am
by m4r35n357
CommonSenseOTB wrote:
I too am guilty of not checking if the equipment can be awarded first.
Well, I am disputing your guilt ;) AIUI the API supports two ways of awarding equipment; "check-then-act" (canAwardEquipment followed by awardEquipment, with or without checking return) and "do it but handle potential failure" (awardEquipment and check return). In the absence of firm guidance I would infer that the latter is actually preferable (one function call, no window of vulnerability between check & act).
So, devs, sorry I was unclear in my earlier post; can we have clarification on this specific point?

Re: Energy bomb [Solved]

Posted: Fri Jul 13, 2012 10:37 am
by cim
m4r35n357 wrote:
CommonSenseOTB wrote:
I too am guilty of not checking if the equipment can be awarded first.
Well, I am disputing your guilt ;) AIUI the API supports two ways of awarding equipment; "check-then-act" (canAwardEquipment followed by awardEquipment, with or without checking return) and "do it but handle potential failure" (awardEquipment and check return). In the absence of firm guidance I would infer that the latter is actually preferable (one function call, no window of vulnerability between check & act).
So, devs, sorry I was unclear in my earlier post; can we have clarification on this specific point?
There are three possible outcomes of a call to awardEquipment:
1) The equipment exists and can be awarded. awardEquipment awards the equipment and returns 'true'.
2) The equipment exists but cannot currently be awarded to this ship. awardEquipment returns 'false'.
3) The equipment does not exist. awardEquipment throws an exception.

So it's fine to call awardEquipment without calling canAwardEquipment first, provided that:
  • you know, for certain, that the named equipment exists (perhaps because you are awarding it from a script of the OXP that defines it); or
  • you use the try/catch syntax to catch the exception if it is thrown and recover appropriately

Re: Energy bomb [Solved]

Posted: Fri Jul 13, 2012 11:29 am
by JensAyton
cim wrote:
  • you know, for certain, that the named equipment exists (perhaps because you are awarding it from a script of the OXP that defines it); or
And, to be fair, assuming built-in equipment will always exist is pretty reasonable. This is a special case.

However, the script in question was checking but was doing it in a fragile way. Given the choice between canAwardEquipment (which checks all relevant conditions based on the current equipment definitions) and testing the conditions you can think of yourself, canAwardEquipment is definitely the Right Thing.
m4r35n357 wrote:
I would infer that the latter is actually preferable (one function call, no window of vulnerability between check & act)
This “window of vulnerability” isn’t a real thing, since the programming model for scripts is single-threaded/serial and atomic with respect to the application’s state updates. In other words, the only way something can change between canAwardEquipment and awardEquipment in the same function is if you do something to cause a change.

(Breaking this assumption would vast numbers of scripts and the resulting programming environment would be far to difficult for casual scripters to deal with. If there’s ever any form of scripting concurrency in Oolite, it will probably be something highly isolated, like Web Workers.)

Re: Energy bomb [Solved]

Posted: Fri Jul 13, 2012 12:23 pm
by m4r35n357
OK, thanks for the clarification guys.
I understand the bit about scripts themselves running in a single-threaded environment, but what if, say, you attempt to award some equipment to a ship in flight, and it gets destroyed after the canAwardEquipment() call and before the awardEquipment() call? Yes, it's a contrived and extreme scenario, but it _could_ happen theoretically, couldn't it? So in that case it would still be necessary to do a try/catch?
FWIW, I do award equipment to ships in flight (to speed up launching multiple ships), but it's core equipment so I just award it and check the return (so I could be vulnerable to an exception too, hmm I think I'll risk it!).
I think I might have over-analysed this ;)

Re: Energy bomb [Solved]

Posted: Fri Jul 13, 2012 12:41 pm
by JensAyton
m4r35n357 wrote:
I understand the bit about scripts themselves running in a single-threaded environment, but what if, say, you attempt to award some equipment to a ship in flight, and it gets destroyed after the canAwardEquipment() call and before the awardEquipment() call? Yes, it's a contrived and extreme scenario, but it _could_ happen theoretically, couldn't it?
No, it couldn’t, as long as it was all within one event handler or callback. Obviously calling canAwardEquipment() and setting a flag, returning, then assuming the flag is still valid in some other event would be bad.

Re: Energy bomb [Solved]

Posted: Fri Jul 13, 2012 12:46 pm
by Switeck
Are frame callbacks in separate OXPs triggering for the same frame/event run concurrently or simultaneously?

Re: Energy bomb [Solved]

Posted: Fri Jul 13, 2012 12:47 pm
by m4r35n357
Ah, OK, does that mean that all game threads are suspended during (every) JS (function?) execution?

Re: Energy bomb [Solved]

Posted: Fri Jul 13, 2012 12:50 pm
by cim
m4r35n357 wrote:
OK, thanks for the clarification guys.
I understand the bit about scripts themselves running in a single-threaded environment, but what if, say, you attempt to award some equipment to a ship in flight, and it gets destroyed after the canAwardEquipment() call and before the awardEquipment() call? Yes, it's a contrived and extreme scenario, but it _could_ happen theoretically, couldn't it? So in that case it would still be necessary to do a try/catch?
Even in that situation with flags in different event handlers, you wouldn't need to try/catch (unless the event handlers are so far separated that the player could have saved the game, changed their OXP set, and carried on between the two...). The equipment item exists, so the "worst" awardEquipment can do is return false.
Switeck wrote:
Are frame callbacks in separate OXPs triggering for the same frame/event run concurrently or simultaneously?
As with the event handlers, frame callbacks are run sequentially and serially.
m4r35n357 wrote:
Ah, OK, does that mean that all game threads are suspended during (every) JS execution?
While Oolite is technically a multi-threaded application, the vast majority of processing - updating the Universe, handling player input, and displaying the graphics - takes place on the same single thread. JS execution is just another part of updating the universe.