Skip to content

Instantly share code, notes, and snippets.

@mastern2k3
Created May 23, 2019 23:32
Show Gist options
  • Save mastern2k3/0c0e06625b926527a4e6c56258d49f68 to your computer and use it in GitHub Desktop.
Save mastern2k3/0c0e06625b926527a4e6c56258d49f68 to your computer and use it in GitHub Desktop.
package com.ragnaros.reactor.utils;
import com.badlogic.gdx.Gdx;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
/**
* A {@link ScheduledExecutorService} implementation that executes operations on the game loop
* thread using {@link com.badlogic.gdx.Application#postRunnable(Runnable)} via {@link Gdx#app}
* and a delegated scheduled executor service.
*/
public class GdxScheduledExecutorService implements ScheduledExecutorService {
private final ScheduledExecutorService delegate;
public GdxScheduledExecutorService(ScheduledExecutorService delegate) {
this.delegate = delegate;
}
/**
* Creates a new {@link GdxScheduledExecutorService} with a thread pool as the delegate.
* @param corePoolSize the number of threads to keep in the pool
* @return the new executor service
*/
public static GdxScheduledExecutorService create(int corePoolSize) {
return new GdxScheduledExecutorService(Executors.newScheduledThreadPool(corePoolSize));
}
@Override
public ScheduledFuture<?> schedule(final Runnable command, long delay, TimeUnit unit) {
return delegate.schedule(new Runnable() {
@Override
public void run() {
runTask(command);
}
}, delay, unit);
}
@Override
public <V> ScheduledFuture<V> schedule(final Callable<V> callable, long delay, TimeUnit unit) {
return delegate.schedule(new Callable<V>() {
@Override
public V call() throws Exception {
return runCallable(callable);
}
}, delay, unit);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(final Runnable command, long initialDelay, long period, TimeUnit unit) {
return delegate.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
runTask(command);
}
}, initialDelay, period, unit);
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(final Runnable command, long initialDelay, long delay, TimeUnit unit) {
return delegate.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
runTask(command);
}
}, initialDelay, delay, unit);
}
@Override
public void shutdown() {
delegate.shutdown();
}
@Override
public List<Runnable> shutdownNow() {
return delegate.shutdownNow();
}
@Override
public boolean isShutdown() {
return delegate.isShutdown();
}
@Override
public boolean isTerminated() {
return delegate.isTerminated();
}
@Override
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
return delegate.awaitTermination(timeout, unit);
}
@Override
public <T> Future<T> submit(final Callable<T> task) {
return delegate.submit(new Callable<T>() {
@Override
public T call() throws Exception {
return runCallable(task);
}
});
}
@Override
public <T> Future<T> submit(final Runnable task, T result) {
return delegate.submit(new Runnable() {
@Override
public void run() {
runTask(task);
}
}, result);
}
@Override
public Future<?> submit(final Runnable task) {
return delegate.submit(new Runnable() {
@Override
public void run() {
runTask(task);
}
});
}
@Override
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException {
return delegate.invokeAll(gdxTasks(tasks));
}
@Override
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout,
TimeUnit unit) throws InterruptedException {
return delegate.invokeAll(gdxTasks(tasks), timeout, unit);
}
@Override
public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException {
return delegate.invokeAny(gdxTasks(tasks));
}
@Override
public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return delegate.invokeAny(gdxTasks(tasks), timeout, unit);
}
@Override
public void execute(final Runnable command) {
delegate.execute(new Runnable() {
@Override
public void run() {
runTask(command);
}
});
}
private void runTask(final Runnable command) {
final CountDownLatch lock = new CountDownLatch(1);
Gdx.app.postRunnable(
new Runnable() {
@Override
public void run() {
command.run();
lock.countDown();
}
});
try {
lock.await();
}
catch (InterruptedException e) {
// ignored
}
}
private <V> V runCallable(final Callable<V> callable) throws Exception {
final AtomicReference<V> result = new AtomicReference<>();
final AtomicReference<Exception> exception = new AtomicReference<>();
final CountDownLatch lock = new CountDownLatch(1);
Gdx.app.postRunnable(
new Runnable() {
@Override
public void run() {
try {
result.set(callable.call());
}
catch (Exception e) {
exception.set(e);
}
lock.countDown();
}
});
lock.await();
if (exception.get() != null) {
throw exception.get();
}
return result.get();
}
private <T> List<? extends Callable<T>> gdxTasks(Collection<? extends Callable<T>> tasks) {
ArrayList<Callable<T>> wrapped = new ArrayList<Callable<T>>();
for (final Callable<T> task : tasks) {
wrapped.add(
new Callable<T>() {
@Override
public T call() throws Exception {
return runCallable(task);
}
});
}
return wrapped;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment