--- /dev/null 2016-04-22 22:42:07.067228853 +0100 +++ new/src/java.httpclient/share/classes/java/net/http/SequentialExecutor.java 2016-04-25 23:11:04.565374190 +0100 @@ -0,0 +1,39 @@ +package java.net.http; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Executor; +import java.util.concurrent.RejectedExecutionException; + +import static java.util.Objects.requireNonNull; + +// +// Executor that runs one task at a time, though possibly by different threads. +// Tasks are executed in a happen-before order (synced through the queue). +// +final class SequentialExecutor implements Executor { + + private final BlockingQueue tasks; + private final SignalHandler handler; + + SequentialExecutor(Executor executor, BlockingQueue tasks) { + this.tasks = requireNonNull(tasks); + this.handler = new SignalHandler(requireNonNull(executor), this::pollAndExecute); + } + + @Override + public void execute(Runnable command) { + requireNonNull(command); + if (!tasks.offer(command)) { + throw new RejectedExecutionException(); + } else { + handler.signal(); + } + } + + private void pollAndExecute() { + Runnable t; + while ((t = tasks.poll()) != null) { + t.run(); + } + } +}