/*
This is a cute little program which shows off the different things that the
ODB can do. It throws and catches a couple of exceptions, run a quicksort
program (buggy!), and starts up a couple of threads which promptly
(or not-so-promptly) deadlock. Finally, it throws an exception which is
only caught by the ODB itself.
*/
package com.lambda.Debugger;
import java.util.Hashtable;
import java.util.Random;
import java.util.Vector;
public class Demo {
public static Demo demo;
public static int MAX = 20;
public static Vector v;
public int[] array;
public Demo quick;
public char c = 'X';
public byte b = 61;
public static void badMethod() {
worseMethod();
}
public static void worseMethod() {
worstMethod();
}
public static void worstMethod() {
throw new NullPointerException("Bad method! Bad, bad, bad!");
}
public static void main(String[] argv) {
if (argv.length > 0) MAX = Integer.parseInt(argv[0]);
System.out.println("----------------------ODB Demo Program----------------------");
v = new Vector();
try { badMethod(); }
catch (NullPointerException e) {
System.out.println("A badMethod threw: "+e);
}
System.out.println("Starting QuickSort: " + MAX);
final Demo q = new Demo();
demo = q;
q.quick = new Demo();
q.array = new int[MAX];
q.array[0] = 1;
for (int i=1; i < MAX; i++) q.array[i] = ((i-1)*1233)%1974;
Thread t = new Thread(new DemoRunnable(q, 0, MAX-1), "Sorter");
t.start();
try {t.join();} catch (InterruptedException ie) {} // Impossible
System.out.println("Done sorting");
q.printAll(q);
Hashtable h = new Hashtable();
for (int i = 0; i < 5; i++) {
v.add(i+ " bottles of beer on the wall");
h.put(i+"th", i+" beers");
System.out.println("at " + i + " -> " + v.elementAt(i));
System.out.println("at " + i + " -> " + h.get(i+"th"));
}
for (int i = 4; i > 1; i--) {
v.removeElementAt(i);
h.put(i+"th", "NO MORE BEER!");
}
for (int i = 0; i < 4; i++) {
v.add(new DemoThing(i));
}
DemoWait.doWait();
DemoDeadLock.deadHead();
Vector v2 = manipulate(v);
print(v2);
// Demonstrate how exceptions are caught OUTSIDE of main()
throw new NullPointerException("Random exception for Debugger.runTarget to catch.");
}
public static Vector manipulate(Vector v) {
Vector v2 = new Vector();
for (int i = 0; i < v.size(); i++) {
Object thing = v.elementAt(i);
if (thing instanceof DemoThing) {
DemoThing dt = (DemoThing) thing;
String s = dt.name;
v2.add(s);
}
}
return v2;
}
public static void print(Vector v) {
try {
for (int i = 0; i < v.size(); i++) {
String s = (String) v.elementAt(i);
if (s.equals("Albert")) continue; // Don't show Albert!
System.out.println(s);
}
}
catch (NullPointerException e) {
System.out.println("Demo.print() caught "+ e);
}
}
public void printAll(Demo q) {
int top = MAX;
if (MAX > 100) top=100;
for (int i=0; i < top; i++) {
System.out.println(i + "\t "+ array[i]);
}
}
public void sort(int start, int end) {
int i, j, tmp, middle, newEnd;
if ((end - start) < 1) return;
if ((end - start) == 1) {
if (array[end] < array[start]) {
tmp = array[start];
array[start] = array[end];
array[end] = tmp;
return;
}
return;
}
middle = average(start, end);
newEnd = end;
L: for (i = start; i < newEnd; i++) {
if (array[i] > middle) {
for (j = newEnd; j > i; j--) {
if (array[j] < middle) {
tmp = array[i];
array[i] = array[j];
array[j] = tmp;
newEnd = j;
continue L;
}
}
newEnd = j;
}
}
if (start == newEnd) return;
Thread t = null;
if (((newEnd - start) > 2) || ((end - newEnd) > 2)) {
t = new Thread(new DemoRunnable(this, start, newEnd-1), "Sorter");
t.start();
}
else
sort(start, newEnd-1);
sort(newEnd, end);
if (t != null) {
try {t.join();} catch (InterruptedException ie) {} // Impossible
}
return;
}
public int average(int start, int end) {
int sum = 0;
for (int i = start; i < end; i++) {
sum += array[i];
}
return (sum/(end-start));
}
}
class DemoWait implements Runnable {
static void doWait() {
new Thread(new DemoWait(), "Waiter").start();
new Thread(new DemoWait(), "Waiter").start();
try {Thread.sleep(1000);}
catch (InterruptedException ie) {System.out.println("InterruptedException thrown?!"); System.exit(0);}
synchronized (DemoWait.class) {DemoWait.class.notifyAll();}
}
public void run() {
System.out.println("Getting lock for DemoWait " + Thread.currentThread().getName());
synchronized (DemoWait.class) {
System.out.println("Got lock for DemoWait " + Thread.currentThread().getName());
try {
System.out.println("Waiting in DemoWait " + Thread.currentThread().getName());
DemoWait.class.wait();
System.out.println("Waited in DemoWait " + Thread.currentThread().getName());
}
catch (InterruptedException ie) {System.out.println("InterruptedException thrown?!"); System.exit(0);}
}
System.out.println("Released lock for DemoWait " + Thread.currentThread().getName());
}
}
class DemoRunnable implements Runnable {
int start, end;
Demo q;
public DemoRunnable(Demo q, int start, int end) {
this.start = start;
this.end = end;
this.q = q;
}
public void run() {
q.sort(start, end);
}
}
class DemoDeadLock implements Runnable {
protected static boolean DEBUG = true;
private static int MAX = 2;
private static int nDemoThings = MAX, nCompleted = 0, nThreads = MAX, nSwaps = 50;
private static DemoThing[] things;
private static Thread[] threads;
public int count;
public DemoDeadLock(int i) {
count = i;
}
public static void deadHead() {
things = new DemoThing[MAX];
threads = new Thread[MAX];
for (int i = 0; i<nDemoThings; i++) {things[i] = new DemoThing(i);}
DemoThing dt = (DemoThing) Demo.v.elementAt(4);
dt.name = null;
for (int i = 0; i<nThreads; i++) {
DemoDeadLock dead = new DemoDeadLock(i);
threads[i] = new Thread(dead, "Hanger");
threads[i].start();
}
try {Thread.sleep(2000);}
catch (InterruptedException ie) {System.out.println("InterruptedException thrown?!"); System.exit(0);}
}
public void run() {
Random ran = new Random();
int r1, r2;
try {
for (int i = 0; i<nSwaps; i++) {
r1 = Math.abs(ran.nextInt() % nDemoThings);
r2 = Math.abs(ran.nextInt() % nDemoThings);
DemoThing thing1 = things[count];
DemoThing thing2 = things[(count+1)%MAX];
thing1.swap(thing2);
}
}
catch (InterruptedException ie) {System.out.println("InterruptedException thrown?!"); System.exit(0);}
}
}
class DemoThing {
static String[] names = {"Albert", "Joshua", "Vladimir", "Ivan"};
int value;
Random ran;
String name;
public DemoThing(int i) {
value = i;
ran = new Random(i);
if (i < names.length) name = names[i];
}
public String toString() {
return("<DemoThing " +name +">");
}
public void swap(DemoThing t) throws InterruptedException {
String name = Thread.currentThread().getName();
if (DemoDeadLock.DEBUG) {System.out.println(name +"\t " + this + ".swap(" + t + ")");}
synchronized (this) {
Thread.sleep(Math.abs(ran.nextInt() % 200));
synchronized (t) {
int tmp1 = t.value();
t.setValue(value);
value = tmp1;
}
}
if (DemoDeadLock.DEBUG) {System.out.println(name + "\t " + this + ".swapped(" + t + ")");}
}
public synchronized int value() throws InterruptedException {
return value;
}
public synchronized void setValue(int v) throws InterruptedException {
value = v;
}
}