<div dir="ltr"><div dir="ltr">Hello all, I am new here but just wanted to ask a question & share a thought on StructuredTaskScope API.<div><br></div><div>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>)`. </div><div><br></div><div>Note </div><div>(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.</div><div>(2) Supplier<Joiner> in constructor because Joiner is stateful.</div><div><br></div><div>On the surface, there are a few advantages to the symmetric API</div><div>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 </div><div>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 -> {...}));`.</div><div>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.</div><div>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, </div><div>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.</div><div><br></div><div>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?</div><div><br></div><div>Subrahmanyam</div><div><br></div><div><br></div></div>
</div>