Style difference between StructuredTaskScope and ScopedValue APIs
Subrahmanyam V
vemana.github at gmail.com
Thu Aug 21 11:07:12 UTC 2025
Hello all, I am new here but just wanted to ask a question & share a
thought on StructuredTaskScope API.
What's the reason for the asymmetry between ScopedValue and
StructuredTaskScope APIs? Symmetry would suggest something like
`StructuredTaskPolicy.create(Supplier<Joiner>).call(Function<StructuredTaskScope,
T>)`.
Note
(1) StructuredTask_Policy_. The _call_ method on a Policy instance creates
a StructuredTaskScope, passes it to the Consumer/Function and closes it
before returning. Scoped Value propagation should behave like in the
current API.
(2) Supplier<Joiner> in constructor because Joiner is stateful.
On the surface, there are a few advantages to the symmetric API
1. [Immutable, well-defined Policies] StructuredTaskPolicy instances can be
immutable and shared across the application and its many threads. I can
imagine applications that use just 2 different policies {all-succeed,
any-succeed} across tens or hundreds of call sites
2. [Expressions] This API produces expressions instead of imperative
constructs and thus composes better. For example, I can do:
`return awaitUniterruptibly(() -> ALL_SUCCEED_POLICY.call(scope ->
{...}));`.
3. [Managed Scope lifecycle] Let the API manage scope.close() to free
resources instead of relying on the user. Hide lifecycle methods like
open() and close() and expose only fork() and join() on StructuredTaskScope
- the only ones that the user really cares about.
4. [Brevity that leads to Clarity] Nesting is feasible given brevity and
expressions (#2). For example, a single readable expression can express
that two subtasks should each succeed where the first task is itself a
StructuredTask made up of three subtasks any of which succeeds,
5. [Easier evolution] If StructuredTaskScope.Config API evolves (this seems
an active area of change), only Policy classes need to be evaluated by
users for any potential migration instead of every call-site. A handful of
immutable Policy classes is easier to manage than 10s or 100s of call-sites.
But, on reflection, an application can get all of the above benefits if it
sticks exclusively to the _race()_ or _runConcurrently()_ constructs from
the JEP. That is, instead of _Policy Classes_, it uses _Policy Methods_
like race(). Which begs the question - should the structured concurrency
API also expose Policy Methods as a first class API, one Policy Method per
Joiner?
Subrahmanyam
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20250821/fa37e105/attachment.htm>
More information about the loom-dev
mailing list