public < ReturnType > CompletableFuture < ReturnType > add ( Supplier < CompletableFuture < ? extends ReturnType > > toRun ) { CompletableFuture < ReturnType > result = new CompletableFuture <> ( ) ; CompletableFuture < ? > existingTask ; synchronized ( this . lock ) { Exceptions . checkNotClosed ( this . closed , this ) ; existingTask = this . lastTask ; if ( existingTask != null ) { // Another task is in progress. Queue up behind it, and make sure to only start the execution once // it is done. existingTask . whenCompleteAsync ( ( r , ex ) -> Futures . completeAfter ( toRun , result ) , this . executor ) ; } this . lastTask = result ; } if ( existingTask == null ) { // There is no previously running task. Need to trigger its execution now, outside of the synchronized block. Futures . completeAfter ( toRun , result ) ; } // Cleanup: if no more tasks are registered after this one, then clean up the field. result . whenComplete ( ( r , ex ) -> { synchronized ( this . lock ) { if ( this . lastTask != null && this . lastTask . isDone ( ) ) { this . lastTask = null ; } } } ) ; return result ; }
Queues up a new task to execute .