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

il.ac.bgu.cs.bp.bpjs.model.BThreadSyncSnapshot Maven / Gradle / Ivy

Go to download

Provides runtime and analysis for behavioral programs written in JavaScript. It can run stand-alone (from the commmandline) or be embedded in larger JVM-based systems.

The newest version!
package il.ac.bgu.cs.bp.bpjs.model;

import il.ac.bgu.cs.bp.bpjs.execution.jsproxy.MapProxy;
import il.ac.bgu.cs.bp.bpjs.internal.ScriptableUtils;
import java.io.Serializable;
import java.util.Map;
import java.util.Optional;

import org.mozilla.javascript.Function;
import org.mozilla.javascript.NativeContinuation;
import org.mozilla.javascript.Scriptable;

import java.util.Objects;

/**
 * The state of a BThread at {@code bsync}.
 *
 * @author orelmosheweinstock
 * @author Michael
 */
public class BThreadSyncSnapshot implements Serializable {

    /**
     * Name of the BThread described
     */
    private String name;

    /**
     * The JavaScript function that will be called when {@code this} BThread
     * runs.
     */
    private final Function entryPoint;

    /**
     * BThreads may specify a function that runs when they are removed because
     * of a {@code breakUpon} statement.
     */
    private Function interruptHandler = null;

    /**
     * Continuation of the code.
     */
    private NativeContinuation continuation;

    /**
     * BSync statement of the BThread at the time of the snapshot.
     */
    private SyncStatement syncStatement;
    
    /**
     * BThread-global data object. Can be anything. For verification, needs
     * to be serializable, and with proper {@code equals} and {@code hashCode}.
     */
    private Object data;
    
    /** 
     * The changes to the b-program data this b-thread wants to make.
     * These changes are not part of the sync snapshot serialized form, since at
     * the serialization (i.e. after entering a sync point) all changes have been 
     * applied to the program state, or we would have not been able to get into 
     * the sync point due to conflict.
     */
    protected transient MapProxy bprogramStoreModifications;

    /**
     * Fully detailed constructor. Mostly useful for getting objects out of
     * serialized forms.
     *
     * @param name              name of the b-thread
     * @param entryPoint        function where the b-thread starts
     * @param interruptHandler  function to handle interrupts (or {@code null}, mostly)
     * @param continuation      captured b-thread continuation
     * @param bSyncStatement    current statement of the b-thread
     * @param someData          data for the b-thread (mqy be null).
     * @param modifications     modifications to the b-program store
     */
    public BThreadSyncSnapshot(String name, Function entryPoint, Function interruptHandler,
            Object continuation, SyncStatement bSyncStatement, Object someData, MapProxy modifications) {
        this.name = name;
        this.entryPoint = entryPoint;
        this.interruptHandler = interruptHandler;
        this.continuation = (NativeContinuation)continuation;
        this.syncStatement = bSyncStatement;
        data = someData;
        bprogramStoreModifications = modifications;
    }

    public BThreadSyncSnapshot(String aName, Function anEntryPoint, BProgram bprog) {
        this(aName, anEntryPoint, null, null, null, null, new MapProxy(bprog.getStore()) );
    }
    
    /**
     * Creates the next snapshot of the BThread, after {@code this} snapshot
     * ran.
     *
     * @param aContinuation The BThread's continuation at the next sync.
     * @param aStatement The BThread's statement for the next sync.
     * @param storageModifications storage modifications created during the run.
     * @return a copy of {@code this} with updated continuation and statement.
     */
    public BThreadSyncSnapshot makeNext(Object aContinuation, SyncStatement aStatement, MapProxy storageModifications) {
        BThreadSyncSnapshot retVal = new BThreadSyncSnapshot(name, null, interruptHandler,
            aContinuation, aStatement, data, storageModifications);
        
        aStatement.setBthread(retVal);

        return retVal;
    }

    public SyncStatement getSyncStatement() {
        return syncStatement;
    }

    public void setSyncStatement(SyncStatement stmt) {
        syncStatement = stmt;
        if (syncStatement.getBthread() != this) {
            syncStatement.setBthread(this);
        }
    }

    public NativeContinuation getContinuation() {
        return continuation;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Optional getInterrupt() {
        return Optional.ofNullable(interruptHandler);
    }

    public void setInterruptHandler(Function anInterruptHandler) {
        interruptHandler = anInterruptHandler;
    }

    public Scriptable getScope() {
        return (continuation!=null) ? continuation : entryPoint;
    }

    public Function getEntryPoint() {
        return entryPoint;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
    
    public void setBaseStore( Map aBaseStore ) {
        bprogramStoreModifications.setSeed(aBaseStore);
    }
    
    public Map> getStorageModifications() {
        return bprogramStoreModifications.getModifications();
    }

    public void clearStorageModifications() {
        bprogramStoreModifications.reset();
    }
    
    /**
     * When {@code true}, this b-thread can continue. In cases where the return
     * value is {@code false}, this object holds data about the results of the 
     * b-thread execution, e.g. storage modifications.
     * 
     * @return {@code true} iff this b-thread can run another round.
     */
    public boolean canContinue(){
        return (getContinuation()!=null) || (getEntryPoint()!=null);
    }
        
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = prime * Objects.hash(name, syncStatement);
        if (continuation != null) {
            result += continuation.getImplementation().hashCode();
        }
        result += ScriptableUtils.jsHashCode(data);
        return result;
    }

    @Override
    public boolean equals(Object obj) {

        // Quick circuit-breakers
        if (this == obj) return true;
        if (obj == null) return false;
        if (!(obj instanceof BThreadSyncSnapshot)) return false;
        
        BThreadSyncSnapshot other = (BThreadSyncSnapshot) obj;
        
        if (!Objects.equals(getName(), other.getName())) {
            return false;
        }
        if ( ! Objects.equals(syncStatement,other.getSyncStatement()) ) {
            return false;
        }
        
        if ( (!ScriptableUtils.jsEquals(data,other.getData())) ||
              (!Objects.equals(bprogramStoreModifications,other.bprogramStoreModifications)) ) {
            return false;
        }
        
        if (continuation == null) {
            // This b-thread hasn't run yet. Check eqality on its source.
            return (other.continuation == null) && entryPoint.equals(other.entryPoint);
        } else {
            // Check equality on the PC+stack+heap
//            return getContinuationProgramState().equals(other.getContinuationProgramState());
            return NativeContinuation.equalImplementations(continuation,other.getContinuation());
        }
    }

    @Override
    public String toString() {
        return "[BThreadSyncSnapshot: " + name + " @" + hashCode() + "]";
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy