Created
May 23, 2019 23:32
-
-
Save mastern2k3/0c0e06625b926527a4e6c56258d49f68 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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