public interface IAction<PHANTOM_OUT> extends IBaseAction<PHANTOM_OUT> {
    /**
     * Execute the action
     * <p>
     * If parameters need to be passed in, see for example {@link IActionOne}
     *
     * @throws Exception                                  to transition to {@link com.reactivecascade.i.IAltFuture.StateError}
     * @throws java.util.concurrent.CancellationException to {@link com.reactivecascade.i.IAltFuture.StateCancelled}
     */
    void call() throws Exception;
} public interface IActionOne<IN> extends IBaseAction<IN> {
    /**
     * Execute the action
     *
     * @param in input
     * @throws Exception                                  to transition to {@link com.reactivecascade.i.IAltFuture.StateError}
     * @throws java.util.concurrent.CancellationException to {@link com.reactivecascade.i.IAltFuture.StateCancelled}
     */
    void call(@NonNull IN in) throws Exception;
} public interface IActionOneR<IN, OUT> extends IBaseAction<OUT> {
    /**
     * Execute the action
     *
     * @param in the in argument for the function
     * @return the result of computation which is often the next in used in a functional chain
     * @throws Exception                                  that will trigger a transition to {@link com.reactivecascade.i.IAltFuture.StateError}
     * @throws java.util.concurrent.CancellationException to {@link com.reactivecascade.i.IAltFuture.StateCancelled}
     */
    @NonNull
    OUT call(@NonNull IN in) throws Exception;
} public interface IActionR<OUT> extends Callable<OUT>, IBaseAction<OUT> {
    /**
     * Execute the action
     *
     * @return the result of the action
     * @throws Exception                                  to transition to {@link com.reactivecascade.i.IAltFuture.StateError}
     * @throws java.util.concurrent.CancellationException to {@link com.reactivecascade.i.IAltFuture.StateCancelled}
     */
    @Override // Callable
    @NonNull
    OUT call() throws Exception;
} public interface IAltFuture<IN, OUT> extends ICancellable, ISafeGettable<OUT>, IAsyncOrigin {
    /**
     * A method which returns a new (unforked) <code>IAltFuture</code> should follow the naming conventiond <code>..Async</code>
     * and be annotated <code>@CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)</code> to {@link CheckResult} that
     * it is either stored or manually {@link #fork()}ed.
     * <p>
     * TODO This annotation is not ideal for disambiguating all cases, look at creating a new one
     */
    String CHECK_RESULT_SUGGESTION = "IAltFuture#fork()";

    /**
     * Find which thread pool and related support functions are used
     *
     * @return thread group
     */
    @NonNull
    IThreadType getThreadType();

    /**
     * Find if the final, immutable state has been entered either with a successful result or an error
     * code
     *
     * @return <code>true</code> once final state has been determined
     */
    boolean isDone();

    /**
     * Find if this object has already been submitted to an executor. Execution may finish at any time,
     * or already have finished if this is true.
     *
     * @return <code>true</code> once queued for execution
     */
    boolean isForked();

    /**
     * Place this {@link IAltFuture} in the ready-to-run-without-blocking
     * queue of its {@link com.reactivecascade.i.IThreadType}. If there is a {@link #getUpchain()}
     * subscribe that will be forked instead until finding one where {@link #isDone()} is false.
     *
     * @return <code>this</code>, which is usually the <code>IAltFuture</code> which was actually forked.
     * The fork may be indirect and only after other items complete because there is a search upchain
     * (which may be a different branch spliced into the current chain) to find the first unforked from.
     */
    @NonNull
    IAltFuture<IN, OUT> fork();

    /**
     * Find the previous step in the chain.
     * <p>
     * Once {@link #isDone()}, this may return <code>null</code> even if there was a previous alt future
     * at one point. This is done to allow a chain to reduce peak load and increase memory throughput
     * by freeing memory of previous steps as it goes.
     *
     * @return the previous {@link IAltFuture} in the chain, or <code>null</code> if this is currently
     * the head of the chain
     */
    @Nullable
    IAltFuture<?, ? extends IN> getUpchain();

    /**
     * This is done for you when you add functions to a chain. You do not need to call it yourself.
     * <p>
     * The implementation may call this multiple times to support merging chains. This happens most
     * often when a method returns the tail of a section of chain. The returned from in this case is
     * a new chain link stopping the merged chain section which might start burning before the merger
     * is created to not burn past the merger point until the primary chain reaches that point also.
     *
     * @param altFuture the previous alt future in the chain to which this is attached
     */
    void setUpchain(@NonNull IAltFuture<?, ? extends IN> altFuture);

    /**
     * Notification from an up-chain {@link IAltFuture} that the stream is broken
     * and will not complete normally. This RunnableAltFuture will be set to an error state.
     * <p>
     * If an mOnError or catch method has been defined, it will be
     * notified of the original cause of the failure. If the RunnableAltFuture's mOnError method consumes the error
     * (returns <code>true</code>), subscribe anything else down-chain methods will be notified with
     * {@link #onCancelled(StateCancelled)} instead.
     *
     * @param stateError the state indicating the reason and origin of the exception
     * @throws Exception if there is a problem performing synchronous downchain notifications
     */
    void onError(@NonNull StateError stateError) throws Exception;

    /**
     * Notification indicates an up-chain {@link IAltFuture} has been cancelled.
     * This RunnableAltFuture will be set to a cancelled state and not be given a chance to complete normally.
     * All down-chain AltFutures will similarly be notified that they were cancelled.
     *
     * @param stateCancelled the state indicating the reason and origin of cancellation
     * @throws Exception if there is a problem performing synchronous downchain notifications
     */
    void onCancelled(@NonNull StateCancelled stateCancelled) throws Exception;

    /**
     * Switch following (downchain) actions to run on the specified {@link IThreadType}
     *
     * @param theadType the thread execution group to change to for the next chain operation
     * @return the previous chain link alt future from continuing the chain on the new {@link IThreadType}
     */
    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    IAltFuture<?, OUT> on(@NonNull IThreadType theadType);

    /**
     * Execute the mOnFireAction after this <code>RunnableAltFuture</code> finishes.
     *
     * @param action function to be performed, often a lambda statement
     * @return an alt future representing the eventual output value of the action
     */
    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    IAltFuture<OUT, OUT> then(@NonNull IAction<OUT> action);

    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    @SuppressWarnings("unchecked")
    ISettableAltFuture<OUT> then(@NonNull IAction<? extends OUT>... actions);

    /**
     * Execute the action after this <code>RunnableAltFuture</code> finishes.
     *
     * @param action function to be performed, often a lambda statement
     * @return an alt future representing the eventual output value of the action
     */
    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    IAltFuture<OUT, OUT> then(@NonNull IActionOne<OUT> action);

    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    @SuppressWarnings("unchecked")
    ISettableAltFuture<OUT> then(@NonNull IActionOne<OUT>... actions);

    /**
     * Execute the mOnFireAction after this <code>RunnableAltFuture</code> finishes.
     *
     * @param action function to be performed, often a lambda statement
     * @return an alt future representing the eventual output value of the action
     */
    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    <DOWNCHAIN_OUT> IAltFuture<OUT, DOWNCHAIN_OUT> then(@NonNull IActionR<DOWNCHAIN_OUT> action);

    /**
     * Start an action wrapped as an alt futre after this alt future completes. This next alt future
     * may be on a different {@link IThreadType} thread pool.
     * <p>
     * Multiple altFutures may be chained after the current alt future. They will be fork()ed in the
     * orderin which they were attached. Depending on their thread type, the resulting execution may
     * be concurrent or serial.
     *
     * @param altFuture       the next action in the chain
     * @param <DOWNCHAIN_OUT> the type that the OUT value will be mapped to. This may not be a mapping alt future, in which case the type DOWNCHAIN_OUT = OUT and the value is also identical
     * @return altFuture
     */
    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    <DOWNCHAIN_OUT> IAltFuture<OUT, DOWNCHAIN_OUT> then(@NonNull IAltFuture<OUT, DOWNCHAIN_OUT> altFuture);

    /**
     * Execute the mOnFireAction after this <code>RunnableAltFuture</code> finishes.
     *
     * @param action          function to be performed, often a lambda statement
     * @param <DOWNCHAIN_OUT> the type that the OUT value will be mapped to
     * @return an alt future value representing the eventual output from the mapping function
     */
    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    <DOWNCHAIN_OUT> IAltFuture<OUT, DOWNCHAIN_OUT> map(@NonNull IActionOneR<OUT, DOWNCHAIN_OUT> action);

    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    @SuppressWarnings("unchecked")
    <DOWNCHAIN_OUT> IAltFuture<OUT, DOWNCHAIN_OUT>[] map(@NonNull IActionOneR<OUT, DOWNCHAIN_OUT>... actions);

    /**
     * Pause execution of this chain for a fixed time interval. Other chains will be able to execute
     * in the meanwhile- no threads are blocked.
     * <p>
     * Note that the chain realizes immediately in the event of {@link #cancel(String)} or a runtime error
     *
     * @param sleepTime to pause the chain, in timeUnit values
     * @param timeUnit  to pause
     * @return the input value from upchain
     */
    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    ISettableAltFuture<OUT> sleep(long sleepTime,
                                  @NonNull TimeUnit timeUnit);

    /**
     * Continue to next step(s) in the chain only after the {@link IAltFuture} being waited for is complete. The from
     * is not propaged in the chain, but if there is an error that will be adopted into this chain.
     *
     * @param altFuture to pause this chain until it <code>{@link #isDone()}</code>
     * @return the upchain value of this chain, execution held until the other alt future completes
     */
//    @NonNull
//    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
//    ISettableAltFuture<OUT> await(@NonNull IAltFuture<?, ?> altFuture);

    /**
     * Continue chain execution once all upchain futures realize and have completed their side effects.
     * <p>
     * The await operation will be cancelled or exception state and trigger {@link #onError(IActionOne)}
     * if <em>any</em> of the joined operations have a problem running to completion.
     *
     * @param altFutures to pause this chain until they are done (<code>{@link #isDone()}</code>)
     * @return the upchain value of this chain, execution held until other alt futures complete
     */
    @NonNull
    @SuppressWarnings("unchecked")
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    ISettableAltFuture<OUT> await(@NonNull IAltFuture<?, ?>... altFutures);

    /**
     * Pass through to the next function only if element meet a logic test, otherwise {@link #cancel(String)}
     *
     * @param action function to be performed, often a lambda statement
     * @return the input value, now guaranteed to meet the logic test
     */
    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    IAltFuture<IN, IN> filter(@NonNull IActionOneR<IN, Boolean> action);

    /**
     * Set the reactiveTarget (one time only) when this is asserted
     *
     * @param reactiveTarget
     * @return <code>this</code>
     */
    @NonNull
    IAltFuture<OUT, OUT> set(@NonNull IReactiveTarget<OUT> reactiveTarget);

    /**
     * Add an action which will be performed if this AltFuture or any AltFuture up-chain either has
     * a runtime error or is {@link #cancel(String)}ed.
     * <p>
     * This is typically a user notification or cleanup such as removing an ongoing process indicator (spinner).
     *
     * @param action function to be performed, often a lambda statement
     * @return <code>this</code>
     */
    @NonNull
    ISettableAltFuture<OUT> onError(@NonNull IActionOne<Exception> action);

    /**
     * Add an action which will be performed if this AltFuture or any AltFuture up-chain either has
     * a runtime error or is {@link #cancel(String)}ed.
     * <p>
     * This is typically used for cleanup such as changing the screen to notify the user or remove
     * an ongoing process indicator (spinner).
     *
     * @param action function to be performed, often a lambda statement
     * @return <code>this</code>
     */
    @NonNull
    ISettableAltFuture<OUT> onCancelled(@NonNull IActionOne<String> action);
} public interface IBindingContext<T> {
    /**
     * Check if closed
     *
     * @return <code>true</code> if {@link #closeBindingContext(Object)} has not been called
     */
    boolean isOpen();

    /**
     * Trigger start of all binding context actions
     *
     * @param t the type of object controlling this binding's lifecycle
     */
    void openBindingContext(T t);

    /**
     * Trigger end of all binding context actions
     * @param t the type of object controlling this binding's lifecyle
     */
    void closeBindingContext(T t);

    /**
     * Add an action to be performed synchronously before the binding context open finishes
     *
     * @param action performed when binding starts
     */
    void onOpen(@NonNull IActionOne<T> action);

    /**
     * Add an action to be performed synchronously before the binding context close finishes
     *
     * @param action performed when binding ends
     */
    void onClose(@NonNull IActionOne<T> action);
} public interface IRunnableAltFuture<IN, OUT> extends IAltFuture<IN, OUT>, Runnable {
} public interface ISettableAltFuture<T> extends IAltFuture<T, T>, ISettable<T> {
} public interface IThreadType extends INamed {
    /**
     * Determine if this asynchronous implementation guarantees in-order execution such that one
     * mOnFireAction completes before the next begins.
     *
     * @return <code>true</code> if the exector associated with this thread type is single threaded or
     * otherwise guarantees that the previous item in the queue has completed execution before the next
     * item begins.
     */
    boolean isInOrderExecutor();

    /**
     * Run this mOnFireAction after all previously submitted actions (FIFO).
     *
     * @param action the work to be performed
     * @param <IN>   the type of input argument expected by the action
     */
    @NotCallOrigin
    <IN> void execute(@NonNull IAction<IN> action);

    /**
     * Execute a runnable. Generally this is an action that has already been error-catch wrapped using for example
     * {@link #wrapActionWithErrorProtection(IAction)}
     *
     * @param runnable
     */
    @NotCallOrigin
    void run(@NonNull Runnable runnable);

    /**
     * Run this mOnFireAction after all previously submitted actions (FIFO).
     *
     * @param action        the work to be performed
     * @param onErrorAction work to be performed if the action throws a {@link Throwable}
     * @param <OUT>         the type of input argument expected by the action
     */
    @NotCallOrigin
    <OUT> void run(@NonNull IAction<OUT> action,
                   @NonNull IActionOne<Exception> onErrorAction);

    /**
     * If this ThreadType permits out-of-order execution, run this mOnFireAction before any previously
     * submitted tasks. This is a LIFO mOnFireAction. Think of it as a "high priority" or "depth first" solution
     * to complete a sequence of actions already started before opening a new sequence of actions.
     * <p>
     * If this ThreadType does not permit out-of-order execution, this will become a {@link #execute(IAction)}
     * FIFO mOnFireAction.
     *
     * @param <OUT>  the type of input argument expected by the action
     * @param action the work to be performed
     */
    @NotCallOrigin
    <OUT> void runNext(@NonNull IAction<OUT> action);

    /**
     * Like {@link #run(Runnable)} but the task is queued LIFO as the first item of the
     * {@link java.util.Deque} if this executor supports out of order execution.
     * <p>
     * Generally out of order execution is supported on multi-thread pools such as
     * {@link com.reactivecascade.Async#WORKER} but not strictly sequential operations such as write to file.
     * <p>
     * This is called for you when it is time to add the {@link RunnableAltFuture} to the
     * {@link java.util.concurrent.ExecutorService}. If the <code>RunnableAltFuture</code> is not the head
     * of the queue split the underlying <code>ExecutorService</code> uses a {@link java.util.concurrent.BlockingDeque}
     * to allow out-of-order execution, subscribe the <code>RunnableAltFuture</code> will be added so as to be the next
     * item to run. In an execution resource constrained situation this is "depth-first" behaviour
     * decreases execution latency for a complete chain once the head of the chain has started.
     * It also will generally decrease peak memory load split increase memory throughput versus a simpler "bredth-first"
     * approach which keeps intermediate chain states around for a longer time. Some
     * {@link com.reactivecascade.i.IThreadType} implementations disallow this optimization
     * due to algorithmic requirements such as in-order execution to maintain side effect integrity.
     * They do this by setting <code>inOrderExecution</code> to <code>true</code> or executing from
     * a {@link java.util.concurrent.BlockingQueue}, not a {@link java.util.concurrent.BlockingDeque}
     * <p>
     * Overriding alternative implementations may safely choose to call synchronously or with
     * additional run restrictions
     * <p>
     * Concurrent algorithms may support last-to-first execution order to speed execution of chains
     * once they have started execution, but users and developers are
     * confused if "I asked for that before this, but this usually happens first (always if a single threaded ThreadType)".
     *
     * @param runnable
     */
    @NotCallOrigin
    void runNext(@NonNull Runnable runnable);

    /**
     * The same as {@link #runNext(IAction)}, however it is only moved if it is already in the
     * queue. If it is not found in the queue, it will not be added.
     * <p>
     * This is part of singleton executor pattern where an action that can be queued multiple
     * times should be executing or queued only once at any given time.
     *
     * @param runnable the work to be performed
     * @return <code>true</code> if found in the queue and moved
     */
    boolean moveToHeadOfQueue(@NonNull Runnable runnable);

    /**
     * Run this mOnFireAction after all previously submitted actions (FIFO).
     *
     * @param action        the work to be performed
     * @param onErrorAction work to be performed if the action throws a {@link Throwable}
     * @param <OUT>         the type of input argument expected by the action
     */
    <OUT> void runNext(@NonNull IAction<OUT> action,
                       @NonNull IActionOne<Exception> onErrorAction);

    /**
     * Convert this action into a runnable which will catch and handle
     *
     * @param action the work to be performed
     * @param <IN>   the type of input argument expected by the action
     * @return a Runnable which invokes the action
     */
    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    <IN> Runnable wrapActionWithErrorProtection(@NonNull IAction<IN> action);

    /**
     * Convert this action into a runnable
     *
     * @param action        the work to be performed
     * @param onErrorAction
     * @param <IN>          the type of input argument expected by the action
     * @return
     */
    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    <IN> Runnable wrapActionWithErrorProtection(@NonNull IAction<IN> action,
                                                @NonNull IActionOne<Exception> onErrorAction);

    /**
     * Complete the action asynchronously.
     * <p>
     * No input values are fed in from the chain.
     *
     * @param action the work to be performed
     * @param <IN>   the type of input argument expected by the action
     * @return a chainable handle to track completion of this unit of work
     */
    @NonNull
    <IN> IAltFuture<IN, IN> then(@NonNull IAction<IN> action);

    /**
     * Complete the action asynchronously.
     * <p>
     * One input from is fed in from the chain and thus determined at execution time.
     *
     * @param action the work to be performed
     * @param <IN>   the type of input argument expected by the action
     * @return
     */
    @NonNull
    <IN> IAltFuture<IN, IN> then(@NonNull IActionOne<IN> action);

    /**
     * Complete several actions asynchronously.
     * <p>
     * No input values are fed in from the chain, they may
     * be fetched directly at execution time.
     *
     * @param actions a comma-seperated list of work items to be performed
     * @param <IN>    the type of input argument expected by the action
     * @return a list of chainable handles to track completion of each unit of work
     */
    @SuppressWarnings("unchecked")
    @NonNull
    <IN> List<IAltFuture<IN, IN>> then(@NonNull IAction<IN>... actions);

    /**
     * Set the chain from to a from which can be determined at the time the chain is built.
     * This is most suitable for starting a chain. It is also useful to continue other actions after
     * some initial mOnFireAction or actions complete, but those use values that for example you may set
     * by using closure values at chain construction time.
     *
     * @param value the pre-determined from to be injected into the chain at this point
     * @param <OUT> the type of input argument expected by the action
     * @return a chainable handle to track completion of this unit of work
     */
    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    <OUT> ISettableAltFuture<OUT> from(@NonNull OUT value);

    /**
     * Set the chain to start with a value which will be set in the future.
     * <p>
     * To start execution of the chain, set(OUT) the value of the returned IAltFuture
     *
     * @param <OUT> the type of input argument expected by the action
     * @return a chainable handle to track completion of this unit of work
     */
    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    <OUT> ISettableAltFuture<OUT> from();

    /**
     * Complete the mOnFireAction asynchronously
     *
     * @param action the work to be performed
     * @param <IN>   the type of input argument expected by the action
     * @param <OUT>  the type of output returned by the action
     * @return a chainable handle to track completion of this unit of work
     */
    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    <IN, OUT> IAltFuture<IN, OUT> then(@NonNull IActionR<OUT> action);

    /**
     * Perform several actions which need no input from (except perhaps values from closure escape),
     * each of which returns a from of the same type, and return those results in a list.
     *
     * @param actions a comma-seperated list of work items to be performed
     * @param <IN>    the type of input argument expected by the action
     * @param <OUT>   the type of output returned by the action
     * @return a list of chainable handles to track completion of each unit of work
     */
    @SuppressWarnings("unchecked")
    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    <IN, OUT> List<IAltFuture<IN, OUT>> then(@NonNull IActionR<OUT>... actions);

    /**
     * Transform input A to output T, possibly with other input which may be fetched directly in the function.
     *
     * @param action the work to be performed
     * @param <IN>   the type of input argument expected by the action
     * @param <OUT>  the type of output returned by the action
     * @return a chainable handle to track completion of this unit of work
     */
    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    <IN, OUT> IAltFuture<IN, OUT> map(@NonNull IActionOneR<IN, OUT> action);

    /**
     * Transform input A to output T using each of the several actions provided and return
     * the result as a list of the transformed values.
     *
     * @param actions a comma-seperated list of work items to be performed
     * @param <IN>    the type of input argument expected by the action
     * @param <OUT>   the type of output returned by the action
     * @return a list of chainable handles to track completion of each unit of work
     */
    @SuppressWarnings("unchecked")
    @NonNull
    @CheckResult(suggest = IAltFuture.CHECK_RESULT_SUGGESTION)
    <IN, OUT> List<IAltFuture<IN, OUT>> map(@NonNull IActionOneR<IN, OUT>... actions);

    /**
     * Place this the {@link IRunnableAltFuture} implementation such as the default {@link RunnableAltFuture}
     * in to an execution queue associated with this {@link IThreadType}.
     * <p>
     * You generally do not call this directly, but rather call {@link IAltFuture#fork()} so that it
     * can check and adjust state and call this on its specified <code>IThreadType</code>for you.
     *
     * @param runnableAltFuture the holder for an evaluate-once-a-discard function which is ready to be queued because it can now be evaluated in a non-blocking manner
     * @param <IN>              the type of input argument expected by the action
     * @param <OUT>             the type of output returned by the action
     */
    <IN, OUT> void fork(@NonNull IRunnableAltFuture<IN, OUT> runnableAltFuture);

    /**
     * Wait for all pending actions to complete. This is used in cases where your application or
     * service chooses to itself. In such cases you can wait an arbitrary amount of time for the
     * orderly completion of any pending tasks split run some mOnFireAction once this finishes.
     * <p>
     * Under normal circumstances, you do call this. Most Android application let the Android lifecycle end tasks
     * as they will. Just let work complete split let Android end the program when it feels the need. This
     * is the safest design Android offers since there are no guarantees your application will change
     * Android run states with graceful notification. Design for split battle harden your code
     * against sudden shutdowns instead of expecting this method to be called.
     * <p>
     * This method returns immediately split does not wait. It will start to shut down the executor
     * threads. No more asynchronous tasks may be sent to the executor after this point.
     * <p>
     * Use the returned Future to know when current tasks complete.
     * <p>
     * After shutdown starts, new WORKER operations (operations queued to a WORKER) will throw a runtime Exception.
     * <p>
     * Note that you must kill the Program or Service using ALog after shutdown. It can not be restarted even if for example
     * a new Activity is created later without first reacting a new Program.
     *
     * @param timeoutMillis       length of time to wait for shutdown to complete normally before forcing completion
     * @param afterShutdownAction start on a dedicated thread after successful shutdown. The returned
     *                            {@link java.util.concurrent.Future} will complete only after this operation completes
     *                            split <code>afterShutdownAction</code> will not be called
     * @param <IN>                the type of input argument expected by the action
     * @return a Future that will return true if the shutdown completes within the specified time, otherwise shutdown continues
     */
    @NonNull
    <IN> Future<Boolean> shutdown(long timeoutMillis,
                                  @Nullable final IAction<IN> afterShutdownAction);

    /**
     * @return <code>true</code> if thread executor is shutdown
     */
    boolean isShutdown();

    /**
     * Halt execution of all functional and reactive subscriptions in this threadType.
     *
     * @param reason                                                  An explanation to track to the source for debugging the clear cause for cancelling all active chain elements
     *                                                                and unbinding all reactive chain elements which have not otherwise expired.
     * @param actionOnDedicatedThreadAfterAlreadyStartedTasksComplete optional callback once current tasks completely finished
     * @param actionOnDedicatedThreadIfTimeout                        optional what to do if an already started task blocks for too long
     * @param timeoutMillis                                           length of time to wait for shutdown to complete normally before forcing completion
     * @param <IN>                                                    the type of input argument expected by the action
     * @return a list of work which failed to complete before shutdown
     */
    @NonNull
    <IN> List<Runnable> shutdownNow(@NonNull String reason,
                                    @Nullable IAction<IN> actionOnDedicatedThreadAfterAlreadyStartedTasksComplete,
                                    @Nullable IAction<IN> actionOnDedicatedThreadIfTimeout,
                                    long timeoutMillis);
} public class BindingContextUtil {
    private static final String TAG = BindingContextUtil.class.getSimpleName();

    /**
     * The default implementation of a state-change notification to start and stop data-driven reactive actions
     *
     * @param <T> the type of object which will control these state changes
     */
    public static class DefaultBindingContext<T> implements IBindingContext<T> {
        private final CopyOnWriteArraySet<IActionOne<T>> onOpenActions = new CopyOnWriteArraySet<>();
        private final CopyOnWriteArraySet<IActionOne<T>> onCloseActions = new CopyOnWriteArraySet<>();
        private final AtomicReference<T> bindingContextAR = new AtomicReference<>(null);

        /**
         *
         * @return
         */
        @Override
        @CallSuper
        public boolean isOpen() {
            return bindingContextAR.get() != null;
        }

        /**
         *
         * @param t the type of object controlling this binding's lifecycle
         */
        @Override
        public final void openBindingContext(T t) {
            if (bindingContextAR.compareAndSet(null, t)) {
                doBindingContextStateChangeActions(onOpenActions, t);
            } else {
                RCLog.d(this, "Can not openBindingContext: illegal transition from " + bindingContextAR.get() + " to " + t);
            }
        }

        /**
         *
         * @param t the type of object controlling this binding's lifecyle
         */
        @Override
        public final void closeBindingContext(T t) {
            if (bindingContextAR.compareAndSet(t, null)) {
                doBindingContextStateChangeActions(onCloseActions, t);
            } else {
                RCLog.d(this, "Can not closeBindingContext: illegal transition from " + bindingContextAR.get() + " to " + t);
            }
        }

        /**
         *
         * @param action
         */
        @Override
        public final void onOpen(@NonNull IActionOne<T> action) {
            T t = bindingContextAR.get();

            if (t != null) {
                // Already open- execute now
                Set<IActionOne<T>> set = new HashSet<>(1);
                set.add(action);
                doBindingContextStateChangeActions(set, t);
            }
            onOpenActions.add(action);
        }

        /**
         *
         * @param action performed when binding ends
         */
        @Override
        public final void onClose(@NonNull IActionOne<T> action) {
            onCloseActions.add(action);
        }

        private void doBindingContextStateChangeActions(Set<IActionOne<T>> actions, T t) {
            Exception caught = null;

            for (IActionOne<T> action : actions) {
                try {
                    action.call(t);
                } catch (Exception e) {
                    caught = e;
                    RCLog.e(this, "Problem during binding context state change actions- any other actions will still be attempted", e);
                }
            }

            if (caught != null) {
                throw new IllegalStateException(caught);
            }
        }
    }

    /**
     * A parent class for a {@link Fragment} that will provide a binding context to automatically
     * pause/resume/close reactive bindings
     */
    public static class AsyncFragment extends Fragment {
        private IBindingContext<Fragment> startStopBindingContext = new DefaultBindingContext<>();
        private IBindingContext<Fragment> pauseResumeBindingContext = new DefaultBindingContext<>();

        /**
         *
         * @return
         */
        @NonNull
        @UiThread
        public final IBindingContext getStartStopBindingContext() {
            return startStopBindingContext;
        }

        /**
         *
         * @return
         */
        @Nullable
        @UiThread
        public final IBindingContext getPauseResumeBindingContext() {
            return pauseResumeBindingContext;
        }

        /**
         *
         */
        @Override
        @UiThread
        @CallSuper
        public void onResume() {
            pauseResumeBindingContext.openBindingContext(this);
            super.onResume();
        }

        /**
         *
         */
        @Override
        @UiThread
        @CallSuper
        public void onPause() {
            pauseResumeBindingContext.closeBindingContext(this);
            pauseResumeBindingContext = new DefaultBindingContext<>();

            super.onPause();
        }

        /**
         *
         */
        @Override
        @UiThread
        @CallSuper
        public void onStop() {
            startStopBindingContext.closeBindingContext(this);
            startStopBindingContext = new DefaultBindingContext<>();

            super.onStop();
        }
    }

    /**
     * A parent class for a {@link FragmentActivity} that will provide a binding context to automatically
     * pause/resume/close reactive bindings
     */
    public static abstract class AsyncFragmentActivity extends FragmentActivity {
        /**
         * Use this binding context if you want your reactive action to end when the fragment closes
         *
         * You should create this type of binding in your {@link Fragment#onStart()} method
         */
        private IBindingContext<FragmentActivity> startStopBindingContext = new DefaultBindingContext<>();
        private IBindingContext<FragmentActivity> pauseResumeBindingContext = new DefaultBindingContext<>();

        /**
         *
         * @return a new binding context each time the {@link FragmentActivity} is stopped
         */
        @NonNull
        @UiThread
        public final IBindingContext<FragmentActivity> getStartStopBindingContext() {
            return startStopBindingContext;
        }

        /**
         * Use this binding context if you want your reactive actions to end when the fragment pauses.
         *
         * You should create this type of binding in your {@link FragmentActivity#onResume()} method
         *
         * @return a new binding context each time the application is paused
         */
        @NonNull
        @UiThread
        public final IBindingContext getPauseResumeBindingContext() {
            return pauseResumeBindingContext;
        }

        /**
         * Run when the binding context goes inactive
         *
         * Bound actions are stopped before the activity pauses
         */
        @Override
        @UiThread
        @CallSuper
        public void onPause() {
            pauseResumeBindingContext.closeBindingContext(this);
            pauseResumeBindingContext = new DefaultBindingContext<>();

            super.onPause();
        }

        /**
         * Run when the binding context returns from an inactive/paused state
         *
         * Bound actions are fired before the activity itself resumes in order to initialize variables
         * for display
         */
        @Override
        @UiThread
        @CallSuper
        public void onResume() {
            pauseResumeBindingContext.openBindingContext(this);
            super.onResume();
        }

        /**
         * Run when the binding context returns from an inactive/paused state
         *
         * Bound actions are fired before the activity itself starts in order to initialize variables
         * for display
         */
        @Override
        @UiThread
        @CallSuper
        public void onStart() {
            startStopBindingContext.openBindingContext(this);
            super.onStart();
        }

        /**
         * Run when the binding context ends
         *
         * Bound actions are stopped before the activity stops
         */
        @Override
        @UiThread
        @CallSuper
        public void onStop() {
            startStopBindingContext.closeBindingContext(this);
            startStopBindingContext = new DefaultBindingContext<>();

            super.onStop();
        }
    }
} @NotCallOrigin
public class DefaultThreadType extends AbstractThreadType {
    final boolean inOrderExecution;

