/* 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.functional; import android.support.annotation.NonNull; import com.reactivecascade.i.IAltFuture; import com.reactivecascade.i.ISettableAltFuture; import com.reactivecascade.i.IThreadType; import com.reactivecascade.i.NotCallOrigin; import com.reactivecascade.util.RCLog; /** * An {@link IAltFuture} on which you can {@link SettableAltFuture#set(Object)} * one time to change state * <p> * Note that a <code>SettableAltFuture</code> is not itself {@link java.lang.Runnable}. You explicity {@link #set(Object)} * when the from is determined, and this changes the state to done. Therefore concepts like {@link IAltFuture#fork()} * and {@link IAltFuture#isForked()} do not have their traditional meanings. * <p> * {@link RunnableAltFuture} overrides this class. * TODO You may also use a {@link SettableAltFuture} to inject data where the from is determined from entirely outside of the current chain hierarchy. * This is currently an experimental feature so be warned, your results and chain behaviour may vary. Additional * testing is on the long list. * <p> * You may prefer to use {@link ImmutableValue} that a similar need in some cases. That is a * slightly faster, simpler implementation than {@link SettableAltFuture}. * <p> * TODO Would it be helpful for debugging to store and pass forward a reference to the object which originally detected the problem? It might help with filtering what mOnFireAction you want to do mOnError */ @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 } }