/** * Copyright (c) 2009-2011, The HATS Consortium. All rights reserved. * This file is licensed under the terms of the Modified BSD License. */ package abs.backend.java.visualization; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Stroke; import java.util.Arrays; import java.util.Random; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.SwingUtilities; import abs.backend.java.lib.runtime.ABSException; import abs.backend.java.lib.types.ABSValue; import abs.backend.java.observing.COGView; import abs.backend.java.observing.FutView; import abs.backend.java.observing.GuardView; import abs.backend.java.observing.ObjectView; import abs.backend.java.observing.SystemObserver; import abs.backend.java.observing.TaskObserver; import abs.backend.java.observing.TaskSchedulerObserver; import abs.backend.java.observing.TaskStackFrameView; import abs.backend.java.observing.TaskView; public class TaskStateHistoryObserver implements SystemObserver,TaskSchedulerObserver, TaskObserver { int[] activeTasks = new int[200]; int[] suspendedTasks = new int[200]; int[] readyTasks = new int[200]; int[] deadlockedTasks = new int[200]; int[] blockedTasks = new int[200]; int nsteps = 0; private final TaskHistoryViewer gui = new TaskHistoryViewer(this); @Override public void systemStarted() { } @Override public void newCOGCreated(COGView cog, ObjectView initialObject) { cog.getScheduler().registerTaskSchedulerObserver(this); } @Override public void taskCreated(final TaskView task) { if (task != null) task.registerTaskListener(this); // readyTasks[nsteps] = readyTasks[nsteps]+1; readyTasks[nsteps] = readyTasks[nsteps]+1; } @Override public synchronized void taskReady(TaskView view) { //readyTasks[nsteps] = readyTasks[nsteps]+1; } @Override public synchronized void taskResumed(TaskView runningTask, GuardView view) { activeTasks[nsteps]++; suspendedTasks[nsteps]--; } @Override public synchronized void taskSuspended(TaskView task, GuardView guard) { activeTasks[nsteps]--; suspendedTasks[nsteps]++; } @Override public synchronized void taskStarted(TaskView task) { readyTasks[nsteps] = readyTasks[nsteps]-1; activeTasks[nsteps] = activeTasks[nsteps]+1; System.out.println("Task started : "+activeTasks[nsteps]); } @Override public synchronized void taskFinished(TaskView task) { activeTasks[nsteps]--; } @Override public synchronized void taskBlockedOnFuture(TaskView task, FutView fut) { activeTasks[nsteps]--; blockedTasks[nsteps]++; } @Override public synchronized void taskRunningAfterWaiting(TaskView view, FutView fut) { blockedTasks[nsteps]--; activeTasks[nsteps]++; } @Override public synchronized void taskStep(TaskView task, String fileName, int line) { nsteps++; if (nsteps == activeTasks.length) { activeTasks = Arrays.copyOf(activeTasks, nsteps*2); blockedTasks = Arrays.copyOf(blockedTasks, nsteps*2); suspendedTasks = Arrays.copyOf(suspendedTasks, nsteps*2); readyTasks = Arrays.copyOf(readyTasks, nsteps*2); deadlockedTasks = Arrays.copyOf(deadlockedTasks, nsteps*2); } activeTasks[nsteps] = activeTasks[nsteps-1]; blockedTasks[nsteps] = blockedTasks[nsteps-1]; suspendedTasks[nsteps] = suspendedTasks[nsteps-1]; readyTasks[nsteps] = readyTasks[nsteps-1]; deadlockedTasks[nsteps] = deadlockedTasks[nsteps-1]; gui.update(); } @Override public void taskDeadlocked(TaskView task) { activeTasks[nsteps]--; deadlockedTasks[nsteps]++; } public static void main(String[] args) { test(); } private static void test() { TaskStateHistoryObserver o = new TaskStateHistoryObserver(); Random r = new Random(); for (int i = 0; i < 400; i++) { randomStep(o,r); } } private static void randomStep(TaskStateHistoryObserver o, Random r) { if (r.nextBoolean()) o.taskStep(null, null, 0); switch (r.nextInt(10)) { case 0: o.taskBlockedOnFuture(null, null); break; case 1: o.taskCreated(null); break; case 2: o.taskDeadlocked(null); break; case 3: o.taskFinished(null); break; case 4: o.taskReady(null); break; case 5: o.taskResumed(null, null); break; case 6: o.taskRunningAfterWaiting(null, null); break; case 7: o.taskStarted(null); break; case 8: o.taskStep(null, null, 0); break; case 9: o.taskSuspended(null, null); break; } } @Override public void stackFrameCreated(TaskView task, TaskStackFrameView stackFrame) { // TODO Auto-generated method stub } @Override public void localVariableChanged(TaskStackFrameView stackFrame, String name, ABSValue v) { // TODO Auto-generated method stub } @Override public void systemFinished() { // TODO Auto-generated method stub } @Override public void systemError(ABSException e) { // TODO Auto-generated method stub } @Override public void stackFrameRemoved(TaskView task, TaskStackFrameView oldFrame) { // TODO Auto-generated method stub } } class TaskHistoryViewer { private JFrame frame; private TaskStateHistoryObserver state; private Canvas canvas; private int drawWidth; private int drawHeight; public TaskHistoryViewer(TaskStateHistoryObserver state) { this.state = state; canvas = new Canvas(); canvas.setOpaque(true); frame = new JFrame("Task History"); frame.setLayout(new BorderLayout()); frame.add(BorderLayout.CENTER, canvas); frame.setLocation(400, 0); frame.setSize(600,300); frame.setVisible(true); } public void update() { canvas.repaint(); } class Canvas extends JComponent { private double xfactor; public void updateSizes() { drawWidth = (this.getWidth()-2*margin); drawHeight = (this.getHeight()-2*margin); xfactor = Math.min((double)drawWidth / state.nsteps,8); } @Override public void paint(Graphics arg0) { updateSizes(); Graphics2D g = (Graphics2D) arg0; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setStroke(new BasicStroke(1)); g.setBackground(Color.white); g.setColor(Color.white); Rectangle r = g.getClipBounds(); g.fillRect(r.x, r.y, r.width, r.height); g.setColor(Color.lightGray); g.drawRect(margin,margin, drawWidth, drawHeight); int xliney = margin; for (int x = 0; x <= state.nsteps/10; x++) { int xstep = (int) (x*10*xfactor); g.drawLine(xstep, xliney-5 , xstep, xliney+5); } g.setStroke(new BasicStroke(2)); synchronized (state) { drawArray(g, state.activeTasks, Color.GREEN); drawArray(g, state.blockedTasks, Color.RED); drawArray(g, state.suspendedTasks, Color.ORANGE); drawArray(g, state.deadlockedTasks, Color.BLACK); drawArray(g, state.readyTasks, Color.YELLOW); } } int margin = 20; private void drawArray(Graphics2D g, int[] tasks, Color lineColor) { g.setColor(lineColor); int n = state.nsteps; int lastx = margin; int lasty = drawHeight-margin; int fac = 4; for (int x = 0; x < n; x++) { int newx = margin+(int)(xfactor*(x+1)); int newy = drawHeight+margin-(fac*tasks[x]); g.drawLine(lastx,lasty,newx,newy); lastx = newx; lasty = newy; } } } }