We need to add blocking methods to CompletionStage!

Martin Buchholz martinrb at google.com
Mon Sep 26 23:18:52 UTC 2016


On Mon, Sep 26, 2016 at 7:55 AM, Viktor Klang <viktor.klang at gmail.com>
wrote:

>
>>
> Test methods,
>>
>
> Yeah, I thought so as well, but it turns out that when you have tons of
> async tests, not being able to start new tests until either that timeout or
> result makes for a very slow test suite, so that's why most serious test
> frameworks are growing support for dealing with async code. Then all you
> want to be able to limit is work-in-progress (sloppily called parallelism)
>

I don't see any support in junit or testng for multi-threaded tests.  jtreg
uses the strategy of having a set of reusable JVM processes, each of which
is running only one test at a time, which provides "pretty good" isolation,
and seems to work well.


> main methods
>>
>
> That's a common scenario, but one that can be solved by having
> non-daemonic pooled worker threads.
>

Do you have docs for such a thread pool?


> and unix process reapers are all examples where it's reasonable to block
>> forever.
>>
>
> What about waitpid() + WNOHANG?
>

Are you suggesting periodic polling is better than blocking?


> PPPPS: "I think it's unreasonable to not provide this for users
>>> (especially when we can do so more efficiently)." <- If efficiency is
>>> desired then blocking is definitely not the right solution.
>>>
>>
>> What about efficiently providing isComplete?
>>
>
> In my experience isComplete is virtually useless without being able to
> extract the value, in which case you may as well introduce a non-blocking
> `Optional<T> poll()`
>

Do you support adding the Polling methods from
http://www.scala-lang.org/api/2.12.0-RC1/scala/concurrent/Future.html
to CompletionStage, i.e. isDone and getNow?


> The result may already be available without actually blocking.  It may
>> even be known to be available immediately.  One would like to get the value
>> without additional allocation.
>>
>
> I've seen that use-case :), and it tends to either be a situation where
> the value is available by pure luck (or…scheduling artifacts) or when one
> is keeping CompletionStages where strict values could be kept instead
> (think rebinding a value on completion).
>
> Reading what your'e writing, may I dare propose that what you're after is
> something along the lines of a: PollableCompletionStage which sits in
> between CompletionStage and CompletableFuture?
>

I've been waffling!  Right now, I'm leaning towards having Java APIs return
fully mutable CompletableFutures as Benjamin and Pavel suggested upthread.
Why?  Because a completion stage can be thought of as all of:
- a consumer of an upstream value
- a subscription to the event that makes the upstream value available, and
- the producer of a possible value for downstream consumers.
Cancellation could be interpreted as a request to unsubscribe from upstream
producer or a notification to downstream consumers that no value will be
forthcoming, or both.

Here's a problem with jdk9 minimalCompletionStage: even if you are happy
with the minimality of the source stage (perhaps it's shared) you might
want downstream stages to be mutable, but the methods such as thenApply
also create minimal completion stages.  If you want to convert to a mutable
future, you can try calling toCompletableFuture, but there's no guarantee
that will work, even if it doesn't throw UOE.  You can hand-construct a
CompletableFuture which is then completed in a Runnable via thenRun, but
then this is opaque to the CompletableFuture implementation, and
implementation features such as stack overflow prevention will be
ineffective.

So right now I'm OK with e.g. Process#onExit simply returning
CompletableFuture.


More information about the core-libs-dev mailing list