Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
An implementation of ScheduledExecutorService for LibGDX which executes tasks on the main game thread.
import com.badlogic.gdx.Gdx;
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;
import java.util.stream.Collectors;
/**
* 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(Runnable command, long delay, TimeUnit unit) {
return delegate.schedule(() -> runTask(command), delay, unit);
}
@Override
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
return delegate.schedule(() -> runCallable(callable), delay, unit);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
return delegate.scheduleAtFixedRate(() -> runTask(command), initialDelay, period, unit);
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
return delegate.scheduleWithFixedDelay(() -> 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(Callable<T> task) {
return delegate.submit(() -> runCallable(task));
}
@Override
public <T> Future<T> submit(Runnable task, T result) {
return delegate.submit(() -> runTask(task), result);
}
@Override
public Future<?> submit(Runnable task) {
return delegate.submit(() -> 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(Runnable command) {
delegate.execute(() -> runTask(command));
}
private void runTask(Runnable command) {
CountDownLatch lock = new CountDownLatch(1);
Gdx.app.postRunnable(() -> {
command.run();
lock.countDown();
});
try {
lock.await();
}
catch (InterruptedException e) {
// ignored
}
}
private <V> V runCallable(Callable<V> callable) throws Exception {
AtomicReference<V> result = new AtomicReference<>();
AtomicReference<Exception> exception = new AtomicReference<>();
CountDownLatch lock = new CountDownLatch(1);
Gdx.app.postRunnable(() -> {
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) {
return tasks.stream()
.map(task -> (Callable<T>) () -> runCallable(task))
.collect(Collectors.toList());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.