More Granular Bridging Functionality in Structured Concurrency

Peter Eastham petereastham at gmail.com
Mon Aug 18 15:53:38 UTC 2025


Hello Loom Team,

While reading over the other thread concerning Joiners, I finally loaded in
the EA for Java 25 and took a look over the Java Doc. While I'm liking what
I'm seeing (and need to play around with it more), I'm struggling to figure
out how to bridge older approaches with this.

For example, let's say Library A heavily utilizes a ThreadLocal. Because
it's a library we can't migrate to a ScopedValue or InheritableThreadLocal.
Currently the best bridge I've found is to provide a Configuration with a
custom ThreadFactory. This is a little heavy handed, as you're really only
wanting to hydrate a ThreadLocal, not manage the entire Thread.

Joiner#onFork(Subtask) looked promising, but the task is final, so it can't
be "wrapped" in something extra. Has an overload of
StructuredTaskScope#fork(Runnable/Callable) been looked at? Something like
the following (Typing is likely off, less concerned about that, just
showing what I'm thinking)
StructureTaskScope#fork(Function<Callable<? extends U>,Callabe<? extends
U>>, Callable<? extends U>)
StructuredTaskScope#fork(Function<Runnable,Runnable>, Runnable)

The idea being the overload lets a more granular customization than the
ThreadFactory, while being more obvious to the developer. I'll use an
example from the Java Doc with my fake situation.

final var threadLocalValue = ThreadLocalContext.get();
var injectLocalVariable = (callable) -> {
    ThreadLocalContext.set(threadLocalValue);
     return callable.call();
};
 try (var scope = StructuredTaskScope.open()) {

   // @link substring="fork" target="#fork(Callable)" :
   Subtask<String> subtask1 = scope.fork(injectLocalVariable, () ->
query(left));
   Subtask<Integer> subtask2 = scope.fork(injectLocalVariable, () ->
query(right));

   // throws if either subtask fails
    scope.join();  // @link substring="join" target="#join()"
    // both subtasks completed successfully
    // @link substring="get" target="Subtask#get()" :
    return new MyResult(subtask1.get(), subtask2.get());
 }

Once again I might have some of the particulars off, but the idea is
present. An overload with an AOP aspect, which can be leveraged to help
"bridge" older patterns.

Thoughts?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20250818/0e22c65a/attachment.htm>


More information about the loom-dev mailing list