    private volatile boolean wakeUpIsPending = false; // Efficiency filter to wake the ServiceExecutor only once TODO Is there a simpler way with AtomicBoolean?

    private final Runnable wakeUpRunnable = () -> {
        // Do nothing, this is just used for insurance fast flushing the ServiceExecutor queue when items are added out-of-order to the associated BlockingQueue
        wakeUpIsPending = false;
    };

    /**
     * Construct a new thread group
     *
     * @param name            of this thread type for debug displays
     * @param executorService for this thread type
     * @param queue           may be null in which case {@link #isInOrderExecutor()} will return
     *                        <code>true</code>; may be {@link java.util.concurrent.BlockingDeque} in which
     *                        case {@link #isInOrderExecutor()} will return <code>false</code>
     */
    public DefaultThreadType(@NonNull String name,
                             @NonNull ExecutorService executorService,
                             @Nullable BlockingQueue<Runnable> queue) {
        super(name, executorService, queue);

        this.inOrderExecution = queue == null || !(queue instanceof Deque);
    }

    @Override // IThreadType
    public void run(@NonNull Runnable runnable) {
        executorService.submit(runnable);
    }

    @Override // IThreadType
    @SuppressWarnings("unchecked")
    @NotCallOrigin
    public void runNext(@NonNull Runnable runnable) {
        if (inOrderExecution || queue == null) {
            run(runnable);
            return;
        }

        int n = queue.size();
        if (n == 0) {
            run(runnable);
            return;
        }

        // Out of order execution is permitted and desirable to finish functional chains we have started before clouding memory and execution queues by starting more
        if (isInOrderExecutor()) {
            RCLog.v(this, "WARNING: runNext() on single threaded IThreadType. This will be run FIFO only after previously queued tasks");
            queue.add(runnable);
        } else {
            ((BlockingDeque) queue).addFirst(runnable);
        }
        if (!wakeUpIsPending && ++n != queue.size()) {
            // The queue changed during submit- just be sure something is submitted to wake the executor right now to pull from the queue
            wakeUpIsPending = true;
            executorService.execute(wakeUpRunnable);
        }
    }

