Loom on Scala
Eric Kolotyluk
eric at kolotyluk.net
Sun Nov 28 04:08:41 UTC 2021
@Paul Bjorkstrand <paul.bjorkstrand at gmail.com>
The vast majority of Java developers I have worked with that understand
> streams, also understand that they are lazy, and require a terminal
> operation.
>
In a polyglot world, where people are using multiple languages, expecting
people to always be an expert on all idioms is asking a lot. I am
advocating designs and idioms that are safer and more intuitive in the big
picture. Also, I can see the utility in not having to *always *having to
use lazy evaluation. WRT Koltin and Scala, Java is the oddball here.
Exceptions thrown by .close() are already handled by the catch block(s)
> attached to the try-with-resources.
>
Ah, right, I remember now encountering that scenario. Somehow I thought the
close() was done in the finally, but it's done before, so catchable. Thanks
for the correction.
I could see this being useful to have close() call join, in addition to it
> calling shutdown()
>
I don't think close() needs to call shutdown(), it just needs to detect if
all tasks have been completed, and call join() if they have not. Even
better, join() should be idempotent (and may be already). If people want to
shutdown(), it should be explicit.
I could see an additional parameter flag for StructuredExecutor.open()
> which changes the shutdown implementation from the default "interrupt" to
> "wait" aka join.
>
Sorry, I don't really see the utility in that. My preferred solution is to
use something like
structuredExecutor.joinUntil(Instant.now().plusSeconds(10));
catch the TimeoutException, and then call shutdown(). Unfortunately, that
won't work because the variable structuredExecutor is out of scope in the
catch. That's another Java pet peeve of mine.
Maybe something like
structuredExector.joinUntil(Instant.now().plusSeconds(10)).then( () -> {
structuredExector.shutdown(); structuredExector.join(); } )
But now I am really just fantasizing.
Cheers, Eric
On Sat, Nov 27, 2021 at 5:20 PM Paul Bjorkstrand <paul.bjorkstrand at gmail.com>
wrote:
>
>> 1. Java Collections need non-lazy monadic operators in addition to
>> Stream.
>>
>
> The vast majority of Java developers I have worked with that understand
> streams, also understand that they are lazy, and require a terminal
> operation. There may be some places where you could simplify some code with
> non-lazy operations, but every non-lazy operation is just a lazy operation
> that has an immediate terminal operation.
>
>
>> - Even in Java, join() should not be necessary because it is possible
>> to
>> wait for all Futures to be complete by other means.
>> - Indeed, close() should be able to detect if all tasks have
>> completed, even if join() has not been called.
>> - It is reasonable to expect StructuredExecutor#close to implicitly
>> join() if necessary,
>> - and throw an exception when appropriate, even if this requires
>> wrapping try-with-resources with another try to catch the
>> closing exception.
>> - yes, this would be really ugly, but we have trade-offs on where
>> ugly and beautiful present themselves
>>
>
> Exceptions thrown by .close() are already handled by the catch block(s)
> attached to the try-with-resources. There is no need for nesting. Example:
>
> class Main {
> public static void main(String args[]) {
> try (var twc = new ThrowsWhenClosed()) {
> // Do nothing
> } catch (Exception e) {
> System.out.println(e.getMessage());
> }
> }
> }
>
> class ThrowsWhenClosed implements AutoCloseable {
> public void close() throws Exception {
> throw new Exception("Always throws");
> }
> }
>
> This outputs "Always throws" to stdout when run.
>
>
>> - Yes, calling join() before close() is an extremely good practice for
>> many reasons, but it's not always semantically necessary.
>> - Is calling join() before close() a seatbelt where Loom is trying to
>> protect us from ourselves?
>> - Is it too much work to implement this otherwise?
>> - Is there some hard-core technical reason why this is necessary?
>
>
> I could see this being useful to have close() call join, in addition to it
> calling shutdown(), but shutdown() currently cancels futures and interrupts
> threads (
> https://github.com/openjdk/loom/blob/70b2a4f3723379ba7e36115651b2b18bd7acee5d/src/java.base/share/classes/java/util/concurrent/StructuredExecutor.java#L557
> )
>
> I could see an additional parameter flag for StructuredExecutor.open()
> which changes the shutdown implementation from the default "interrupt" to
> "wait" aka join.
>
>
> -Paul
>
More information about the loom-dev
mailing list