package co.gongzh.procbridge; import org.jetbrains.annotations.Nullable; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ExecutorService; import java.util.concurrent.Semaphore; /** * @author Gong Zhang */ class TimeGuard { private final long timeout; private final Runnable task; TimeGuard(long timeout, Runnable task) { this.timeout = timeout; this.task = task; } void execute() throws ProcBridgeException { execute(null); } void execute(@Nullable ExecutorService executorService) throws ProcBridgeException { final Semaphore semaphore = new Semaphore(0); final boolean[] overtime = { false }; final Exception[] exception = { null }; Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { overtime[0] = true; semaphore.release(); } }, timeout); Runnable runnable = () -> { try { task.run(); } catch (Exception ex) { exception[0] = ex; } finally { semaphore.release(); } }; if (executorService != null) { executorService.execute(runnable); } else { new Thread(runnable).start(); } try { semaphore.acquire(); if (overtime[0]) { throw ProcBridgeException.timeout(); } if (exception[0] != null) { Throwable ex = exception[0].getCause(); if (ex == null) { ex = exception[0]; } if (ex instanceof ProcBridgeException) { throw (ProcBridgeException) ex; } else { throw new ProcBridgeException(ex); } } } catch (InterruptedException e) { throw new ProcBridgeException(e); } finally { timer.cancel(); } } }