Menu

Visual test

Krzysztof Dębski

/*************

  • Copyright (c) 2009-2013 Krzysztof Dębski.
  • All rights reserved.
    *************/
    package pfor.sample;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JSpinner;
import javax.swing.JToggleButton;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;

import pfor.CompletionCallback;
import pfor.PTask;
import pfor.ParallelContext;
import pfor.ProgressCallback;
import pfor.annotations.Speed.SpeedType;
import pfor.closures.index.IndexAction;
import pfor.closures.range.RangeAction;
import pfor.sample.util.Stopwatch;

import com.spinn3r.log5j.Logger;

public class VisualTest implements CompletionCallback<void>, ProgressCallback {</void>

@SuppressWarnings("serial")
private static class DebugException extends Exception {
}

private class DrawIndexAction extends IndexAction {
    final int rowCount;

    public DrawIndexAction(int rowCount, SpeedType speed) {
        super(speed);
        this.rowCount = rowCount;
    }

    @Override
    public void perform(int i) throws Exception {
        work(i, rowCount, (int) Thread.currentThread().getId() % colors.length);
    }
}

private class DrawRangeAction extends RangeAction {
    final int rowCount;

    public DrawRangeAction(int rowCount, SpeedType speed) {
        super(speed);
        this.rowCount = rowCount;
    }

    @Override
    public void perform(int start, int end) throws Exception {
        final int thread = (int) Thread.currentThread().getId() % colors.length;
        for (int i = start; i < end; i++) {
            work(i, rowCount, thread);
        }
    }
}

private static enum ExecutionType {
    ASYNCHRONOUS, FAST_CANCEL, SYNCHRONOUS
}

private enum ForType {
    PFOR_INDEX, PFOR_RANGE, SIMPLE_LOOP
}

private static final Logger log = Logger.getLogger();

public static void main(String[] args) throws InterruptedException, ExecutionException {
    final VisualTest test = new VisualTest();
    test.loopRepaint();
};

BufferedImage image;

Graphics2D graphics;
final static Color[] colors = { Color.RED, Color.BLUE, Color.CYAN, Color.GREEN, Color.MAGENTA,
        Color.GRAY, Color.WHITE, Color.PINK };
volatile Future<Void> future = null;
JComboBox speedCombo = new JComboBox(SpeedType.values());
JComboBox executionCombo = new JComboBox(ExecutionType.values());
final SpinnerNumberModel threadsSpinnerModel = new SpinnerNumberModel(2, 1, 100, 1);
final SpinnerNumberModel xSpinnerModel = new SpinnerNumberModel(500, 1, 1000, 1);
final SpinnerNumberModel ySpinnerModel = new SpinnerNumberModel(500, 1, 1000, 1);
JPanel panel;
final JPanel outerPanel = new JPanel();
final JPanel topPanel = new JPanel();
final JPanel controlPanel = new JPanel();
final JPanel optionsPanel = new JPanel();
final JPanel bottomPanel = new JPanel();
final JFrame frame = new JFrame();
final JButton startB = new JButton("Start (pfor indexed based)");
final JButton rangeB = new JButton("Start (pfor range based)");
final JButton simpleB = new JButton("Start (plain loop)");
final JButton cancelB = new JButton("Cancel");
final JToggleButton exceptionB = new JToggleButton("Exception");
final JButton resetB = new JButton("Reset");

final Stopwatch stopwatch = new Stopwatch();
final JLabel timeL = new JLabel("      ");
final JCheckBox completeBox = new JCheckBox("Completion notyfication", true);

final JCheckBox progressBox = new JCheckBox("Progress notyfication", true);
final JCheckBox excBox = new JCheckBox("Cancel on exception", true);

JProgressBar progressBar;

ParallelContext context;

int steps;

int foo;

static final AtomicBoolean throwException = new AtomicBoolean(false);

private VisualTest() {
    final JSpinner threadsS = new JSpinner(threadsSpinnerModel);
    final JSpinner xS = new JSpinner(xSpinnerModel);
    final JSpinner yS = new JSpinner(ySpinnerModel);

    startB.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            try {
                start(ForType.PFOR_INDEX);
            } catch (final DebugException e) {
                e.printStackTrace();
            }
        }
    });

    rangeB.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            try {
                start(ForType.PFOR_RANGE);
            } catch (final DebugException e) {
                e.printStackTrace();
            }
        }
    });

    simpleB.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            try {
                start(ForType.SIMPLE_LOOP);
            } catch (final DebugException e) {
                e.printStackTrace();
            }
        }
    });

    cancelB.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            cancel();
        }
    });

    exceptionB.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            throwException();
        }
    });

    resetB.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            reset();
        }
    });

    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            topPanel.add(new JLabel("Threads:"));
            topPanel.add(threadsS);
            topPanel.add(new JLabel("X:"));
            topPanel.add(xS);
            topPanel.add(new JLabel("Y:"));
            topPanel.add(yS);
            topPanel.add(new JLabel("Assumed task speed:"));
            topPanel.add(speedCombo);
            topPanel.add(new JLabel("Execution type:"));
            topPanel.add(executionCombo);
            optionsPanel.add(progressBox);
            optionsPanel.add(completeBox);
            optionsPanel.add(excBox);

            controlPanel.add(startB);
            controlPanel.add(rangeB);
            controlPanel.add(simpleB);
            controlPanel.add(cancelB);
            controlPanel.add(exceptionB);
            controlPanel.add(resetB);
            controlPanel.add(timeL);

            outerPanel.setLayout(new BoxLayout(outerPanel, BoxLayout.Y_AXIS));
            outerPanel.add(topPanel);
            outerPanel.add(optionsPanel);
            outerPanel.add(controlPanel);
            outerPanel.add(bottomPanel);

            frame.setSize(new Dimension(600, 600));
            frame.getContentPane().add(outerPanel);
            frame.pack();

            reset();
            frame.setVisible(true);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }
    });

}

