package org.jcon.test;

import org.jcon.util.DataLib;
import org.jcon.util.GenLib;

/**
 * Version2 - Reusable thread. - FAILS
 * java org.jcon.test.TestTimeout2
 *
 * @author Jack Harich
 */
public class TestTimeout2 implements Runnable {

//---------- Private Fields ------------------------------
private boolean   running;
private boolean   working;
private long      timeout = 3000;
private Thread    thread;

private int       performResult;
private String    performInputData;
private Exception performException;

private static final int FAILURE = -1;

//---------- Initialization ------------------------------
/**
* Runs the test, pausing for command input. Enter "quit"
* to end the test, nothing to use current timeout, or
* enter a new timeout in milliseconds. The initial
* timeout is 3000. The task sleeps for 5000 ms before
* completing. Thus the default is the task times out.
*/
public static void main(String args[]) {
    new TestTimeout2().start();    
}    
//---------- Public Methods ------------------------------
public void start() {
    // This should timeout if delayed, such as server down
    print(" ------ Starting test");
    String command = "";
    while(! command.equalsIgnoreCase("Quit")) {
        if (DataLib.isInt(command)) timeout = Integer.valueOf(command).intValue();
        
        int result = perform("TestData");
        print(" - Result = " + result + ", timeout = " + timeout);
        
        command = GenLib.readInputLine("Enter command: ");   
    }
    print(" ------ Test complete");
}
public synchronized int perform(String inputData) {
    // Init thread data
    performInputData = inputData;
    performException = null;
    
    // Start reusable thread to do the work
    if (! running) {
        running = true;
        thread = new Thread(this);
        thread.start();
    }      
    // Continue thread, wait for notify or timeout
    try {
        notify(); // Will start thread
        wait(timeout); // *** FAILS to continue if lock unavailable
        print(".perform() - After wait(timeout)");
    } catch(InterruptedException ex) {
        ex.printStackTrace(); // Should never happen           
        return FAILURE;
    }
    // Process result
    if (working) {
        // Timed out
        working = false; // "Double variable use" , BAD
        return FAILURE; // Or throw exception
    } else if (performException != null) {
        performException.printStackTrace();
        return FAILURE;
    } else {
        // Okay
        return performResult;        
    }
}    
//---------- Runnable Implementation ---------------------
public synchronized void run() {
while (running) {    
    try {
        wait();
        working = true;
        
        print(" - Starting task with: " + performInputData);
        // Simulate overly long task
        Thread.currentThread().sleep(5000);
        
        if (! working) {
            // Don't do anymore work
        } else {
            // Do more work
            performResult = 10;
        }
    } catch(Exception ex) {
        performException = ex;
    }
    working = false;
    notifyAll();    
}
} // End method
    
//---------- Private Methods -----------------------------
//--- Std
private static void print(String text) {
    System.out.println("TestTimeout2" + text);
}

} // End class
