JEP 102 Process Updates revised API draft

Peter Levart peter.levart at gmail.com
Fri Feb 13 12:36:48 UTC 2015


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.Riggs at 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




More information about the core-libs-dev mailing list