private void cancel() {
    cancelB.setEnabled(false);

    if (future != null) {
        future.cancel(true);
    }

    frame.repaint();
};

private void disableStart() {
    startB.setEnabled(false);
    rangeB.setEnabled(false);
    simpleB.setEnabled(false);
}

@SuppressWarnings("serial")
private void loop(int threads, SpeedType speed, ForType forType) throws DebugException {

    final int x = (Integer) xSpinnerModel.getNumber();
    final int y = (Integer) ySpinnerModel.getNumber();
    steps = x * y;

    image = new BufferedImage(x, y, BufferedImage.TYPE_INT_RGB);
    graphics = image.createGraphics();
    if (panel != null) {
        bottomPanel.remove(panel);
    }

    if (progressBar != null) {
        controlPanel.remove(progressBar);
    }

    progressBar = new JProgressBar(0, steps + 1);
    controlPanel.add(progressBar);

    panel = new JPanel() {
        @Override
        public void paint(Graphics g) {
            super.paint(g);
            final Graphics2D graphics2D = (Graphics2D) g;
            graphics2D.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
        }

    };

    panel.setSize(new Dimension(x, y));
    panel.setPreferredSize(new Dimension(x, y));
    bottomPanel.add(panel);

    frame.pack();

    if (context != null) {
        context.shutdown();
    }

    context = ParallelContext.newInstance(threads);

    stopwatch.start();
    if (forType == ForType.SIMPLE_LOOP) {
        simpleFor(x, y);
        return;
    }

    PTask<Void> action = forType == ForType.PFOR_INDEX ? context.getPFor().each(
            new DrawIndexAction(x, speed), 0, steps) : context.getPFor().eachRange(
            new DrawRangeAction(x, speed), 0, steps);

    final ExecutionType executionType = (ExecutionType) executionCombo.getSelectedItem();
    if (progressBox.isSelected()) {
        action = action.withProgressCallback(this);
    }

    if (completeBox.isSelected()) {
        action = action.withCompletionCallback(this);
    }

    if (excBox.isSelected()) {
        action = action.withCancellationOnException();
    }

    cancelB.setEnabled(true);
    if (executionType == ExecutionType.SYNCHRONOUS) {
        stopwatch.start();
        try {
            action.execute();
        } catch (final Exception e) {
            log.warn("execute() failed", e);
        }
        onProgress(steps);
        reset();
    } else {
        future = action.executeAsynchronously(executionType == ExecutionType.FAST_CANCEL);
    }

}

private void loopRepaint() {
    new Timer().scheduleAtFixedRate(new TimerTask() {
        public void run() {
            frame.repaint();
        }
    }, 0, 200);

}

@Override
public void onComplete(Future<Void> future) {
    log.debug("onComplete");
    try {
        future.get();
    } catch (final Exception e) {
        log.warn("get() failed", e);
    } finally {
        reset();
        timeL.setText(stopwatch.getTimeDifference().toString());
    }
}

@Override
public void onProgress(int totalStepsCompleted) {
    progressBar.setValue(totalStepsCompleted);
    timeL.setText(stopwatch.getTimeDifference().toString());
}

private void reset() {
    cancelB.setEnabled(false);
    startB.setEnabled(true);
    rangeB.setEnabled(true);
    simpleB.setEnabled(true);
}

private void simpleFor(int rowCount, int colCount) throws DebugException {
    final int sum = rowCount * colCount;
    final int thread = (int) Thread.currentThread().getId() % colors.length;
    for (int j = 0; j < sum; j++) {
        work(j, rowCount, thread);
    }
    onProgress(sum);
    reset();
}

private void start(ForType forType) throws DebugException {
    disableStart();

    loop((Integer) threadsSpinnerModel.getValue(), (SpeedType) speedCombo.getSelectedItem(),
            forType);

    frame.repaint();
}

protected void throwException() {
    throwException.set(true);
}

private void work() throws DebugException {
    final Random r = new Random();
    if (throwException.getAndSet(false)) {
        exceptionB.getModel().setSelected(false);
        throw new DebugException();
    }

    int bar = 0;
    for (int j = 0; j < 1000; j++) {
        bar += r.nextInt();
    }
    foo += bar;
}

private void work(int i, int rowCount, int thread) throws DebugException {
    final int row = i / rowCount;
    final int col = i % rowCount;
    work();
    synchronized (graphics) {
        final Color color = colors[thread];
        graphics.setColor(color);
        graphics.drawRect(col, row, 1, 1);

    }
}

}


Related

Wiki: Home

MongoDB Logo MongoDB