/* * This file is part of the X10 project (http://x10-lang.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.opensource.org/licenses/eclipse-1.0.php * * This file was originally derived from the Polyglot extensible compiler framework. * * (C) Copyright 2000-2007 Polyglot project group, Cornell University * (C) Copyright IBM Corporation 2007-2012. */ package polyglot.util; import x10.util.CollectionFactory; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.ListIterator; import java.util.Map; /** * This class represents a set of calculations to be performed, some * of which have already been completed. It optionally stores the results of * those calculations. * * Requires: every 'calculation' object has a working hashcode and * toString method. **/ public class WorkList { /** * Creates a new, empty worklist. **/ public WorkList() { pending = new LinkedList<Object>(); results = CollectionFactory.newHashMap(); size = 0; } /** * Adds the calculation represented by <o> to the worklist, if it has not * already been calculated. **/ public void addWork(Object o) { if (! results.containsKey(o)) { results.put(o, NOT_CALCULATED); pending.addLast(o); size++; } } /** * Adds every member of the collection <c> to the worklist, if it * has not already been calculted. **/ public void addWork(Collection<Object> c) { for (Object o : c) addWork(o); } /** * Returns true iff there is no more work to do. **/ public boolean finished() { return size == 0; } /** * Returns the first element with no known result. Throws * NoSuchElementException if no such element exists. **/ public Object getWork() { if (size>0) return pending.getFirst(); else throw new java.util.NoSuchElementException("WorkList.getWork"); } /** * Announces that we have finished the calculation represented by <work>, * getting the result <result>. Removes <work> from the pending list, * and sets its result to <result> **/ public void finishWork(Object work, Object result) { if (results.get(work) == NOT_CALCULATED) { for (ListIterator<Object> i = pending.listIterator(); i.hasNext(); ) { if (i.next().equals(work)) i.remove(); } } results.put(work, result); } /** * Announces that we have finished the calculation represented by <work>. **/ public void finishWork(Object work) { finishWork(work, null); } /** * Returns true iff <work> has been completed. **/ public boolean isFinished(Object work) { return results.containsKey(work) && results.get(work) != NOT_CALCULATED; } /** * Returns an immutable view of a map from calculation objects to * their results. Non-computed values map to NOT_CALCULATED **/ public Map<Object, Object> getMap() { return Collections.unmodifiableMap(results); } // The list of objects to be calculated on. The oldest element is first. // RI: Every member of <pending> is a key in <results>. protected LinkedList<Object> pending; // A map from all objects to their results. Any object with no result // maps to NOT_CALCULATED. protected Map<Object, Object> results; // The number of elements in pending. protected int size; public static final Object NOT_CALCULATED = new Object(); }