package xapi.jre.process;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.ReentrantLock;
import xapi.annotation.inject.SingletonDefault;
import xapi.except.NotYetImplemented;
import xapi.inject.impl.LazyPojo;
import xapi.inject.impl.SingletonProvider;
import xapi.log.X_Log;
import xapi.platform.JrePlatform;
import xapi.process.api.AsyncCondition;
import xapi.process.api.AsyncLock;
import xapi.process.api.ConcurrentEnvironment;
import xapi.process.impl.ConcurrencyServiceAbstract;
import xapi.process.service.ConcurrencyService;
import xapi.util.X_Namespace;
import xapi.util.api.ErrorHandler;
import xapi.util.api.RemovalHandler;
import xapi.util.api.SuccessHandler;
@JrePlatform
@SingletonDefault(implFor=ConcurrencyService.class)
public class ConcurrencyServiceJre extends ConcurrencyServiceAbstract{
public ConcurrencyServiceJre() {
}
private static class LazyQueue<T> extends LazyPojo<ConcurrentLinkedQueue<T>> {
@Override
protected ConcurrentLinkedQueue<T> initialValue() {
return new ConcurrentLinkedQueue<T>();
}
}
protected class JreConcurrentEnvironment extends ConcurrentEnvironment {
private final LazyQueue<Runnable> defers = new LazyQueue<Runnable>();
private final LazyQueue<Runnable> finalies = new LazyQueue<Runnable>();
private final LazyQueue<Runnable> eventualies = new LazyQueue<Runnable>();
private final LazyQueue<Thread> threads = new LazyQueue<Thread>();
@Override
public Iterable<Runnable> getDeferred() {
return defers.get();
}
@Override
public Iterable<Thread> getThreads() {
return threads.get();
}
@Override
public Iterable<Runnable> getFinally() {
return finalies.get();
}
@Override
public void pushDeferred(Runnable cmd) {
defers.get().add(cmd);
}
@Override
public void pushEventually(Runnable cmd) {
eventualies.get().add(cmd);
}
@Override
public void pushFinally(Runnable cmd) {
finalies.get().add(cmd);
}
@Override
public void pushThread(Thread cmd) {
threads.get().add(cmd);
}
@Override
public boolean isEmpty() {
if (defers.isSet()) {
if (!defers.get().isEmpty())
return false;
}
if (finalies.isSet()) {
return finalies.get().isEmpty();
}
return true;
}
}
private final SingletonProvider<Integer> maxThreads = new SingletonProvider<Integer>() {
@Override
protected Integer initialValue() {
return Integer.parseInt(System.getProperty(X_Namespace.PROPERTY_MULTITHREADED, "5"));
}
};
@Override
public ConcurrentEnvironment initializeEnvironment(
Thread key, UncaughtExceptionHandler params) {
ConcurrentEnvironment enviro = new JreConcurrentEnvironment();
return enviro;
};
protected int maxThreads() {
return maxThreads.get();
}
@Override
public boolean isMultiThreaded() {
return maxThreads() > 1;
}
@Override
public void runTimeout(Runnable cmd, int millisToWait) {
}
@Override
public AsyncLock newLock() {
return new LockWrapper();
}
}
class LockWrapper implements AsyncLock {
private final ReentrantLock lock = new ReentrantLock();
@Override
public AsyncCondition newCondition() {
throw new NotYetImplemented("AsyncCondition not yet implemented");
}
@Override
public boolean tryLock() {
return lock.tryLock();
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public RemovalHandler lock(SuccessHandler<AsyncLock> onLocked) {
// TODO actually push the callback onto a deferred stack,
// and return without blocking.
try {
lock.lock();
onLocked.onSuccess(this);
} catch (Throwable e){
if (onLocked instanceof ErrorHandler) {
try {
((ErrorHandler)onLocked).onError(e);
} catch (Throwable ignored) {}
} else {
X_Log.warn("Error occured while performing lock callback on "+onLocked,
onLocked);
}
}
return RemovalHandler.DoNothing;
}
@Override
public void unlock() {
lock.unlock();
}
}