import java.util.*;
public class GlobalFunc extends Process implements GlobalService {
    FuncUser prog;
    SpanTree tree = null;
    IntLinkedList pending = new IntLinkedList();
    int myValue;
    int answer;
    boolean answerRecvd;
    boolean pendingSet = false;
    public GlobalFunc(Linker initComm, boolean isRoot) {
        super(initComm);
        tree = new SpanTree(comm, isRoot);
    }
    public void initialize(int myValue, FuncUser prog) {
        this.myValue = myValue;
        this.prog = prog;
        tree.waitForDone();
        Util.println(myId + ":" + tree.children.toString());
    }
    public synchronized int computeGlobal() {
        pending.addAll(tree.children);
        pendingSet = true;
        notifyAll();
        while (!pending.isEmpty()) myWait();
        if (tree.parent == myId) { // root node
            answer = myValue;
        } else { //non-root node
            sendMsg(tree.parent, "subTreeVal", myValue);
            answerRecvd = false;
            while (!answerRecvd) myWait();
        }
        sendChildren(answer);
        return answer;
    }
    void sendChildren(int value) {
        ListIterator t = tree.children.listIterator(0);
        while (t.hasNext()) {
            Integer child = (Integer) t.next();
            sendMsg(child.intValue(), "globalFunc", value);
        }
    }
    public synchronized void handleMsg(Message m, int source, String tag) {
        tree.handleMsg(m,source,tag);
        if (tag.equals("subTreeVal")) {
            while (!pendingSet) myWait();
            pending.remove(new Integer(source));
            myValue = prog.func(myValue, m.getMessageInt());
            if (pending.isEmpty()) notifyAll();
        } else if (tag.equals("globalFunc")) {
            answer = m.getMessageInt();
            answerRecvd = true;
            notifyAll();
        }
    }
}