Class SequencedFuture

java.lang.Object
com.tccc.kos.commons.util.concurrent.future.FutureWork
com.tccc.kos.commons.util.concurrent.future.SequencedFuture
All Implemented Interfaces:
Abortable, Cancelable, Terminable, Runnable

public class SequencedFuture extends FutureWork
Allows a list of individual futures to be run in sequence, where the overall state of SequencedFuture reflects the result of the sequence. All child futures are executed in the scheduler thread pool to ensure clean decoupling from event threads that may be used to finalize the state of the future.

The behavior of this future when a child fails can be configured using setFailState(). The behavior is defined as follows:

  • FAIL (default) : If any child is not successful, this future will not run any more children in the sequence and will report an end state of FAIL, using the reason code of the failed child.
  • ABORT : Identical to FAIL except the end state will be ABORT.
  • null : All child futures will be run regardless of failures. If any child fails, the end state of the sequence will be FAIL and the reason will be the reason from the first failed child.
Canceling this future cancels the currently active child.
Since:
1.0
Version:
2022-05-05
  • Constructor Details

    • SequencedFuture

      public SequencedFuture(String name)
      Creates a SequencedFuture to hold child futures. By default this stops after any child is not successful and then reports a failure. This can be changed using setFailState() .
      Parameters:
      name - the name (for diagnostic data)
  • Method Details

    • setFailState

      public void setFailState(FutureState state)
      Sets what this work should do if a child fails. By default this future fails if any child fails. This can be set to the following values:
      • null : Ignore all child errors and return successfully. Use childFailed() and getChildReason() to determine if a child failed and the associated reason.
      • FAIL : If any child fails, this future will stop and report fail.
      • ABORT : If any child fails, this future will stop and report abort.
      Parameters:
      state - either ABORT or FAIL
    • getIndex

      public int getIndex()
      Gets the index of the currently running future. If the sequence hasn't been started, the index is -1. If the sequence aborts, the index is the position of the future that failed. If the sequence runs to completion, the index is equal to the number of child futures.
    • setIndex

      public void setIndex(int index)
      Sets the index of the next child future to run. This must be set to the index before the desired future, as the index is pre-incremented before the next future is processed. For example, -1 will cause the first future in the list to be selected next, and 2 will cause the 3rd future to be selected.

      This exists for very specialized use cases. The most common is the ability to restart a sequence of futures that previously failed at a particular point. The failed index can be saved from the failed sequence and the index-1 can be set in a new identical sequence to restart at the failed step, or index can be used to start at the step after the failed step. Futures are not reusable so this only works when creating another identical sequence. It also only works in the case where the steps being skipped do not impact the rest of the futures in the sequence. This is the case when performing pour sequences and a primary use case is attempting to recover a long pour sequence given the previous steps were physically performed and thus don't necessarily need to be performed again.

      It is not possible to move the index backwards as this would cause an existing future to be used again.

    • skipToEnd

      public void skipToEnd()
      Sets the index to the end of the list. This causes the currently running child future to be the last in the sequence, as all remaining child futures will be skipped.

      This is useful when a sequence is performing a series of futures to achieve a particular success criteria, and once that criteria is met the remaining steps should be skipped.

    • setRunnable

      public FutureWork setRunnable(FutureRunnable runnable)
      Description copied from class: FutureWork
      Sets the runnable to be performed by the work. Unlike Java futures, it is possible for this work to complete without changing the end state. For example, this work may simply kick off a hardware process and some other mechanism is used to determine when that hardware is done, and that will change the state.

      This runnable can set the state, but callbacks won't be triggered until this function returns. This prevents race conditions between this code and any state event callbacks.

      If this runnable throws an exception, then the state is set to "aborted".

      Overrides:
      setRunnable in class FutureWork
      Parameters:
      runnable - the code to run as part of the work
    • fail

      public void fail(String reason)
      Description copied from class: FutureWork
      Fails the work with the specified reason.
      Overrides:
      fail in class FutureWork
      Parameters:
      reason - the fail reason
    • success

      public void success()
      Description copied from class: FutureWork
      Marks the work "successful".
      Overrides:
      success in class FutureWork
    • add

      public void add(FutureWork future)
      Adds a future to the sequence. Futures can only be added before the sequence has started.
      Parameters:
      future - the future to add to the sequence
    • add

      public void add(int index, FutureWork future)
      Adds a future to the specified location in the sequence following List semantics for insertion. Futures can only be added before the sequence has started.
      Parameters:
      index - where to insert the future
      future - the future to add to the sequence
    • childFailed

      public boolean childFailed()
      Returns true if any child failed or was aborted.
    • getChildReason

      public String getChildReason()
      Returns the reason code from the first failed or aborted child.
    • getEstimatedTimeMs

      public long getEstimatedTimeMs()
      When running in sequence, the estimated completion time is equal to the sum of all child tasks.
      Overrides:
      getEstimatedTimeMs in class FutureWork
      Returns:
      the estimated time of the operation