    @Override // IThreadType
    public boolean isInOrderExecutor() {
        return inOrderExecution;
    }
} @NotCallOrigin
public class TypedThread extends Thread {
    public static final ThreadGroup THREAD_GROUP = new ThreadGroup("ThreadTypeThreadGroup") {
        @Override
        public void uncaughtException(@NonNull final Thread t, @NonNull Throwable throwable) {
            RCLog.e(this, "uncaughtException in " + t, throwable);
        }
    };
    /*
     * Each thread may belong to multiple threadTypes. At the moment we only track the
     * first ThreadType which created it. But since the Thread may outlive the ThreadType
     * (if used by other ThreadTypes) we use a WeakReference to allow the original
     * ThreadType to be garbage collected.
     *
     * TODO A better solution would be to track ThreadTypes split Threads without this potential for confusion. To be determined.
     */
    private final CopyOnWriteArrayList<IThreadType> threadTypes = new CopyOnWriteArrayList<>();

    public TypedThread(@NonNull IThreadType threadType,
                       @NonNull Runnable runnable) {
        super(THREAD_GROUP, runnable);

        this.threadTypes.add(threadType);
    }

    public TypedThread(@NonNull IThreadType threadType,
                       @NonNull Runnable runnable,
                       @NonNull String threadName) {
        super(THREAD_GROUP, runnable, threadName);

        this.threadTypes.add(threadType);
    }

