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

flabbergast.Computation Maven / Gradle / Ivy

package flabbergast;

import java.util.ArrayList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * A generic computation to be worked on by the TaskMaster.
 */
public abstract class Computation {

    /**
     * Apply an override to a normal computation resulting in another normal
     * computation.
     */
    public static ComputeValue performOverride(final String filename,
            final int start_line, final int start_column, final int end_line,
            final int end_column, final ComputeOverride wrapper,
            final ComputeValue original) {
        return new ComputeValue() {

            @Override
            public Computation invoke(TaskMaster task_master,
                                      SourceReference reference, Context context, Frame self,
                                      Frame container) {
                SourceReference inner_reference = new BasicSourceReference(
                    "used by override", filename, start_line, start_column,
                    end_line, end_column, reference);
                if (original == null) {
                    return new FailureComputation(task_master, inner_reference,
                                                  "override of non-existant attribute");
                }

                return wrapper.invoke(task_master, reference, context, self,
                                      container, original.invoke(task_master,
                                              inner_reference, context, self, container));
            }

        };
    }

    /**
     * The delegate(s) to be invoked when the computation is complete.
     */
    private ArrayList consumer = new ArrayList();
    /**
     * The return value of the computation.
     *
     * This should be assigned by the subclass.
     */
    protected Object result = null;

    protected final TaskMaster task_master;

    private boolean virgin = true;

    private final Lock ex = new ReentrantLock();

    public Computation(TaskMaster task_master) {
        this.task_master = task_master;
    }

    /**
     * Called by the TaskMaster to start or continue computation.
     */
    void compute() {
        if (result == null) {
            run();
            if (result == null) {
                return;
            }
            wakeupListeners();
        }
    }

    /**
     * Attach a callback when the computation is complete. If already complete,
     * the callback is immediately invoked.
     */
    public void listen(ConsumeResult new_consumer) {
        listen(new_consumer, true);
    }

    public void listen(ConsumeResult new_consumer, boolean needs_slot) {
        ex.lock();
        if (result == null) {
            consumer.add(new_consumer);
            if (needs_slot) {
                slotHelper();
            }
            ex.unlock();
        } else {
            ex.unlock();
            new_consumer.consume(result);
        }
    }

    public void listenDelayed(ConsumeResult new_consumer) {
        listen(new_consumer, false);
    }

    /**
     * The method that will be invoked when the result is needed.
     */
    protected abstract void run();

    public void slot() {
        ex.lock();
        if (result == null) {
            slotHelper();
        }
        ex.unlock();
    }

    private void slotHelper() {
        if (virgin && task_master != null) {
            virgin = false;
            task_master.slot(this);
        }
    }

    protected void wakeupListeners() {
        if (result == null) {
            throw new UnsupportedOperationException();
        }
        ex.lock();
        ArrayList consumer_copy = consumer;
        consumer = null;
        ex.unlock();

        if (consumer_copy == null) {
            return;
        }

        for (ConsumeResult cr : consumer_copy) {
            cr.consume(result);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy