Re: RFR: 8290040: Provide simplified deterministic way to manage listeners [v8]

2022-12-01 Thread John Hendrikx
On Mon, 7 Nov 2022 20:29:16 GMT, Andy Goryachev  wrote:

>> John Hendrikx has updated the pull request incrementally with one additional 
>> commit since the last revision:
>> 
>>   Fix javadoc error
>
> I am not a native speaker, but to me `whenever` sounds event better than 
> `conditionOn`.  I might be wrong, but it does suggest that the binding 
> becomes active *again* when the condition turns `true`.

@andy-goryachev-oracle @mstr2 would one of you be willing to review this one as 
well?  It should be close to its final state now.

-

PR: https://git.openjdk.org/jfx/pull/830


Re: RFR: 8290040: Provide simplified deterministic way to manage listeners [v8]

2022-12-01 Thread Nir Lisker
On Wed, 26 Oct 2022 07:56:52 GMT, John Hendrikx  wrote:

>> This PR adds a new (lazy*) property on `Node` which provides a boolean which 
>> indicates whether or not the `Node` is currently part of a `Scene`, which in 
>> turn is part of a currently showing `Window`.
>> 
>> It also adds a new fluent binding method on `ObservableValue` dubbed `when` 
>> (open for discussion, originally I had `conditionOn` here).
>> 
>> Both of these together means it becomes much easier to break strong 
>> references that prevent garbage collection between a long lived property and 
>> one that should be shorter lived. A good example is when a `Label` is bound 
>> to a long lived property:
>> 
>>  
>> label.textProperty().bind(longLivedProperty.when(label::isShowingProperty));
>> 
>> The above basically ties the life cycle of the label to the long lived 
>> property **only** when the label is currently showing.  When it is not 
>> showing, the label can be eligible for GC as the listener on 
>> `longLivedProperty` is removed when the condition provided by 
>> `label::isShowingProperty` is `false`.  A big advantage is that these 
>> listeners stop observing the long lived property **immediately** when the 
>> label is no longer showing, in contrast to weak bindings which may keep 
>> observing the long lived property (and updating the label, and triggering 
>> its listeners in turn) until the next GC comes along.
>> 
>> The issue in JBS also describes making the `Subscription` API public, but I 
>> think that might best be a separate PR.
>> 
>> Note that this PR contains a bugfix in `ObjectBinding` for which there is 
>> another open PR: https://github.com/openjdk/jfx/pull/829 -- this is because 
>> the tests for the newly added method would fail otherwise; once it has been 
>> integrated to jfx19 and then to master, I can take the fix out.
>> 
>> (*) Lazy means here that the property won't be creating any listeners unless 
>> observed itself, to avoid problems creating too many listeners on 
>> Scene/Window.
>
> John Hendrikx has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Fix javadoc error

Looks good. Left a couple of minor comments.

modules/javafx.graphics/src/main/java/javafx/scene/Node.java line 1410:

