Cool example. You are right.
We are migrating our code to asynchronous. :-)
On Thursday, 1 September 2016 13:59:45 UTC+1, Thomas Broyer wrote:
>
> Consider the following code:
>
> class Foo {
> String bar;
>
> synchronized String getBar() {
> if (bar == null) { // OK, we all know this is bad in the Java world,
> just bear with me for this sample code
> Future<String> realBar = …; // make a call that returns a
> CompletableFuture<String>
> bar = realBar.get();
> }
> return bar;
> }
> }
>
> You're proposing that it's somehow translated more or less to:
>
> var _symbol$bar = Symbol("Foo.bar");
> class Foo {
> async getBar() { // Note: transformed to 'async', no 'synchronized'
> if (this[_symbol$bar] == null) {
> var realBar = …;
> this[_symbol$bar] = await realBar.get(); // transformed to await
> }
> return this[_symbol$bar];
> }
> }
>
> Now imagine that while await⋅ing realBar.get(), getBar() is called again,
> on the same Foo instance (triggered by an event; for example, getBar() is
> called from a click handler, and the … returning the
> CompletableFuture<String> fetches some resource through HTTP).
> Looking at the original Java code, you'd expect that the second call is
> blocked until the first one terminates and releases the lock on the Foo
> object, so the first call would set the bar field and the second call would
> skip the 'if' branch.
> In JS though, the second call would *enter* the 'if' branch and make a
> second call; then, when each 'realBar' is completed, the private (through
> Symbol) property is set: twice; and if the call that returned a
> CompletableFuture<String> is stateful, that means the state has been
> modified twice.
> What kind of JS would you produce that'd prevent this from happening?
>
> I wouldn't trade "emulating CompletableFuture#get" for "bloated JS and a
> much more complex compiler". The Pareto rule tells us that you should just
> embrace asynchrony and live with only the non-blocking API (CompletionStage
> basically, plus getNow() and a few others).
>
> On Thursday, September 1, 2016 at 11:53:45 AM UTC+2, Ian Preston wrote:
>>
>> Interesting question, Thomas. I believe it should still work. Consider
>> the following:
>>
>> 1. A 'thread' comes into a method and obtains a lock on A.
>> 2. whilst holding the lock, it makes an async call to
>> CompletableFuture.get()
>> 3. Somewhere down the call stack some state which is guarded by the lock
>> on A is modified
>> On the JVM, either that lock is not re-entrant, in which case it is a
>> deadlock, or it is re-entrant and modifying the state is fine. We only have
>> one thread in JS so it is fine.
>>
>> Correct me if I'm wrong, but I believe this means that GWT could continue
>> to ignore synchronization, and get the same results assuming non
>> deadlocking programs, which can't be translated without a full emulator
>> like doppio anyway.
>>
>>
>> On Thursday, 1 September 2016 10:22:08 UTC+1, Thomas Broyer wrote:
>>>
>>>
>>>
>>> On Wednesday, August 31, 2016 at 11:58:51 PM UTC+2, Ian Preston wrote:
>>>>
>>>> One idea, which would be awesome from a user perspective, is the
>>>> following:
>>>>
>>>> Emulate CompletableFuture with native Promises. Then if the synchronous
>>>> cf.get() call is used, then translate that to await, and make the function
>>>> it is in async (in JS land). This would automatically change the signature
>>>> to a CompletableFuture, and then propagate this up to all callers. If it
>>>> makes it all the way to a function exposed with JsInterop, then that
>>>> function changes signature like the rest of them to return a promise. The
>>>> consumer of this function is obviously in JS and so can handle the promise
>>>> fine. This would equate to translating the synchronous java calls which
>>>> wait on a CompletableFuture (Promise) to return promises in JS. This
>>>> wouldn't require any changes to the Java code - it could continue in its
>>>> synchronous style, and not disrupt JVM based users of the same code.
>>>>
>>>
>>>> Thoughts?
>>>>
>>>
>>> 'await' is not synchronous, which means things can happen while
>>> awaiting, which could mutate state you'd rely on being immutable because
>>> you 'synchronized' it (in other words: how would your proposal work with
>>> the 'synchronized' keyword? GWT currently simply ignores 'synchronized'
>>> because JS is single-threaded anyway; now what if you call
>>> CompletableFuture#get() within a 'synchronized' function, possibly several
>>> levels deep in the call-stack?).
>>>
>>> There are good reasons why only async functions can call async
>>> functions, and only async functions can use the await keyword: explicit vs.
>>> implicit.
>>>
>>>
--
You received this message because you are subscribed to the Google Groups "GWT
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.