/*
 * Written by Dawid Kurzyniec and released to the public domain, as explained
 * at http://creativecommons.org/licenses/publicdomain
 */

package edu.emory.mathcs.util.gc;

import java.util.*;

import edu.emory.mathcs.util.concurrent.*;
import edu.emory.mathcs.backport.java.util.concurrent.*;

public class FinalizationStatus {
    Object result;
    Throwable exception;
    boolean done;
    List completionCallbacks = new ArrayList();
    public FinalizationStatus() {}
    public final void setCompleted(Object result) {
        synchronized (this) {
            if (done) throw new IllegalStateException("Already completed");
            this.result = result;
            this.done = true;
        }
        fireCallbacks();
    }
    public final void setFailed(Throwable cause) {
        synchronized (this) {
            if (done) throw new IllegalStateException("Already completed");
            this.exception = exception;
            this.done = true;
        }
        fireCallbacks();
    }

    // pre: done set
    synchronized Object getResult() throws ExecutionException {
        if (!done) throw new IllegalStateException();
        if (exception != null) throw new ExecutionException(exception);
        else return result;
    }

    final synchronized boolean addCompletionCallback(Callback cb) {
        if (done) return false;
        completionCallbacks.add(cb);
        return true;
    }

    private void fireCallbacks() {
        if (exception != null) {
            for (Iterator itr = completionCallbacks.iterator(); itr.hasNext();) {
                Callback cb = (Callback)itr.next();
                cb.failed(exception);
            }
        }
        else {
            for (Iterator itr = completionCallbacks.iterator(); itr.hasNext();) {
                Callback cb = (Callback)itr.next();
                cb.completed(result);
            }
        }
    }

    protected boolean cancel(boolean mayInterruptIfRunning) {
        return false;
    }
}
