/* * This file is part of the Jikes RVM project (http://jikesrvm.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 * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package test.org.jikesrvm.basic.core.threads; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.Set; /** * Utility class to make it easier to generate deterministic output by caching output per thread and outputting it at end. */ abstract class XThread extends Thread { static class ThreadRecord { final String name; final LinkedList<String> messages = new LinkedList<String>(); final Thread thread; ThreadRecord(final String name, final Thread thread) { this.name = name; this.thread = thread; } } private static final Map<Integer, ThreadRecord> records = new HashMap<Integer, ThreadRecord>(); private static final ThreadRecord mainRecord = new ThreadRecord("Main", null); static { records.put(0, mainRecord); } private static int maxId = 1; static boolean holdMessages = !"false".equals(System.getProperty("tests.DeterministicOutput")); private final ThreadRecord record; private final int id; boolean completed; boolean running; public XThread(String name) { super(name); synchronized (XThread.class) { id = maxId++; } record = new ThreadRecord(name, this); records.put(id, record); tsay("creating"); } public synchronized void start() { tsay("starting"); super.start(); } public void run() { tsay("run starting"); running = true; try { performTask(); } finally { tsay("run finishing"); } completed = true; } abstract void performTask(); void tsay(final String message) { if (holdMessages) { record.messages.add(message); } else { output(id, record.name, message); } } public static void say(final String message) { final Thread thread = Thread.currentThread(); final int id = (thread instanceof XThread) ? ((XThread) thread).id : 0; final ThreadRecord record = records.get(id); if (holdMessages) { record.messages.add(message); } else { output(id, record.name, message); } } public static synchronized void joinOnAll() { for (ThreadRecord record : records.values()) { if (null != record.thread && record.thread.isAlive()) { try { record.thread.join(); } catch (final InterruptedException ie) { } } } } public static synchronized void outputMessages() { joinOnAll(); final Set<Integer> keySet = records.keySet(); final ArrayList<Integer> ids = new ArrayList<Integer>(keySet.size()); ids.addAll(keySet); Collections.sort(ids); for (final Integer id : ids) { final ThreadRecord record = records.get(id); for (final String message : record.messages) { final String name = record.name; output(id, name, message); } } } private static void output(final int id, final String name, final String message) { System.out.println("Thread " + id + " " + name + ": " + message); } }