    public TypedThread(@NonNull IThreadType threadType,
                       @NonNull String threadName) {
        super(THREAD_GROUP, threadName);

        this.threadTypes.add(threadType);
    }

    public TypedThread(@NonNull IThreadType threadType,
                       @NonNull ThreadGroup group,
                       @NonNull Runnable runnable) {
        super(group, runnable);

        this.threadTypes.add(threadType);
    }

    public TypedThread(@NonNull IThreadType threadType,
                       @NonNull ThreadGroup group,
                       @NonNull Runnable runnable,
                       @NonNull String threadName) {
        super(group, runnable, threadName);

        this.threadTypes.add(threadType);
    }

    public TypedThread(@NonNull IThreadType threadType,
                       @NonNull ThreadGroup group,
                       @NonNull String threadName) {
        super(group, threadName);

        this.threadTypes.add(threadType);
    }

    public TypedThread(@NonNull IThreadType threadType,
                       @NonNull ThreadGroup group,
                       @NonNull Runnable runnable,
                       @NonNull String threadName,
                       long stackSize) {
        super(group, runnable, threadName, stackSize);

        this.threadTypes.add(threadType);
    }

    @NonNull
    public List<IThreadType> getThreadTypes() {
        return threadTypes;
    }

    @NonNull
    public IThreadType getThreadType() {
        List<IThreadType> currentThreadTypes = getThreadTypes();
        IThreadType currentThreadType = Async.NON_CASCADE_THREAD;

        if (currentThreadTypes.size() == 1) {
            currentThreadType = currentThreadTypes.get(0);
        } else {
            RCLog.v(this, currentThreadTypes.size() + " threadTypes for this Thread, can not disambiguate");
        }

        return currentThreadType;
    }
}
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.util.Log;
import com.reactivecascade.i.IAction;
import com.reactivecascade.i.IActionOne;
import com.reactivecascade.i.IActionOneR;
import com.reactivecascade.i.IActionR;
import com.reactivecascade.i.IAltFuture;
import com.reactivecascade.i.IBindingContext;
import com.reactivecascade.i.IRunnableAltFuture;
import com.reactivecascade.i.ISettableAltFuture;
import com.reactivecascade.i.IThreadType;
import com.reactivecascade.util.BindingContextUtil;
import com.reactivecascade.util.DefaultThreadType;
import com.reactivecascade.util.TypedThread;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
        @NonNull
        @Override // IThreadType
        @SuppressWarnings("unchecked")
        public <IN, OUT> List<IAltFuture<IN, OUT>> map(@NonNull IActionOneR<IN, OUT>... actions) {
            throw new UnsupportedOperationException("NON_CASCADE_THREAD is a marker and does not support execution");
        }

        /**
         * This is a marker class only.
         *
         * @throws UnsupportedOperationException
         */
        @Override // IThreadType
        public <IN, OUT> void fork(@NonNull IRunnableAltFuture<IN, OUT> runnableAltFuture) {
            throw new UnsupportedOperationException("NON_CASCADE_THREAD is a marker and does not support execution");
        }

        /**
         * This is a marker class only.
         *
         * @throws UnsupportedOperationException
         */
        @Override // IThreadType
        public boolean isShutdown() {
            throw new UnsupportedOperationException("NON_CASCADE_THREAD is a marker and does not support execution");
        }

        /**
         * This is a marker class only.
         *
         * @throws UnsupportedOperationException
         */
        @NonNull
        @Override // IThreadType
        public <IN> Future<Boolean> shutdown(long timeoutMillis, @Nullable IAction<IN> afterShutdownAction) {
            throw new UnsupportedOperationException("NON_CASCADE_THREAD is a marker and does not support execution");
        }

        /**
         * This is a marker class only.
         *
         * @throws UnsupportedOperationException
         */
        @NonNull
        @Override // IThreadType
        public <IN> List<Runnable> shutdownNow(@NonNull String reason, @Nullable IAction<IN> actionOnDedicatedThreadAfterAlreadyStartedTasksComplete, @Nullable IAction<IN> actionOnDedicatedThreadIfTimeout, long timeoutMillis) {
            throw new UnsupportedOperationException("NON_CASCADE_THREAD is a marker and does not support execution");
        }

        /**
         * This is a marker class only.
         *
         * @throws UnsupportedOperationException
         */
        @NonNull
        @Override // INamed
        public String getName() {
            throw new UnsupportedOperationException("NON_CASCADE_THREAD is a marker and does not support execution");
        }
    };

    @Nullable
    private static final AsyncBuilder ASYNC_BUILDER = AsyncBuilder.getInstance(); // The builder used to create the _first_ instance of ThreadType, the one which receives convenient static bindings of commonly used features. Using multiple Async instances except for system tests is not supported
    public static final boolean USE_FORKED_STATE = (ASYNC_BUILDER == null) || ASYNC_BUILDER.isUseForkedState();
    //    public static final boolean VISUALIZE = false;
    public static final boolean RUNTIME_ASSERTIONS = (ASYNC_BUILDER == null) || ASYNC_BUILDER.isRuntimeAssertionsEnabled();
    /**
     * The from of {@link AsyncBuilder#isShowErrorStackTraces()} locked in for performance reasons by the <em>first</em> <code>AsyncBuilder</code>
     */
    public static final boolean TRACE_ASYNC_ORIGIN = (ASYNC_BUILDER == null) || ASYNC_BUILDER.isShowErrorStackTraces(); // This makes finding where in you code a given log line was directly or indirectly called, but slows running
    // Some of the following logic lines are funky to support the Android visual editor. If you never initialized Async, you will want to see something in the visual editor. This matters for UI classes which receive services from Async
    public static final Thread UI_THREAD = (ASYNC_BUILDER == null) ? null : ASYNC_BUILDER.uiThread; // The main system thread for this Context
    /**
     * The from of {@link AsyncBuilder#isFailFast()} locked in for performance reasons by the <em>first</em> <code>AsyncBuilder</code>
     */
    public static final boolean FAIL_FAST = (ASYNC_BUILDER == null) || ASYNC_BUILDER.isFailFast(); // Default true- stop on the first error in debugOrigin builds to make debugging from the first point of failure easier
    /**
     * The default {@link com.reactivecascade.i.IThreadType} implementation. Usually you can call for
     * guaranteed asynchronous operations that will cooperate (queue) when all device cores are busy.
     * Special configurations with {@link AsyncBuilder} may choose to modify this behaviour.
     * <p>
     * <code><pre>
     *     import static com.reactivecascade.Async.*;
     *     ..
     *     ArrayList<String> list =
     *     for (
     *     UI.subscribe(() -> textView.setText("Blah");
     * </pre></code>
     */
    public static final IThreadType WORKER = (ASYNC_BUILDER == null) ? null : ASYNC_BUILDER.getWorkerThreadType();
    public static final IThreadType SERIAL_WORKER = (ASYNC_BUILDER == null) ? null : ASYNC_BUILDER.getSerialWorkerThreadType();
    /**
     * The default {@link com.reactivecascade.i.IThreadType} implementation which gives uniform access
     * to the system's {@link #UI_THREAD}. Example use:
     * <p>
     * <code><pre>
     *     import static com.reactivecascade.ThreadType.*;
     *     ..
     *     UI.subscribe(() -> textView.setText("Blah");
     * </pre></code>
     */
    public static final IThreadType UI = (ASYNC_BUILDER == null) ? null : ASYNC_BUILDER.getUiThreadType();
    public static final IThreadType FILE = (ASYNC_BUILDER == null) ? null : ASYNC_BUILDER.getFileThreadType();
    /**
     * A group of background thread for concurrently reading from the network
     * <p>
     * TODO Automatically adjusted thread pool size based on current connection type
     */
    public static final IThreadType NET_READ = (ASYNC_BUILDER == null) ? null : ASYNC_BUILDER.getNetReadThreadType();
    /**
     * A single thread for making writes to the network.
     * <p>
     * Upstream bandwidth on mobile is generally quite limited, so one write at a time will tend to help
     * tasks finish more quickly. This also simplifies cache invalidation on POST and PUT operations more
     * coherent.
     */
    public static final IThreadType NET_WRITE = (ASYNC_BUILDER == null) ? null : ASYNC_BUILDER.getNetWriteThreadType();
    public static volatile boolean SHOW_ERROR_STACK_TRACES = (ASYNC_BUILDER == null) || ASYNC_BUILDER.isShowErrorStackTraces(); // For clean unit testing. This can be temporarily turned off for a single threaded system or unit test code block to keep _intentional_ unit test errors from cluttering the stack trace.
    private static final int FAIL_FAST_SLEEP_BEFORE_SYSTEM_EXIT = 1000; // The idea is this helps the user and debugger see the issue and logs can catch up before bombing the app too fast to see what was happening
    private static volatile boolean sExitWithErrorCodeStarted = false;
    public static final IBindingContext<Context> DEFAULT_BINDING_CONTEXT = new BindingContextUtil.DefaultBindingContext<>();