> 1408: /**
> 1409:  * Indicates whether or not this {@code Node} is shown. A node is 
> considered shown if it's
> 1410:  * part of a {@code Scene} which is part of a {@code Window} whose

which -> that

modules/javafx.graphics/src/main/java/javafx/scene/Node.java line 1420:

> 1418:  * when it is no longer shown.
> 1419:  *
> 1420:  * @see ObservableValue#when(ObservableValue)

You don't need the `@see` since you linked it in the docs.

-

PR: https://git.openjdk.org/jfx/pull/830


Re: RFR: 8290040: Provide simplified deterministic way to manage listeners [v8]

2022-11-28 Thread John Hendrikx
On Wed, 26 Oct 2022 07:56:52 GMT, John Hendrikx  wrote:

>> This PR adds a new (lazy*) property on `Node` which provides a boolean which 
>> indicates whether or not the `Node` is currently part of a `Scene`, which in 
>> turn is part of a currently showing `Window`.
>> 
>> It also adds a new fluent binding method on `ObservableValue` dubbed `when` 
>> (open for discussion, originally I had `conditionOn` here).
>> 
>> Both of these together means it becomes much easier to break strong 
>> references that prevent garbage collection between a long lived property and 
>> one that should be shorter lived. A good example is when a `Label` is bound 
>> to a long lived property:
>> 
>>  
>> label.textProperty().bind(longLivedProperty.when(label::isShowingProperty));
>> 
>> The above basically ties the life cycle of the label to the long lived 
>> property **only** when the label is currently showing.  When it is not 
>> showing, the label can be eligible for GC as the listener on 
>> `longLivedProperty` is removed when the condition provided by 
>> `label::isShowingProperty` is `false`.  A big advantage is that these 
>> listeners stop observing the long lived property **immediately** when the 
>> label is no longer showing, in contrast to weak bindings which may keep 
>> observing the long lived property (and updating the label, and triggering 
>> its listeners in turn) until the next GC comes along.
>> 
>> The issue in JBS also describes making the `Subscription` API public, but I 
>> think that might best be a separate PR.
>> 
>> Note that this PR contains a bugfix in `ObjectBinding` for which there is 
>> another open PR: https://github.com/openjdk/jfx/pull/829 -- this is because 
>> the tests for the newly added method would fail otherwise; once it has been 
>> integrated to jfx19 and then to master, I can take the fix out.
>> 
>> (*) Lazy means here that the property won't be creating any listeners unless 
>> observed itself, to avoid problems creating too many listeners on 
>> Scene/Window.
>
> John Hendrikx has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Fix javadoc error

As per the discussion on the mailing list 
(https://mail.openjdk.org/pipermail/openjfx-dev/2022-November/036707.html) 
we've decided to go for `when` as the name for the new method in 
`ObservableValue`.

I've created a CSR now: https://bugs.openjdk.org/browse/JDK-8297719

-

PR: https://git.openjdk.org/jfx/pull/830


Re: RFR: 8290040: Provide simplified deterministic way to manage listeners [v8]

2022-11-07 Thread Andy Goryachev
On Wed, 26 Oct 2022 07:56:52 GMT, John Hendrikx  wrote:

>> This PR adds a new (lazy*) property on `Node` which provides a boolean which 
>> indicates whether or not the `Node` is currently part of a `Scene`, which in 
>> turn is part of a currently showing `Window`.
>> 
>> It also adds a new fluent binding method on `ObservableValue` dubbed `when` 
>> (open for discussion, originally I had `conditionOn` here).
>> 
>> Both of these together means it becomes much easier to break strong 
>> references that prevent garbage collection between a long lived property and 
>> one that should be shorter lived. A good example is when a `Label` is bound 
>> to a long lived property:
>> 
>>  
>> label.textProperty().bind(longLivedProperty.when(label::isShowingProperty));
>> 
>> The above basically ties the life cycle of the label to the long lived 
>> property **only** when the label is currently showing.  When it is not 
>> showing, the label can be eligible for GC as the listener on 
>> `longLivedProperty` is removed when the condition provided by 
>> `label::isShowingProperty` is `false`.  A big advantage is that these 
>> listeners stop observing the long lived property **immediately** when the 
>> label is no longer showing, in contrast to weak bindings which may keep 
>> observing the long lived property (and updating the label, and triggering 
>> its listeners in turn) until the next GC comes along.
>> 
>> The issue in JBS also describes making the `Subscription` API public, but I 
>> think that might best be a separate PR.
>> 
>> Note that this PR contains a bugfix in `ObjectBinding` for which there is 
>> another open PR: https://github.com/openjdk/jfx/pull/829 -- this is because 
>> the tests for the newly added method would fail otherwise; once it has been 
>> integrated to jfx19 and then to master, I can take the fix out.
>> 
>> (*) Lazy means here that the property won't be creating any listeners unless 
>> observed itself, to avoid problems creating too many listeners on 
>> Scene/Window.
>
> John Hendrikx has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Fix javadoc error

I am not a native speaker, but to me `whenever` sounds event better than 
`conditionOn`.  I might be wrong, but it does suggest that the binding becomes 
active *again* when the condition turns `true`.

-

PR: https://git.openjdk.org/jfx/pull/830


Re: RFR: 8290040: Provide simplified deterministic way to manage listeners [v8]

2022-11-06 Thread John Hendrikx
On Wed, 26 Oct 2022 07:56:52 GMT, John Hendrikx  wrote:

>> This PR adds a new (lazy*) property on `Node` which provides a boolean which 
>> indicates whether or not the `Node` is currently part of a `Scene`, which in 
>> turn is part of a currently showing `Window`.
>> 
>> It also adds a new fluent binding method on `ObservableValue` dubbed `when` 
>> (open for discussion, originally I had `conditionOn` here).
>> 
>> Both of these together means it becomes much easier to break strong 
>> references that prevent garbage collection between a long lived property and 
>> one that should be shorter lived. A good example is when a `Label` is bound 
>> to a long lived property:
>> 
>>  
>> label.textProperty().bind(longLivedProperty.when(label::isShowingProperty));
>> 
>> The above basically ties the life cycle of the label to the long lived 
>> property **only** when the label is currently showing.  When it is not 
>> showing, the label can be eligible for GC as the listener on 
>> `longLivedProperty` is removed when the condition provided by 
>> `label::isShowingProperty` is `false`.  A big advantage is that these 
>> listeners stop observing the long lived property **immediately** when the 
>> label is no longer showing, in contrast to weak bindings which may keep 
>> observing the long lived property (and updating the label, and triggering 
>> its listeners in turn) until the next GC comes along.
>> 
>> The issue in JBS also describes making the `Subscription` API public, but I 
>> think that might best be a separate PR.
>> 
>> Note that this PR contains a bugfix in `ObjectBinding` for which there is 
>> another open PR: https://github.com/openjdk/jfx/pull/829 -- this is because 
>> the tests for the newly added method would fail otherwise; once it has been 
>> integrated to jfx19 and then to master, I can take the fix out.
>> 
>> (*) Lazy means here that the property won't be creating any listeners unless 
>> observed itself, to avoid problems creating too many listeners on 
>> Scene/Window.
>
> John Hendrikx has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Fix javadoc error

I think the most important open point for this PR is the name for the new 
operation to be added to `ObservableValue`.  Currently in this PR it is called 
`when`.

Some background first to help with the decision; all fluent methods follow this 
basic pattern:

 source.operation( ... ) -> new target observable

The proposed operation has a `ObservabeValue` parameter as its 
condition.  It allows you to create a new observable that has the same value as 
its source, unless the associated condition is `false`, in which case it 
contains the last seen value of the source (it does **not** change to `null` or 
empty, so an `orElse` cannot be used to change the value when the condition is 
`false`.).  

The proposed operation differs from the other three available fluent methods 
(`map`, `flatMap` and `orElse`) that in order to determine its result it does 
not need to continuously observe its source -- the source value has no bearing 
on whether the target will or will not reflect the source value, only the 
condition controls this. This is unlike `map` for example, which **must** 
evaluate the source value to determine the target value, and also unlike a 
`filter` method (as seen in `Optional` or `Stream`) which must evaluate the 
source value to see if it passes the filter predicate in order to determine 
whether the target uses the source value or becomes empty.

Because the source value is not needed to reach a decision for this new 
proposed operation, there is no need to constantly observe the source value for 
changes.  When the conditional is `false`, the observer can be removed until 
such time that the conditional becomes `true`.  This is in contrast to `map`, 
`orElse` or a potential future `filter` operation which have no choice but to 
observe their source at all times in order to correctly calculate their target 
value.

There is also a clear intention that the condition changes at some point in the 
future and that it need not be a one time change (when condition becomes `true` 
again, the target again starts tracking the source value); if the condition 
never changes there is no need to use this new operation as one can just use 
the source observable (if condition is always `true`) or it becomes a constant 
value (if condition is always `false`).

A quick overview of the differences between the existing and new operation:

|Time|x|condition|x.map(x -> x * 2)|x.filter(x -> x % 2 == 
0)|x.operation(condition)|
|:-:|:-:|:-:|:-:|:-:|:-:|
|0|2|true|4|2|2|
|1|2|false|4|2|2|
|2|3|false|6|null (empty)|2|
|3|3|true|6|null (empty)|3|
|4|4|true|8|4|4|

## Options for the name of this new operation

The full signature for the newly proposed operation is:

ObservableValue __operation__(ObservableValue condition)

Possible options:

1. `while`, `if`
2. `conditionOn` 

Re: RFR: 8290040: Provide simplified deterministic way to manage listeners [v8]

2022-10-26 Thread John Hendrikx
> This PR adds a new (lazy*) property on `Node` which provides a boolean which 
> indicates whether or not the `Node` is currently part of a `Scene`, which in 
> turn is part of a currently showing `Window`.
> 
> It also adds a new fluent binding method on `ObservableValue` dubbed `when` 
> (open for discussion, originally I had `conditionOn` here).
> 
> Both of these together means it becomes much easier to break strong 
> references that prevent garbage collection between a long lived property and 
> one that should be shorter lived. A good example is when a `Label` is bound 
> to a long lived property:
> 
>  
> label.textProperty().bind(longLivedProperty.when(label::isShowingProperty));
> 
> The above basically ties the life cycle of the label to the long lived 
> property **only** when the label is currently showing.  When it is not 
> showing, the label can be eligible for GC as the listener on 
> `longLivedProperty` is removed when the condition provided by 
> `label::isShowingProperty` is `false`.  A big advantage is that these 
> listeners stop observing the long lived property **immediately** when the 
> label is no longer showing, in contrast to weak bindings which may keep 
> observing the long lived property (and updating the label, and triggering its 
> listeners in turn) until the next GC comes along.
> 
> The issue in JBS also describes making the `Subscription` API public, but I 
> think that might best be a separate PR.
> 
> Note that this PR contains a bugfix in `ObjectBinding` for which there is 
> another open PR: https://github.com/openjdk/jfx/pull/829 -- this is because 
> the tests for the newly added method would fail otherwise; once it has been 
> integrated to jfx19 and then to master, I can take the fix out.
> 
> (*) Lazy means here that the property won't be creating any listeners unless 
> observed itself, to avoid problems creating too many listeners on 
> Scene/Window.

John Hendrikx has updated the pull request incrementally with one additional 
commit since the last revision:

  Fix javadoc error

-

Changes:
  - all: https://git.openjdk.org/jfx/pull/830/files
  - new: https://git.openjdk.org/jfx/pull/830/files/ea546998..46f206aa

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jfx=830=07
 - incr: https://webrevs.openjdk.org/?repo=jfx=830=06-07

  Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod
  Patch: https://git.openjdk.org/jfx/pull/830.diff
  Fetch: git fetch https://git.openjdk.org/jfx pull/830/head:pull/830

PR: https://git.openjdk.org/jfx/pull/830