All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.praxislive.base.DefaultExecutionContext Maven / Gradle / Ivy

Go to download

Forest-of-actors runtime supporting real-time systems and real-time recoding - bringing aspects of Erlang, Smalltalk and Extempore to Java.

There is a newer version: 6.0.0-beta2
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 2020 Neil C Smith.
 * 
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 3 only, as
 * published by the Free Software Foundation.
 * 
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * version 3 for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License version 3
 * along with this work; if not, see http://www.gnu.org/licenses/
 * 
 * 
 * Please visit https://www.praxislive.org if you need additional information or
 * have any questions.
 */
package org.praxislive.base;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import org.praxislive.core.ExecutionContext;

/**
 * Default implementation of {@link ExecutionContext} for use with
 * {@link AbstractRoot}
 */
public class DefaultExecutionContext implements ExecutionContext {

    private final List stateListeners;
    private final List clockListeners;
    
    private ExecutionContext.State state;
    long time;
    private long startTime;

    /**
     * Create a DefaultExecutionContext
     *
     * @param time initial clock time / start time
     */
    public DefaultExecutionContext(long time) {
        this.stateListeners = new CopyOnWriteArrayList<>();
        this.clockListeners = new CopyOnWriteArrayList<>();
        this.state = ExecutionContext.State.NEW;
        this.time = this.startTime = time;
    }

    @Override
    public void addStateListener(ExecutionContext.StateListener listener) {
        stateListeners.add(Objects.requireNonNull(listener));
    }

    @Override
    public void removeStateListener(ExecutionContext.StateListener listener) {
        stateListeners.remove(listener);
    }

    @Override
    public void addClockListener(ExecutionContext.ClockListener listener) {
        clockListeners.add(Objects.requireNonNull(listener));
    }

    @Override
    public void removeClockListener(ExecutionContext.ClockListener listener) {
        clockListeners.remove(listener);
    }

    /**
     * Update the state. Will call all state listeners.
     *
     * @param time time of state change (if ACTIVE also the new start time)
     * @param state new state
     * @throws IllegalStateException if attempting to reset to NEW from another
     * state, or attempting to set to another state if current state is
     * TERMINATED
     */
    @SuppressWarnings(value = "fallthrough")
    protected void updateState(long time, ExecutionContext.State state) {
        // make sure time is set before state listeners called.
        this.time = time;
        switch (state) {
            case ACTIVE:
                if (this.state != ExecutionContext.State.ACTIVE) {
                    startTime = time;
                }
            case IDLE:
                if (this.state == ExecutionContext.State.TERMINATED) {
                    throw new IllegalStateException("Execution Context terminated");
                }
            // fall through
            case TERMINATED:
                if (this.state != state) {
                    this.state = state;
                    fireStateListeners();
                }
                break;
            case NEW:
                if (this.state != ExecutionContext.State.NEW) {
                    throw new IllegalStateException("Can't make Execution Context NEW again.");
                }
                break;
            default:
                throw new RuntimeException();
        }
    }

    @Override
    public ExecutionContext.State getState() {
        return state;
    }

    /**
     * Update the clock time. Will call all clock listeners.
     *
     * @param time
     */
    protected void updateClock(long time) {
        this.time = time;
        if (state == ExecutionContext.State.ACTIVE) {
            fireClockListeners();
        }
    }

    @Override
    public long getTime() {
        return time;
    }

    @Override
    public long getStartTime() {
        return startTime;
    }

    private void fireStateListeners() {
        stateListeners.forEach(l -> l.stateChanged(this));
    }

    private void fireClockListeners() {
        clockListeners.forEach(l -> l.tick(this));
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy