Loom on Scala

Paul Bjorkstrand paul.bjorkstrand at gmail.com
Sun Nov 28 01:19:31 UTC 2021


>
>
>    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