diff -r 0bd10b7df2d2 -r 32f6aefec11e test/jdk/java/net/httpclient/http2/server/Queue.java --- a/test/jdk/java/net/httpclient/http2/server/Queue.java Wed Nov 22 10:15:53 2017 +0000 +++ b/test/jdk/java/net/httpclient/http2/server/Queue.java Wed Nov 22 11:21:36 2017 +0000 @@ -35,24 +35,24 @@ public class Queue implements ExceptionallyCloseable { private final LinkedList q = new LinkedList<>(); - private volatile boolean closed = false; - private volatile Throwable exception = null; + private boolean closed = false; + private boolean closing = false; + private Throwable exception = null; private Runnable callback; private boolean callbackDisabled = false; private int waiters; // true if someone waiting + private final T closeSentinel; + + Queue(T closeSentinel) { + this.closeSentinel = closeSentinel; + } public synchronized int size() { return q.size(); } -// public synchronized boolean tryPut(T obj) throws IOException { -// if (closed) return false; -// put(obj); -// return true; -// } - public synchronized void put(T obj) throws IOException { - if (closed) { + if (closed || closing) { throw new IOException("stream closed"); } @@ -73,30 +73,19 @@ } } -// public synchronized void disableCallback() { -// callbackDisabled = true; -// } - -// public synchronized void enableCallback() { -// callbackDisabled = false; -// while (q.size() > 0) { -// callback.run(); -// } -// } + // Other close() variants are immediate and abortive + // This allows whatever is on Q to be processed first. -// /** -// * callback is invoked any time put is called where -// * the Queue was empty. -// */ -// public synchronized void registerPutCallback(Runnable callback) { -// Objects.requireNonNull(callback); -// this.callback = callback; -// if (q.size() > 0) { -// // Note: calling callback while holding the lock is -// // dangerous and may lead to deadlocks. -// callback.run(); -// } -// } + public synchronized void orderlyClose() { + if (closing || closed) + return; + try { + put(closeSentinel); + } catch (IOException e) { + e.printStackTrace(); + } + closing = true; + } @Override public synchronized void close() { @@ -132,7 +121,12 @@ } waiters--; } - return q.removeFirst(); + T item = q.removeFirst(); + if (item.equals(closeSentinel)) { + closed = true; + assert q.isEmpty(); + } + return item; } catch (InterruptedException ex) { throw new IOException(ex); } @@ -146,26 +140,9 @@ if (q.isEmpty()) { return null; } - T res = q.removeFirst(); - return res; + return take(); } -// public synchronized T[] pollAll(T[] type) throws IOException { -// T[] ret = q.toArray(type); -// q.clear(); -// return ret; -// } - -// public synchronized void pushback(T v) { -// q.addFirst(v); -// } - -// public synchronized void pushbackAll(T[] v) { -// for (int i=v.length-1; i>=0; i--) { -// q.addFirst(v[i]); -// } -// } - private IOException newIOException(String msg) { if (exception == null) { return new IOException(msg); @@ -173,5 +150,4 @@ return new IOException(msg, exception); } } - }