On 02/13/2015 11:02 AM, Paul Sandoz wrote:
Hi,
I am not sure everyone is aware of the sandbox repo that was setup, but it's
rather handy to see the changes:
http://hg.openjdk.java.net/jdk9/sandbox/jdk/rev/9a02f23ca186
On Feb 12, 2015, at 11:02 PM, Roger Riggs <roger.ri...@oracle.com> wrote:
Hi,
The Process and ProcessHandle API javadoc has been updated with the comments
and suggestions including the loose coupling of the Process from the
CompletableFutures
that are linked to process termination.
The improved implementation from Peter is incorporated and the method
descriptions
updated to reflect its behavior.
Updated javadoc: http://cr.openjdk.java.net/~rriggs/ph-apidraft/
I ran into a issue with the generics on CompletableFuture<? extends...>
completableFuture()
in ProcessHandle and Process.
The JDK compiles fine but the javac has a problem with the assignment in a test.
I'll come back to it after a long weekend in a warmer climate.
The use of wild cards in this context is generally discouraged because it
propagates to the caller as you have found out. You cannot do what you want for
the same reasons you cannot do this:
List<? extends Number> len = Arrays.asList(1, 2, 3);
// As this point we do not know the lower bound of elements in len
// Is it Integer or is it BigInteger?
List<Number> ln = len; // error
ln.add(new BigInteger(...)); // Potential heap pollution
Which means you are stuck if you want to provide CF<Process> and
CF<ProcessHandle> using the same overloaded method name.
It *is* inconvenient for the user to have to use wildcards in specifying
types:
CompletableFuture<? extends Process> cf = process.completableFuture();
...but it doesn't hinder the use of above 'cf' quite so much as 'len' in
List example above, since 'T' in CompletableFuture<T> is used mostly in
co-variant positions. The only methods that use it in contra-variant
positions are:
cf.getNow(?);
cf.complete(?);
cf.obtrudeValue(?);
of which I can imagine only the 1st one to be useful in
ProcessHandle/Process situations and even that one only with 'null' as
the argument which is allowed.
Other methods taking functions behave correctly with CompletableFuture<?
extends Process>, for example:
CompletableFuture<? extends Process> cf = process.completableFuture();
cf.handle((p, ex) -> {
p....
});
So it really boils down to what is less inconvenient: using wildcards in
type specifications or casting in cases like:
CompletableFuture<ProcessHandle> cf = process.completableFuture();
cf.handle((ph, ex) -> {
Process p = (Process) ph;
p....
});
Regards, Peter
You could do:
abstract class ProcessHandle<T extends ProcessHandle<T>> {
CompletableFuture<T> completableFuture() { ... }
}
class Process extends ProcessHandle<Process> {
CompletableFuture<Process> completableFuture() { ... }
}
But i am not sure it's worth it, especially as it exposes the sub-type of
process handle.
Paul.
Suggestions appreciated, Roger
p.s.
ws/jdk9-sandbox/jdk/test/java/lang/ProcessHandle/CompletionTest.java:67: error:
incompatible types: CompletableFuture<CAP#1> cannot be converted to
CompletableFuture<Process>
CompletableFuture<Process> future = p.completableFuture();
^
where CAP#1 is a fresh type-variable:
CAP#1 extends ProcessHandle from capture of ? extends ProcessHandle