public final class Async {
    //TODO TIMER system tests
    public static final ScheduledExecutorService TIMER = Executors.newSingleThreadScheduledExecutor(r ->
            new Thread(r, "Timer"));
    /**
     * A marker from returned when a thread is not part of Cascade.
     * <p>
     * See also {@link Async#UI}. The system thread / main thread / UI thread is not created by Cascade, it does
     * not extend this class. It is wrapped in a special implementation with the the assistance of
     * {@link com.reactivecascade.util.UIExecutorService}
     */
    public static final IThreadType NON_CASCADE_THREAD = new IThreadType() {
        /**
         * This is a marker class only.
         *
         * @throws UnsupportedOperationException
         */
        @Override // IThreadType
        public boolean isInOrderExecutor() {
            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> void execute(@NonNull IAction<IN> action) {
            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 void run(@NonNull Runnable runnable) {
            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> void run(@NonNull IAction<IN> action,
                             @NonNull IActionOne<Exception> onErrorAction) {
            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> void runNext(@NonNull IAction<IN> action) {
            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 void runNext(@NonNull Runnable runnable) {
            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 moveToHeadOfQueue(@NonNull Runnable runnable) {
            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> void runNext(@NonNull IAction<IN> action,
                                 @NonNull IActionOne<Exception> onErrorAction) {
            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> Runnable wrapActionWithErrorProtection(@NonNull IAction<IN> action) {
            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> Runnable wrapActionWithErrorProtection(@NonNull IAction<IN> action,
                                                           @NonNull IActionOne<Exception> onErrorAction) {
            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> IAltFuture<IN, IN> then(@NonNull IAction<IN> action) {
            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> IAltFuture<IN, IN> then(@NonNull IActionOne<IN> action) {
            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
        @SuppressWarnings("unchecked")
        public <IN> List<IAltFuture<IN, IN>> then(@NonNull IAction<IN>... actions) {
            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 <OUT> ISettableAltFuture<OUT> from(@NonNull OUT value) {
            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 <OUT> ISettableAltFuture<OUT> from() {
            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, OUT> IAltFuture<IN, OUT> then(@NonNull IActionR<OUT> action) {
            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
        @SuppressWarnings("unchecked")
        public <IN, OUT> List<IAltFuture<IN, OUT>> then(@NonNull IActionR<OUT>... actions) {
            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, OUT> IAltFuture<IN, OUT> map(@NonNull IActionOneR<IN, OUT> action) {
            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
        @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<>();

    static {
        if (!AsyncBuilder.isInitialized()) {
            Log.e(Async.class.getSimpleName(),
                    AsyncBuilder.NOT_INITIALIZED,
                    new IllegalStateException(AsyncBuilder.NOT_INITIALIZED));
        }
    }

    @UiThread
    Async(@NonNull Context context) {
        DEFAULT_BINDING_CONTEXT.openBindingContext(context);
    }

    /**
     * Ugly hack from http://stackoverflow.com/questions/21367646/how-to-determine-if-android-application-is-started-with-junit-testing-instrument
     *
     * @return true if this is a test, or false if this is a production app
     */
    private static boolean isTestMode() {
        boolean result;
        try {
            Class.forName("com.reactivecascade.AsyncBuilderTest");
            result = true;
        } catch (final Exception e) {
            result = false;
        }
        return result;
    }

    public static void exitWithErrorCode(@NonNull String tag,
                                         @NonNull String message,
                                         @Nullable Throwable t) {
        if (isTestMode()) {
            // Some integration tests fail without this- the test harness is disturbed by app shutdown
            return;
        }

        final int errorCode = 1;

        // Kill the app hard after some delay. You are not allowed to refire this Intent in some critical phases (Activity startup)
        //TODO let the Activity or Service down slowly and gently with lifecycle callbacks if production build
        if (sExitWithErrorCodeStarted) {
            Log.v(tag, "Already existing, ignoring exit with error code (" + errorCode + "): " + message + "-" + t);
        } else {
            sExitWithErrorCodeStarted = true; // Not a thread-safe perfect lock, but fast and good enough to generally avoid duplicate shutdown messages during debug
            if (t != null) {
                Log.e(tag, "Exit with error code (" + errorCode + "): " + message, t);
            } else {
                Log.i(tag, "Exit, no error code : " + message);
            }
            WORKER.shutdownNow("exitWithErrorCode: " + message, null, null, 0);
            NET_READ.shutdownNow("exitWithErrorCode: " + message, null, null, 0);
            NET_WRITE.shutdownNow("exitWithErrorCode: " + message, null, null, 0);
            FILE.shutdownNow("exitWithErrorCode: " + message, null, null, 0);

            new Thread(() -> {
                try {
                    // Give the user time to see a popup split adb time to receive the error messages from this process before it dies
                    Thread.sleep(FAIL_FAST_SLEEP_BEFORE_SYSTEM_EXIT);
                } catch (Exception e2) {
                    Log.d(tag, "Problem while pausing before failfast system exit due to " + t, e2);
                }
                System.exit(errorCode);
            }, "FailFastDelayThread")
                    .start();
        }
    }

//    /**
//     * Pass a signal to the JavaScript visualizer client running on the LAN
//     *
//     * @param tag
//     * @param from
//     * @param extraInfo
//     */
//    public static void visualize(Object tag, String from, String extraInfo) {
//        if (signalVisualizerClient != null) {
//            signalVisualizerClient.sendEventMessage(getTag(tag), System.currentTimeMillis(), from, extraInfo);
//        }
//    }


//    /**
//     * Pass a signal to the JavaScript visualizer client running on the LAN
//     *
//     * @param tag
//     * @param from
//     * @param extraInfo
//     */
//    public static void visualize(Object tag, long from, String extraInfo) {
//        if (signalVisualizerClient != null) {
//            signalVisualizerClient.sendEventMessage(getTag(tag), System.currentTimeMillis(), from, extraInfo);
//        }
//    }

//    /**
//     * Pass a signal to the JavaScript visualizer client running on the LAN
//     *
//     * @param tag
//     * @param from
//     * @param extraInfo
//     */
//    public static void visualize(Object tag, JSONObject from, String extraInfo) {
//        if (signalVisualizerClient != null) {
//            signalVisualizerClient.sendEventMessage(getTag(tag), System.currentTimeMillis(), from.toString(), extraInfo);
//        }
//    }

    /**
     * If the current thread belongs to more than one <code>ThreadType</>, subscribe the returned ThreadType will be the one
     * which created the Thread
     * <p>
     * This is used for debugging only. For performance reasons it will always return <code>null</code>
     * in production builds.
     * <p>
     * Beware of debugging confusion if you use one Thread as part of the executor in multiple different ThreadTypes
     *
     * @return the current ThreadType or {@link #NON_CASCADE_THREAD} if the type can be determined
     */
    @NonNull
    public static IThreadType currentThreadType() {
        final Thread thread = Thread.currentThread();

        if (thread instanceof TypedThread) {
            return ((TypedThread) thread).getThreadType();
        } else if (isUiThread()) {
            return UI;
        }

        return NON_CASCADE_THREAD;
    }

    /**
     * Check if currently running on the main system or "user interface" thread
     *
     * @return <code>true</code> if this is the one true system thread for the current {@link android.content.Context}
     */
    public static boolean isUiThread() {
        return Thread.currentThread() == UI_THREAD;
    }
} public class ImmutableValue<T> implements ISafeGettable<T> {
    @SuppressWarnings("unchecked")
    private final AtomicReference<T> valueAR = new AtomicReference<>((T) VALUE_NOT_AVAILABLE);

    private final ConcurrentLinkedQueue<IBaseAction<T>> thenActions = new ConcurrentLinkedQueue<>();

    @Nullable
    private final IActionR<T> action;

    /**
     * Create but do not yet set the from of an underlying {@link java.util.concurrent.atomic.AtomicReference}
     * <p>
     * You can use this object as a placeholder until an asynchronous function result is finally set.
     * <p>
     * You can also attach code which will run when the from is set. See {@link #then(IAction)}
     * and {@link #then(IActionOne)}
     */
    public ImmutableValue() {
        action = null;
    }

    /**
     * This constructor creates and initialized the from to its final from.
     * <p>
     * It can be useful to create for example default values.
     *
     * @param value the value to immediately set
     */
    public ImmutableValue(@NonNull T value) {
        set(value);
        action = null;
    }

    public ImmutableValue(@Nullable IActionR<T> action) {
        this.action = action;
    }

    /**
     * Atomic update.
     * <p>
     * See {@link java.util.concurrent.atomic.AtomicReference#compareAndSet(Object, Object)} for
     * a description and use examples of this pattern.
     *
     * @param expected value
     * @param value    to set if expected is the current value
     * @return if <code>false</code> is returned, you may try again as the from as needed since the
     * final from has not been set.
     */
    private boolean compareAndSet(@NonNull T expected,
                                  @NonNull T value) {
        boolean success = valueAR.compareAndSet(expected, value);

        if (success) {
            doThenActions(value);
        } else {
            RCLog.d(this, "compareAndSet(" + expected + ", " + value + ") failed, current from is " + safeGet());
        }

        return success;
    }

    /**
     * Add an action which will be run when {@link #set(Object)} is called.
     * <p>
     * If the from is already {@link #set(Object)}, the passed mOnFireAction will be run immediately and
     * synchronously.
     *
     * @return this
     */
    @NonNull
    public ImmutableValue<T> then(@NonNull IActionOne<T> action) {
        thenActions.add(action);
        if (isSet()) {
            doThenActions(safeGet());
        }
        return this;
    }

    /**
     * Add an action which will be run when {@link #set(Object)} is called.
     * <p>
     * If the from is already {@link #set(Object)}, the passed mOnFireAction will be run immediately and
     * synchronously.
     *
     * @return this
     */
    @NonNull
    public ImmutableValue<T> then(@NonNull IAction<T> action) {
        thenActions.add(action);
        if (isSet()) {
            doThenActions(safeGet());
        }
        return this;
    }

    private void doThenActions(@NonNull T value) {
        for (IBaseAction<T> action : thenActions) {
            if (thenActions.remove(action)) {
                try {
                    call(value, action);
                } catch (Exception e) {
                    RCLog.e(this, "Can not do then() actions after ImmutableValue was set to from=" + value, e);
                }
            }
        }
    }

    @Nullable
    @SuppressWarnings("unchecked")
    // IN->OUT must be bent to match all cases but the context makes this safe
    private <IN, OUT> OUT call(@NonNull final IN in,
                               @NonNull final IBaseAction<IN> action) throws Exception {
        if (action instanceof IAction) {
            ((IAction) action).call();
            return null;
        } else if (action instanceof IActionOne) {
            ((IActionOne<IN>) action).call(in);
            return null;
        } else if (action instanceof IActionOneR) {
            return ((IActionOneR<IN, OUT>) action).call(in);
        } else if (action instanceof IActionR) {
            return ((IActionR<OUT>) action).call();
        }

        throw new UnsupportedOperationException("Not sure how to call this IBaseAction type: " + action.getClass());
    }

    /**
     * Check if the immutable from has been asserted yet.
     * <p>
     * Note that if you think you need this for your core logic, you may want to ask yourself if you can
     * be better served by using the dependency mechanism of {@link RunnableAltFuture#then(IAltFuture)}
     * and similar calls. It is often better to let the preconditions for a {@link #get()} be set by the functional
     * chain. If still needed, you may inserting your own atomic or non-atomic logic such as
     * <pre>
     * <code>
     *     if (!immutableValue.isSet()) {
     *        immutableValue.set(from); // Not thread save. This will throw an IllegalStateException if someone else set the from between the previous line and this line
     *     }
     * </code>
     * </pre>
     *
     * @return <code>true</code> if the value is already asserted
     */
    public final boolean isSet() {
        return valueAR.get() != VALUE_NOT_AVAILABLE;
    }

    /**
     * Get the from, or throw {@link java.lang.IllegalStateException} if you are getting the from
     * before it has been set.
     * <p>
     * Generally you want to use this method instead of {@link #safeGet()} when you can use dependency
     * mechanisms properly. If you think have problems, ask if you should be doing some of your logic
     * in a <code>.subscribe()</code> clause to guarantee the execution order.
     *
     * @return
     * @throws IllegalStateException if the supplied lazy evaluation IAction throws an error during evaluation
     */
    @CallSuper
    @NonNull
    @SuppressWarnings("unchecked")
    public T get() {
        T value = valueAR.get();

        if (value == VALUE_NOT_AVAILABLE) {
            try {
                if (action != null) {
                    T t = action.call();
                    if (!compareAndSet((T) VALUE_NOT_AVAILABLE, t)) {
                        RCLog.d(this, "ImmutableValue was set while calling action during get: ignoring the second value from action \"" + t + "\" in favor of \"" + valueAR.get() + "\"");
                    }
                    return t;
                }
                throw new IllegalStateException("Null action and from has not been set()");
            } catch (Exception e) {
                throw new IllegalStateException("Can not evaluate the supplied ImmutableValue.IAction", e);
            }
        }

        return value;
    }

    /**
     * Get the from, or return <code>null</code> if the from is not yet set.
     * <p>
     * Usually you will have a better design with {@link #get()} instead. This is fine to use
     * if other parts of your application is reactive and will update the from again when it has
     * been finally set.
     *
     * @return the from, or <code>null</code> if the from has not yet been determined
     */
    @CallSuper
    @SuppressWarnings("unchecked")
    @NonNull
    public T safeGet() {
        return valueAR.get();
    }

    /**
     * Set the from.
     * <p>
     * If this atomic mOnFireAction succeeds, any {@link #then(IActionOne)} actions
     * will also be run synchronously. This is a fairly low-level class which is used by other classes
     * and for practical reasons it violates the "always asynchronous" assumption. Traditional. Sorry. :)
     *
     * @param value
     * @return
     */
    @CallSuper
    @NonNull
    @SuppressWarnings("unchecked")
    public T set(@NonNull T value) {
        AssertUtil.assertNotNull(value);

        if (!compareAndSet((T) VALUE_NOT_AVAILABLE, value)) {
            throw new IllegalStateException("ImmutableReference can not be set multiple times. It is already set to " + safeGet() + " so we can not assert new from=" + value);
        }
        doThenActions(value);

        return value;
    }

    /**
     * Return the current from of the immutable from if possible
     * <p>
     * In other cases marker text "(ImmutableValue not yet set)" will be returned. If you see
     * this text, consider using a {@link #then(IActionOne)} mOnFireAction
     * to make your logic run when this from is set.
     *
     * @return the string representation, or "Value not available" if not yet determined and can not be determined by an on-get action
     */
    @CallSuper
    @NonNull
    public String toString() {
        return safeGet().toString();
    }
} @NotCallOrigin
public class RunnableAltFuture<IN, OUT> extends AbstractAltFuture<IN, OUT> implements IRunnableAltFuture<IN, OUT> {
    private final IActionR<OUT> mAction;

    /**
     * Create a {@link java.lang.Runnable} which will be executed one time on the
     * {@link com.reactivecascade.i.IThreadType} implementation to perform an {@link IBaseAction}
     *
     * @param threadType the thread pool to run this command on
     * @param action     a function that receives one input and no return from
     */
    @SuppressWarnings("unchecked")
    public RunnableAltFuture(@NonNull IThreadType threadType,
                             @NonNull IAction<? extends IN> action) {
        super(threadType);

        this.mAction = () -> {
            IAltFuture<?, ? extends IN> previousAltFuture = getUpchain();
            OUT out;

            if (previousAltFuture == null) {
                out = (OUT) COMPLETE;
            } else {
                AssertUtil.assertTrue("The previous RunnableAltFuture to Iaction is not finished", previousAltFuture.isDone());
                out = (OUT) previousAltFuture.get();
            }
            action.call();
            return out; // T and A are the same when there is no return type from the mOnFireAction
        };
    }

    /**
     * Constructor
     *
     * @param threadType the thread pool to run this command on
     * @param action     a function that receives one input and no return from
     */
    @SuppressWarnings("unchecked")
    public RunnableAltFuture(@NonNull IThreadType threadType,
                             @NonNull IActionOne<IN> action) {
        super(threadType);

        this.mAction = () -> {
            IAltFuture<?, ? extends IN> paf = getUpchain();

            AssertUtil.assertNotNull(paf);
            AssertUtil.assertTrue("The previous RunnableAltFuture in the chain is not finished", paf.isDone());
            final IN in = paf.get();
            action.call(in);

            return (OUT) in; // T and A are the same when there is no return type from the mOnFireAction
        };
    }

    /**
     * Create a {@link java.lang.Runnable} which will be executed one time on the
     * {@link com.reactivecascade.i.IThreadType} implementation to perform an {@link IBaseAction}
     *
     * @param threadType the thread pool to run this command on
     * @param mAction    a function that does not vary with the input from
     */
    public RunnableAltFuture(@NonNull IThreadType threadType,
                             @NonNull IActionR<OUT> mAction) {
        super(threadType);

        this.mAction = mAction;
    }

    /**
     * Create a {@link java.lang.Runnable} which will be executed one time on the
     * {@link com.reactivecascade.i.IThreadType} implementation to perform an {@link IBaseAction}
     *
     * @param threadType the thread pool to run this command on
     * @param mAction    a mapping function
     */
    public RunnableAltFuture(@NonNull IThreadType threadType,
                             @NonNull IActionOneR<IN, OUT> mAction) {
        super(threadType);

        this.mAction = () -> {
            IAltFuture<?, ? extends IN> previousAltFuture = getUpchain();

            AssertUtil.assertNotNull(previousAltFuture);
            AssertUtil.assertTrue("The previous RunnableAltFuture in the chain is not finished:" + getOrigin(), previousAltFuture.isDone());

            return mAction.call(previousAltFuture.get());
        };
    }

//    @CallSuper
//    @CallOrigin
//    @Override // IAltFuture
//    public boolean cancel(@NonNull  final String reason) {
//        assertNotDone();
//        final Object state = stateAR.get();
//
//        if (state instanceof AltFutureStateCancelled) {
//            RCLog.d(this, mOrigin, "Ignoring cancel (reason=" + reason + ") since already in StateError\nstate=" + state);
//        } else {
//            if (stateAR.compareAndSet(state, new AltFutureStateCancelled(reason))) {
//                RCLog.d(this, mOrigin, "Cancelled, reason=" + reason);
//                return true;
//            } else {
//                RCLog.d(this, mOrigin, "Ignoring cancel (reason=" + reason + ") due to a concurrent state change during cancellation\nstate=" + state);
//            }
//        }
//        return false;
//    }

    /**
     * The {@link java.util.concurrent.ExecutorService} of this <code>RunnableAltFuture</code>s {@link com.reactivecascade.i.IThreadType}
     * will call this for you. You will {@link #fork()} when all prerequisite tasks have completed
     * to <code>{@link #isDone()} == true</code> state. If this <code>RunnableAltFuture</code> is part of an asynchronous functional
     * chain, subscribe it will be forked for you when the prerequisites have finished.
     * <p>
     * This is called for you from the {@link IThreadType}'s {@link java.util.concurrent.ExecutorService}
     */
    @Override
    @NotCallOrigin
    public final void run() {
        boolean stateChanged = false;

        try {
            if (isCancelled()) {
                RCLog.d(this, "RunnableAltFuture was cancelled before execution. state=" + stateAR.get());
                throw new CancellationException("Cancelled before execution started: " + stateAR.get().toString());
            }
            final OUT out = mAction.call();

            if (!(stateAR.compareAndSet(VALUE_NOT_AVAILABLE, out) || stateAR.compareAndSet(FORKED, out))) {
                RCLog.d(this, "RunnableAltFuture was cancelled() or otherwise changed during execution. Returned from of function is ignored, but any direct side-effects not cooperatively stopped or rolled back in mOnError()/onCatch() are still in effect. state=" + stateAR.get());
                throw new CancellationException(stateAR.get().toString());
            }
            stateChanged = true;
        } catch (CancellationException e) {
            stateChanged = cancel("RunnableAltFuture threw a CancellationException (accepted behavior, will not fail fast): " + e);
            stateChanged = true;
        } catch (InterruptedException e) {
            stateChanged = cancel("RunnableAltFuture was interrupted (may be normal but NOT RECOMMENDED as behaviour is non-deterministic, but app will not fail fast): " + e);
        } catch (Exception e) {
            AltFutureStateError stateError = new AltFutureStateError("RunnableAltFuture run problem", e);

            if (!(stateAR.compareAndSet(VALUE_NOT_AVAILABLE, stateError) && !(stateAR.compareAndSet(FORKED, stateError)))) {
                RCLog.i(this, "RunnableAltFuture had a problem, but can not transition to stateError as the state has already changed. This is either a logic error or a possible but rare legitimate cancel() race condition: " + e);
                stateChanged = true;
            }
        } finally {
            if (stateChanged) {
                if (!isDone()) {
                    RCLog.e(this, "Not done");
                }
                try {
                    doThen();
                } catch (Exception e) {
                    RCLog.e(this, "RunnableAltFuture.run() state=" + stateAR.get() + "\nProblem in resulting .doThen()", e);
                }

                try {
                    clearPreviousAltFuture(); // Allow garbage collect of past values as the chain burns
                } catch (Exception e) {
                    RCLog.e(this, "RunnableAltFuture.run() state=\" + stateAR.get() + \"\nCan not clearPreviousAltFuture()", e);
                }
            }
        }
    }

    /**
     * Called from {@link AbstractAltFuture#fork()} if preconditions for forking are met.
     * <p>
     * Non-atomic check-do race conditions must still guard from this point on against concurrent fork()
     */
    @CallSuper
    @NotCallOrigin
    protected void doFork() {
        this.threadType.fork(this);
    }
} @NotCallOrigin
public class SettableAltFuture<T> extends AbstractAltFuture<T, T> implements ISettableAltFuture<T> {
    /**
     * Create, from is not yet determined
     *
     * @param threadType on which downchain actions continue
     */
    public SettableAltFuture(@NonNull IThreadType threadType) {
        super(threadType);
    }

    /**
     * Create, immutable from is set and will immediately fork() downchain actions
     *
     * @param threadType on which downchain actions continue
     * @param value
     */
    public SettableAltFuture(@NonNull IThreadType threadType,
                             @NonNull T value) {
        this(threadType);
        set(value);
    }

    @Override // ISettable
    public void set(@NonNull T value) {
        if (stateAR.compareAndSet(VALUE_NOT_AVAILABLE, value) || stateAR.compareAndSet(FORKED, value)) {
            // Previous state was FORKED, so set completes the mOnFireAction and continues the chain
            RCLog.v(this, "SettableAltFuture set, from= " + value);
            doFork();
            clearPreviousAltFuture();
            return;
        }

        // Already set, cancelled or error state
        RCLog.throwIllegalArgumentException(this, "Attempted to set " + this + " to from=" + value + ", but the from can only be set once and was already set to from=" + get());
    }

    protected void doFork() {
        // This is not an IRunnableAltFuture, so nothing to fork() or run(). But RunnableAltFuture overrides this and does more
    }
} 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 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);
}
import android.support.annotation.CheckResult;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.reactivecascade.Async;
import com.reactivecascade.BuildConfig;
import com.reactivecascade.functional.ImmutableValue;
import com.reactivecascade.functional.RunnableAltFuture;
import com.reactivecascade.functional.SettableAltFuture;
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.IRunnableAltFuture;
import com.reactivecascade.i.ISettableAltFuture;
import com.reactivecascade.i.IThreadType;
import com.reactivecascade.i.NotCallOrigin;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
/*
This file is part of Reactive Cascade which is released under The MIT License.
See license.md , https://github.com/futurice/cascade and http://reactivecascade.com for details.
This is open source for the common good. Please contribute improvements by pull request or contact paulirotta@gmail.com
*/
package com.reactivecascade.util;




/**
 * The baseline implementation of ThreadType convenience classes. It provides functional interfaces
 * (lambda-friendly if you are using the RetroLambda library or similar) to execRunnable code in a background
 * WORKER thread pool.
 * <p>
 * For more specialized behaviour a class may choose to replace this.
 * <p>
 */
public abstract class AbstractThreadType extends Origin implements IThreadType {
    @NonNull
    protected final ExecutorService executorService;

    @Nullable
    protected final BlockingQueue<Runnable> queue;

    @NonNull
    private final String name;

    /**
     * Create an asynchronous mOnFireAction handler that embodies certain rules for threading split concurrency
     * in a set of lambda-friendly methods
     *
     * @param executorService the thread or thread pool for this thread type. Threads and thread pools may be
     *                        shared with other thread types, however note that though this this cooperative execution
     *                        reduces context switching and peak memory load it may delay the start of execution
     *                        of tasks in one thread type by tasks in another thread type
     */
    public AbstractThreadType(@NonNull String name,
                              @NonNull ExecutorService executorService,
                              @Nullable BlockingQueue<Runnable> queue) {
        this.name = name;
        this.executorService = executorService;
        this.queue = queue;
    }

//============================= Internal Utility Methods =========================================

    private static boolean isMistakenlyCalledDirectlyFromOutsideTheCascadeLibrary() {
        //TODO This check doesn't really allow 3rd party implementations. Not testing would mean unsafe/less obvious problems can come later. Package hiding would disallow replacement implementations that follow the interface contracts. What we have here is a half measure to guide people since currently there are no alternate implementations.
        StackTraceElement[] ste = Thread.currentThread().getStackTrace();
        AssertUtil.assertTrue("Stack trace[3] is AbstractThreadType.fork(IRunnableAltFuture)", ste[3].getMethodName().contains("fork"));
        return !ste[4].getClassName().startsWith("com.reactivecascade");
    }

    @NotCallOrigin
    public abstract void run(@NonNull Runnable runnable);

    private <IN, OUT> IAltFuture<IN, OUT> runAltFuture(@NonNull IRunnableAltFuture<IN, OUT> altFuture) {