class StateMachine {

    public boolean setIf(T newState, Predicate<T> predicate)
    {
        checkState(!Thread.holdsLock(lock), "Cannot set state while holding the lock");
        requireNonNull(newState, "newState is null");

        while (true) {
            // check if the current state passes the predicate
            T currentState = get();

            // change to same state is not a change, and does not notify the notify listeners
            if (currentState.equals(newState)) {
                return false;
            }

            // do not call predicate while holding the lock
            if (!predicate.test(currentState)) {
                return false;
            }

            // if state did not change while, checking the predicate, apply the new state
            if (compareAndSet(currentState, newState)) {
                return true;
            }
        }
    }

    public  StateMachine(String name, Executor executor, T initialState);
    public  StateMachine(String name, Executor executor, T initialState, Iterable<T> terminalStates);

}