HEADS-UP: Threading restriction for Animation play, pause, stop now enforced USE CASE

John Hendrikx john.hendrikx at gmail.com
Mon Jan 22 23:52:42 UTC 2024


On 22/01/2024 17:46, Jurgen Doll wrote:
> I've been delving into the usage of `aborted` and `inTimePulse` as 
> mentioned by John and gleaned the following:
>
> 1. stop makes a best effort to abort the 'animation' if it is in the 
> process of execution.
> 2. `aborted` and `inTimePulse` are reset with every pulse.
>
> As to the options that John mentioned there's also a fourth:
>
> Accept my original proposal of fixing the NPE which is a known problem 
> and not worry about potential synchronization issues. I mean does it 
> really matter if play, stop, or pause miss a beat due to 
> synchronization, as the API does say this could happen. Furthermore it 
> doesn't appear as though the animation code can be left in some 
> strange inconsistent state as a result of this.


This is not a good idea, the NPE is a symptom of the problem, but there 
can be many more subtler problems (and new ones may surface after fixing 
the NPE) that can affect other animations making use of the shared 
structures involved.  For one thing, absent a method of synchronization, 
Java doesn't even guarantee that fields (or arrays) contain the same 
value for all threads.  So your thread may modify some state, but the FX 
thread wouldn't even know about it (or only partially), and may make 
assumptions about an incorrect state, and then make further changes 
based on incorrect assumptions.

A good example is that even a much simpler class like HashMap when 
accessed by multiple threads can get into a really bad state.  It will 
usually throw a "ConcurrentModificationException" (or perhaps a weird 
NPE or IllegalStateException) to alert you that you're using it wrong -- 
but those are the **best** case scenarios... In the worst case scenario, 
modifying a HashMap on multiple threads can result in an infinite loop 
-- this can happen when two modifications occur, both updating the same 
bucket, and the threads end up changing things in such a way that the 
entries point to each other.  Iterating it then (or accessing the wrong 
key) will cause an infinite loop (not hypothetical, I've had this happen).

I'm afraid that even the synchronization option I proposed is not very 
realistic due to the amount of work it will entail.  We'd need to trace 
all code paths that a call to play or stop could get to, and all those 
code paths would need to be made thread safe.

--John

>
> Jurgen
>
> On Mon, 22 Jan 2024 17:58:20 +0200, John Hendrikx 
> <john.hendrikx at gmail.com> wrote:
>
>     This seems like a reasonable use case, and perhaps this was the
>     original intent of the "asynchronous call" documentation.
>
>     The problem though is that the play/stop code does not seem to
>     take into account being called from a different thread (there are
>     several synchronization issues when I delved into that code).
>
>     So then there's a choice to make I think, either:
>
>     - Disallow it completely, and have users wrap it into
>     Platform.runLater()
>     - Have play/stop do the wrapping itself
>     - Make the methods thread safe by fixing the synchronization issues
>
>     --John
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/openjfx-dev/attachments/20240123/b4d35af6/attachment-0001.htm>


More information about the openjfx-dev mailing list