Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 package com.facebook.presto.execution;
 
 
 
 import java.util.List;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;

Simple state machine which holds a single value. Callers can register for state change events, and can wait for the state to change.
 
 public class StateMachine<T>
 {
     private static final Logger log = Logger.get(StateMachine.class);
 
     private final String name;
     private final Executor executor;
 
     @GuardedBy("this")
     private volatile T state;
 
     @GuardedBy("this")
     private final List<StateChangeListener<T>> stateChangeListeners = new ArrayList<>();
 
     @GuardedBy("this")
     private final List<SettableFuture<T>> futureStateChanges = new ArrayList<>();

    
Creates a state machine with the specified initial value

Parameters:
name name of this state machine to use in debug statements
executor executor for firing state change events; must not be a same thread executor
initialState the initial value
 
     public StateMachine(String nameExecutor executor, T initialState)
     {
         this. = checkNotNull(name"name is null");
         this. = checkNotNull(executor"executor is null");
         this. = checkNotNull(initialState"initialState is null");
     }
 
     public T get()
     {
         return ;
     }
 
     public ListenableFuture<T> getStateChange(T currentState)
     {
         checkState(!Thread.holdsLock(this), "Can not wait for state change while holding a lock on this");
 
         synchronized (this) {
             if (!Objects.equals(currentState)) {
                 return Futures.immediateFuture();
             }
 
             SettableFuture<T> futureStateChange = SettableFuture.create();
             .add(futureStateChange);
             return futureStateChange;
         }
     }

    
Sets the state. If the new state does not .equals() the current state, listeners and waiters will be notified.

Returns:
the old state
 
     public T set(T newState)
     {
         checkState(!Thread.holdsLock(this), "Can not set state while holding a lock on this");
        checkNotNull(newState"newState is null");
        T oldState;
        ImmutableList<SettableFuture<T>> futureStateChanges;
        ImmutableList<StateChangeListener<T>> stateChangeListeners;
        synchronized (this) {
            if (Objects.equals(newState)) {
                return ;
            }
            oldState = ;
             = newState;
            futureStateChanges = ImmutableList.copyOf(this.);
            this..clear();
            stateChangeListeners = ImmutableList.copyOf(this.);
            this.notifyAll();
        }
        fireStateChanged(newStatefutureStateChangesstateChangeListeners);
        return oldState;
    }

    
Sets the state if the current state satisfies the specified predicate. If the new state does not .equals() the current state, listeners and waiters will be notified.

Returns:
the old state
    public boolean setIf(T newValuePredicate<T> predicate)
    {
        checkState(!Thread.holdsLock(this), "Can not set state while holding a lock on this");
        while (true) {
            // check if the current state passes the predicate
            T currentState = get();
            // do not call back while holding a lock on this
            if (!predicate.apply(currentState)) {
                return false;
            }
            // if state did not change while, checking the predicate, apply the new state
            if (compareAndSet(currentStatenewValue)) {
                return true;
            }
        }
    }

    
Sets the state if the current state .equals() the specified expected state. If the new state does not .equals() the current state, listeners and waiters will be notified.

Returns:
the old state
    public boolean compareAndSet(T expectedState, T newState)
    {
        checkState(!Thread.holdsLock(this), "Can not set state while holding a lock on this");
        checkNotNull(expectedState"expectedState is null");
        checkNotNull(newState"newState is null");
        ImmutableList<SettableFuture<T>> futureStateChanges;
        ImmutableList<StateChangeListener<T>> stateChangeListeners;
        synchronized (this) {
            if (!Objects.equals(expectedState)) {
                return false;
            }
            if (Objects.equals(newState)) {
                // successfully changed to the same state, no need to notify
                return true;
            }
             = newState;
            futureStateChanges = ImmutableList.copyOf(this.);
            this..clear();
            stateChangeListeners = ImmutableList.copyOf(this.);
            this.notifyAll();
        }
        fireStateChanged(newStatefutureStateChangesstateChangeListeners);
        return true;
    }
    private void fireStateChanged(
            final T newState,
            final ImmutableList<SettableFuture<T>> futureStateChanges,
            final ImmutableList<StateChangeListener<T>> stateChangeListeners)
    {
        checkState(!Thread.holdsLock(this), "Can not fire state change event while holding a lock on this");
        .execute(new Runnable()
        {
            @Override
            public void run()
            {
                checkState(!Thread.holdsLock(StateMachine.this), "Can not notify while holding a lock on this");
                for (SettableFuture<T> futureStateChange : futureStateChanges) {
                    try {
                        futureStateChange.set(newState);
                    }
                    catch (Throwable e) {
                        .error(e"Error setting future state for %s");
                    }
                }
                for (StateChangeListener<T> stateChangeListener : stateChangeListeners) {
                    try {
                        stateChangeListener.stateChanged(newState);
                    }
                    catch (Throwable e) {
                        .error(e"Error notifying state change listener for %s");
                    }
                }
            }
        });
    }

    
Adds a listener to be notified when the state instance changes according to .equals().
    public synchronized void addStateChangeListener(StateChangeListener<T> stateChangeListener)
    {
        .add(stateChangeListener);
    }

    
Wait for the state to not be .equals() to the specified current state.
    public Duration waitForStateChange(T currentStateDuration maxWait)
            throws InterruptedException
    {
        checkState(!Thread.holdsLock(this), "Can not wait for state change while holding a lock on this");
        if (!Objects.equals(currentState)) {
            return maxWait;
        }
        // wait for task state to change
        long remainingNanos = maxWait.roundTo();
        long start = System.nanoTime();
        long end = start + remainingNanos;
        synchronized (this) {
            while (remainingNanos > 0 && Objects.equals(currentState)) {
                // wait for timeout or notification
                .timedWait(thisremainingNanos);
                remainingNanos = end - System.nanoTime();
            }
        }
        if (remainingNanos < 0) {
            remainingNanos = 0;
        }
        return new Duration(remainingNanos);
    }
    public interface StateChangeListener<T>
    {
        void stateChanged(T newValue);
    }
    @Override
    public String toString()
    {
        return String.valueOf(get());
    }
New to GrepCode? Check out our FAQ X