/*
Copyright 2012 Jan Ove Saltvedt
This file is part of KBot.
KBot is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
KBot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with KBot. If not, see <http://www.gnu.org/licenses/>.
*/
package com.kbotpro.scriptsystem.runnable;
import com.kbotpro.scriptsystem.interfaces.Looped;
import com.kbotpro.scriptsystem.interfaces.WorkerContainer;
import com.kbotpro.ui.ErrorBox;
import com.kbotpro.various.StaticStorage;
import org.apache.log4j.Logger;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutionException;
import java.io.PrintStream;
import java.io.OutputStream;
import java.io.IOException;
/**
* Basic class to be used in scripting.
* Each worker creates a Thread that works independendently from all the other workers (if any)
*/
public class Worker {
/**
* Can be used to call back to the workerContainer.
* Used internally to manage the workers.
*/
protected WorkerContainer workerContainer;
protected Looped looped;
public boolean loopReturned = true;
/**
* May only be called by the Script, therefor it is package local
* @param workerContainer
* @param looped
*/
Worker(WorkerContainer workerContainer, Looped looped) {
this.workerContainer = workerContainer;
this.looped = looped;
}
Future future;
/**
* Package local as the Script needs it.
*/
Runnable runnable = new Runnable() {
public void run() {
int returnedValue = 0;
try{
while(workerContainer != null && looped != null && !workerContainer.isStopped() && (returnedValue) >= 0){
loopReturned = false;
returnedValue = looped.loop();
loopReturned = true;
if (returnedValue < 0) {
break;
}
while(!(workerContainer instanceof Random) && workerContainer.getBotEnv().scriptManager.isScriptsPaused()){
Thread.sleep(500);
}
if(returnedValue == 0){
continue;
}
try {
Thread.sleep(returnedValue);
} catch (InterruptedException ignored) {
}
}
}catch(Exception e){
final String[] message = new String[]{""};
PrintStream printStream = new PrintStream(new OutputStream() {
@Override
public void write(int b) throws IOException {
message[0] += (char)b;
}
});
e.printStackTrace(printStream);
Logger.getRootLogger().error("Exception: ", e);
new ErrorBox(StaticStorage.mainForm, "An error occurred in the script/random: "+ workerContainer.getName()+":\n\n"+ message[0]).setVisible(true);
}
workerContainer.notifyWorkerDone(Worker.this);
}
};
/**
* Checks if a worker has executed
* @return boolean true if the worker is currently alive.
*/
public boolean isAlive(){
return future != null && !future.isDone();
}
/**
* Attempts to cancel execution of this worker.
* @return false if the worker could not be cancelled, typically because it has already completed normally; true otherwise.
*/
public boolean cancel(){
if(future != null){
workerContainer.notifyWorkerDone(this);
}
return future == null || future.cancel(true);
}
/**
* Starts the worker if its not allready running
*/
public void start(){
workerContainer.startWorker(this);
}
/**
* Creates a copy of this worker using the same loop.
* @return
*/
public Worker copy(){
return workerContainer.createWorker(looped);
}
/**
* Waits until the worker is done executing.
*/
public void join(){
if(future == null){
return;
}
try {
future.get();
} catch (InterruptedException e) {
Logger.getRootLogger().error("Exception: ", e); //To change body of catch statement use File | Settings | File Templates.
} catch (ExecutionException e) {
Logger.getRootLogger().error("Exception: ", e); //To change body of catch statement use File | Settings | File Templates.
}
}
}