package arkref.ext.fig.basic; import java.util.*; import java.lang.ThreadLocal; /** * 4/2/09: StopWatchSet should be re-entrant (can call begin("foo") twice) and thread-safe. */ public class StopWatchSet { // For measuring time of certain types of events. // Shared across all threads. private static Map<String, StopWatch> stopWatches = new LinkedHashMap<String, StopWatch>(); // A stack of stop-watches (one per thread) private static ThreadLocal<LinkedList<Pair<String,StopWatch>>> lastStopWatches = new ThreadLocal() { protected LinkedList<Pair<String,StopWatch>> initialValue() { return new LinkedList(); } }; public synchronized static StopWatch getWatch(String s) { return MapUtils.getMut(stopWatches, s, new StopWatch()); } public static void begin(String s) { // Create a new stop watch for reentrance and thread safety lastStopWatches.get().addLast(new Pair(s, new StopWatch().start())); } public static void end() { Pair<String,StopWatch> pair = lastStopWatches.get().removeLast(); pair.getSecond().stop(); // Add it synchronized(stopWatches) { getWatch(pair.getFirst()).add(pair.getSecond()); } } public synchronized static OrderedStringMap getStats() { OrderedStringMap map = new OrderedStringMap(); for(String key : stopWatches.keySet()) { StopWatch watch = getWatch(key); map.put(key, watch + " (" + new StopWatch(watch.n == 0 ? 0 : watch.ms/watch.n) + " x " + watch.n + ")"); } return map; } }