Skip to content

Instantly share code, notes, and snippets.

@battleguard
Created July 16, 2013 14:52
Show Gist options
  • Select an option

  • Save battleguard/6009445 to your computer and use it in GitHub Desktop.

Select an option

Save battleguard/6009445 to your computer and use it in GitHub Desktop.
package org.logicail.framework.script;
import org.logicail.framework.script.job.Container;
import org.logicail.framework.script.job.Job;
import org.logicail.framework.script.job.TaskContainer;
import org.powerbot.script.PollingScript;
/**
* Created with IntelliJ IDEA.
* User: Logicail
* Date: 23/06/13
* Time: 17:31
*/
public abstract class ActiveScript extends PollingScript {
private final Container container = new TaskContainer();
protected ActiveScript() {
getExecQueue(State.SUSPEND).add(new Runnable() {
@Override
public void run() {
setPaused(true);
}
});
getExecQueue(State.RESUME).add(new Runnable() {
@Override
public void run() {
setPaused(false);
}
});
getExecQueue(State.STOP).add(new Runnable() {
@Override
public void run() {
shutdown();
}
});
}
public final boolean isActive() {
return !container.isTerminated();
}
public final boolean isPaused() {
return container.isPaused();
}
public final void setPaused(boolean paramBoolean) {
container.setPaused(paramBoolean);
}
/**
* Graceful shutdown
*/
public final void shutdown() {
if (!isShutdown()) {
container.shutdown();
}
}
public final boolean isShutdown() {
return container.isShutdown();
}
/**
* Force stop
*/
public void forceStop() {
container.interrupt();
}
public final Container getContainer() {
return container;
}
public final void submit(Job job) {
container.submit(job);
}
}
package org.logicail.framework.script.job.state;
import org.powerbot.script.methods.MethodContext;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicReference;
/**
* Created with IntelliJ IDEA.
* User: Logicail
* Date: 16/07/13
* Time: 14:28
*/
public abstract class Branch extends Node {
private final Queue<Node> nodes = new ConcurrentLinkedQueue();
private final AtomicReference<Node> current_node = new AtomicReference();
public Branch(MethodContext ctx, Node[] nodes) {
super(ctx);
this.nodes.addAll(Arrays.asList(nodes));
}
public abstract boolean branch();
@Override
public final boolean activate() {
if (branch()) {
Iterator<Node> iterator = nodes.iterator();
while (iterator.hasNext()) {
Node node = iterator.next();
if (node != null && node.activate()) {
return true;
}
}
}
return false;
}
@Override
public void execute() {
Node current = current_node.get();
if (current != null && current.isAlive()) {
return;
}
Iterator<Node> iterator = nodes.iterator();
while (iterator.hasNext()) {
Node next = iterator.next();
if (next != null && next.activate()) {
current_node.set(next);
getContainer().submit(next);
next.join();
}
}
}
}
package org.logicail.framework.script.job;
/**
* Created with IntelliJ IDEA.
* User: Logicail
* Date: 23/06/13
* Time: 17:16
*/
public abstract interface Container {
public abstract void submit(Job job);
public abstract void setPaused(boolean paused);
public abstract boolean isPaused();
public abstract Job[] enumerate();
public abstract int getActiveCount();
public abstract Container branch();
public abstract Container[] getChildren();
public abstract void shutdown();
public abstract boolean isShutdown();
public abstract void interrupt();
public abstract boolean isTerminated();
public abstract void addListener(JobListener jobListener);
public abstract void removeListener(JobListener jobListener);
}
package org.logicail.framework.script.job.util;
import org.logicail.framework.script.job.Container;
import org.logicail.framework.script.job.Job;
import org.logicail.framework.script.job.JobListener;
/**
* Created with IntelliJ IDEA.
* User: Logicail
* Date: 30/06/13
* Time: 16:46
*/
public class Containers {
public static boolean awaitTermination(Container container) {
return awaitTermination(container, 0);
}
public static boolean awaitTermination(Container container, int timeout) {
if (container.isTerminated()) {
return true;
}
Object lock = new Object();
JobListener jobListener = new JobListener() {
public void jobStarted(Job paramAnonymousJob) {
}
public void jobStopped(Job paramAnonymousJob) {
synchronized (this) {
notify();
}
return;
}
};
container.addListener(jobListener);
long end = System.currentTimeMillis() + timeout;
while (((timeout == 0) || (System.currentTimeMillis() < end)) && (!container.isTerminated())) {
long timeLeft = end - System.currentTimeMillis();
if (timeLeft <= 0) {
break;
}
synchronized (lock) {
try {
lock.wait(timeLeft);
} catch (InterruptedException localInterruptedException) {
container.removeListener(jobListener);
throw new ThreadDeath();
}
}
}
container.removeListener(jobListener);
return container.isTerminated();
}
}
package org.logicail.framework.script.job;
import org.powerbot.script.methods.MethodContext;
import org.powerbot.script.methods.MethodProvider;
/**
* Created with IntelliJ IDEA.
* User: Logicail
* Date: 23/06/13
* Time: 17:15
*/
public abstract class Job extends MethodProvider {
public Job(MethodContext ctx) {
super(ctx);
}
public abstract void work();
public abstract boolean join();
public abstract boolean isAlive();
public abstract void interrupt();
public abstract boolean isInterrupted();
public abstract void setContainer(Container container);
public abstract Container getContainer();
}
package org.logicail.framework.script.job;
/**
* Created with IntelliJ IDEA.
* User: Logicail
* Date: 23/06/13
* Time: 17:17
*/
public abstract interface JobListener {
public abstract void jobStarted(Job job);
public abstract void jobStopped(Job job);
}
package org.logicail.framework.script.job;
import org.powerbot.script.methods.MethodContext;
/**
* Created with IntelliJ IDEA.
* User: Logicail
* Date: 23/06/13
* Time: 17:20
*/
public abstract class LoopTask extends Task {
private boolean paused;
public LoopTask(MethodContext ctx) {
super(ctx);
}
public final void execute() {
Container container = getContainer();
while (!container.isShutdown()) {
if (container.isPaused()) {
paused = true;
sleep(1000);
} else {
paused = false;
int delay;
try {
delay = loop();
} catch (Throwable throwable) {
throwable.printStackTrace();
delay = -1;
}
if (delay >= 0) {
sleep(delay);
} else if (delay == -1) {
break;
}
}
}
}
public abstract int loop();
public boolean isPaused() {
return paused;
}
}
package org.logicail.framework.script.job.state;
import org.logicail.framework.script.job.Task;
import org.powerbot.script.methods.MethodContext;
/**
* Created with IntelliJ IDEA.
* User: Logicail
* Date: 23/06/13
* Time: 17:31
*/
public abstract class Node extends Task {
public Node(MethodContext ctx) {
super(ctx);
}
public abstract boolean activate();
}
package org.logicail.framework.script.job;
import org.powerbot.script.methods.MethodContext;
import java.util.concurrent.Future;
import java.util.logging.Logger;
/**
* Created with IntelliJ IDEA.
* User: Logicail
* Date: 23/06/13
* Time: 17:17
*/
public abstract class Task extends Job {
private final Object init_lock = new Object();
protected Logger log = Logger.getLogger(getClass().getName());
Future<?> future;
private Thread thread;
private Container container = null;
private volatile boolean alive = false;
private volatile boolean interrupted = false;
protected Task(MethodContext ctx) {
super(ctx);
}
public final void work() {
synchronized (init_lock) {
if (alive) {
throw new RuntimeException("Task RuntimeException");
}
alive = true;
}
interrupted = false;
thread = Thread.currentThread();
try {
execute();
} catch (ThreadDeath ignored) {
} catch (Throwable throwable) {
throwable.printStackTrace();
}
alive = false;
}
public abstract void execute();
public final boolean join() {
if (future == null || future.isDone()) {
return true;
}
try {
future.get();
} catch (Throwable ignored) {
}
return future.isDone();
}
public final boolean isAlive() {
return alive;
}
public final void interrupt() {
interrupted = true;
if (thread != null) {
try {
if (!thread.isInterrupted()) {
thread.interrupt();
}
} catch (Throwable ignored) {
}
}
}
public final boolean isInterrupted() {
return interrupted;
}
public Container getContainer() {
return container;
}
public void setContainer(Container container) {
this.container = container;
}
}
package org.logicail.framework.script.job;
import java.util.Deque;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Created with IntelliJ IDEA.
* User: Logicail
* Date: 23/06/13
* Time: 17:21
*/
public class TaskContainer implements Container {
private final CopyOnWriteArrayList<JobListener> listeners = new CopyOnWriteArrayList<>();
private final List<Container> children = new CopyOnWriteArrayList<>();
private Container[] childrenCache = new Container[0];
private final ThreadGroup group;
private final ExecutorService executor;
private final Deque<Job> jobs = new ConcurrentLinkedDeque<>();
private volatile boolean paused = false;
private volatile boolean shutdown = false;
private volatile boolean interrupted = false;
private final TaskContainer parent_container;
public TaskContainer() {
this(Thread.currentThread().getThreadGroup());
}
public TaskContainer(ThreadGroup threadGroup) {
this(threadGroup, null);
}
private TaskContainer(ThreadGroup group, TaskContainer container) {
this.group = new ThreadGroup(group, getClass().getName() + "_" + Integer.toHexString(hashCode()));
this.executor = Executors.newCachedThreadPool(new ThreadPool(this.group));
this.parent_container = container;
}
public final void submit(Job job) {
if (isShutdown()) {
return;
}
job.setContainer(this);
Future localFuture = executor.submit(createWorker(job));
if (job instanceof Task) {
((Task) job).future = localFuture;
}
}
public final void setPaused(boolean paused) {
if (isShutdown()) {
return;
}
if (this.paused != paused) {
this.paused = paused;
}
for (Container localContainer : getChildren()) {
localContainer.setPaused(paused);
}
}
public final boolean isPaused() {
return paused;
}
public Job[] enumerate() {
return jobs.toArray(new Job[jobs.size()]);
}
public final int getActiveCount() {
return jobs.size();
}
public final Container branch() {
TaskContainer taskContainer = new TaskContainer(group, this);
children.add(taskContainer);
return taskContainer;
}
public final Container[] getChildren() {
int size = children.size();
if (size > 0) {
if (size == childrenCache.length) {
return childrenCache;
}
return childrenCache = children.toArray(new Container[size]);
}
return new Container[0];
}
public final void shutdown() {
if (!isShutdown()) {
shutdown = true;
}
for (Container localContainer : getChildren()) {
localContainer.shutdown();
}
}
public final boolean isShutdown() {
return shutdown;
}
public final void interrupt() {
shutdown();
interrupted = true;
for (Container container : getChildren()) {
container.interrupt();
}
for (Job job : jobs) {
job.interrupt();
}
}
public final boolean isTerminated() {
return ((shutdown) || (interrupted)) && (getActiveCount() == 0);
}
public final void addListener(JobListener listener) {
listeners.addIfAbsent(listener);
}
public final void removeListener(JobListener listener) {
listeners.remove(listener);
}
private Runnable createWorker(final Job job) {
return new Runnable() {
public void run() {
jobs.add(job);
notifyListeners(job, true);
try {
job.work();
} catch (Exception ignored) {
} catch (Throwable throwable) {
throwable.printStackTrace();
}
jobs.remove(job);
notifyListeners(job, false);
job.setContainer(null);
}
};
}
private void notifyListeners(Job job, boolean started) {
JobListener[] jobListeners = listeners.toArray(new JobListener[listeners.size()]);
for (JobListener jobListener : jobListeners) {
try {
if (started) {
jobListener.jobStarted(job);
} else {
jobListener.jobStopped(job);
}
} catch (Throwable ignored) {
}
}
if (parent_container != null) {
parent_container.notifyListeners(job, started);
}
}
private final class ThreadPool implements ThreadFactory {
private final ThreadGroup group;
private final AtomicInteger worker = new AtomicInteger(1);
private ThreadPool(ThreadGroup group) {
this.group = group;
}
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(group, runnable, group.getName() + "_" + worker.getAndIncrement());
if (!thread.isDaemon()) {
thread.setDaemon(false);
}
if (thread.getPriority() != 5) {
thread.setPriority(5);
}
return thread;
}
}
}
package org.logicail.framework.script.job.state;
import java.util.Arrays;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicReference;
/**
* Created with IntelliJ IDEA.
* User: Logicail
* Date: 23/06/13
* Time: 17:38
*/
public class Tree {
private final Queue<Node> nodes = new ConcurrentLinkedQueue<>();
private final AtomicReference<Node> current_node = new AtomicReference<>();
public Tree(Node[] nodes) {
this.nodes.addAll(Arrays.asList(nodes));
}
public final synchronized Node state() {
Node current = current_node.get();
if (current != null) {
if (current.isAlive()) {
return null;
}
if (current.activate()) {
/*** Don't loop previous is still valid ***/
return current;
}
}
for (Node next : nodes) {
if (next != null && next.activate()) {
return next;
}
}
return null;
}
public final void set(Node node) {
current_node.set(node);
}
public final Node get() {
return current_node.get();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment