On Fri, 17 Apr 2026 10:12:22 GMT, Marius Hanl <[email protected]> wrote:

>> Hi,
>> 
>>  From what I can see this type of behavior is inherent for an implementation 
>> in which when event is "fired" it is delivered right in place to listeners 
>> like in below pseudo code:
>>  
>> fireXXX()...
>> {
>>   for each listener invoke onXXX(....)
>> }
>> 
>> It is common for all awt and swing listeners and may, in plenty of 
>> conditions when nested firing occurs, lead to change in ordering of events. 
>> Yet, as far as I investigated it, and I did put a lot of work into it more 
>> than decade ago, it is a nature of in-place events firing. 
>> 
>> As I do see it, the very crucial assumption behind in-place firing is: 
>> _"when fireXXX returns, all listeners are notified"_. This is a strong 
>> indication of state and data consistency and only in-place firing may do it. 
>> Like in this pseudo code:
>> 
>> my_function()
>> {
>>   fireXXX() 
>>    _here I can assume that all listeners reacted to XXX_
>>   fireYYY()
>>    _here I can assume that all listeners reacted to XXX and YYY_
>> }
>> 
>> I can assume it regardless if `my_function()` was invoked in response to 
>> event or not.
>> 
>> This assumption is in a strict and conceptual conflict with _"when fireXXX 
>> is invoked the events reach all listeners in the same order as in which 
>> events were fired even if events are fired from inside of listener event 
>> handler"_.
>> 
>> Because now if my example function is invoked inside a listener those 
>> assumptions may be false.
>> 
>> Any attempt to achieve the goal of delivering events in their order of 
>> appearance will break the first assumption and it will lead to corruption of 
>> existing programs. In many, many funny ways.
>> 
>> Also any reliance on _"if listener A was registered before listener B, then 
>> A will get called before B"_ is a horribly bad idea. Please, do not even try 
>> to suggest it. Simply do not. There is no way to ensure that ordering in any 
>> system of some major complexity.
>> 
>> Any removing of "not necessary changes" in notification process is begging 
>> for troubles. It did change, and it did changed again. Preventing that first 
>> change from reaching the listeners is horrible idea, as listener is by 
>> definition getting every change, not just "some". 
>> 
>> In my practice, if I am worried about nested events and ordering problem, I 
>> do consciously decide to "decouple" them. Instead of firing an event in 
>> place I do, consciously, wrap them and delegate to the event pump (in case 
>> of awt - with invokeLater). Then I do know that they will reach the 
>> destination in order of firing, but I also do now that at...
>
>> Also any reliance on _"if listener A was registered before listener B, then 
>> A will get called before B"_ is a horribly bad idea. Please, do not even try 
>> to suggest it. Simply do not. There is no way to ensure that ordering in any 
>> system of some major complexity.
> 
> This is the case right now and will be after this PR.
> 
>> My recommendation is: if You really plan to change in-place firing to some 
>> more sophisticated algorithm **do not do it**. Not in a stable production 
>> code. Recommend, inform, educate about possible side effect, alternatively 
>> add like "orderedFireXXX" methods or something, but do not change such an 
>> essential algorithm. As you can see above delegation is a simple method 
>> which allows programmers using the library to decide what is important from 
>> them and what is not. If they see problems with ordering delegation solves 
>> it. If however you will build it in, they will have no way to ensure that if 
>> they have problems with:
> 
> I still don't get your point. This is about nested changes and that the old 
> value is misleading or simply incorrect. You talked about state consistency, 
> but currently, this can happen:
> 
> 
> myProperty.addListener((_, oldValue, newValue) -> {
>     // Here, oldValue MIGHT not be the last set value, but the value before 
> that.
>     // Instead of A -> B -> C
>     // oldValue can be A and newValue be C. Which is very bad when you want 
> to remove/unregister the old value.
> }
> 
> This PR corrects that to BE consistent, so the `oldValue` will be B in this 
> example. This is consistency for me.

@Maran23 

Thanks for through consideration.

-------------

PR Comment: https://git.openjdk.org/jfx/pull/1081#issuecomment-4295832153

Reply via email to