/* $Id$ */ package ibis.ipl.impl.nio; import ibis.ipl.ConnectionClosedException; import ibis.ipl.MessageUpcall; import ibis.ipl.PortType; import ibis.ipl.ReceivePortConnectUpcall; import ibis.ipl.ReceiveTimedOutException; import ibis.ipl.impl.Ibis; import ibis.ipl.impl.SendPortIdentifier; import ibis.util.Queue; import java.io.IOException; import java.nio.channels.Channel; import java.nio.channels.ReadableByteChannel; import java.util.Properties; final class ThreadNioReceivePort extends NioReceivePort { private ThreadNioDissipator current = null; private Queue readyDissipators; private boolean closing = false; ThreadNioReceivePort(Ibis ibis, PortType type, String name, MessageUpcall upcall, ReceivePortConnectUpcall connUpcall, Properties props) throws IOException { super(ibis, type, name, upcall, connUpcall, props); readyDissipators = new Queue(); } synchronized void newConnection(SendPortIdentifier spi, Channel channel) throws IOException { if (!(channel instanceof ReadableByteChannel)) { throw new IOException("wrong channel type on creating connection"); } addConnection(spi, new ThreadNioDissipator( ((NioIbis) ibis).sendReceiveThread(), (ReadableByteChannel) channel)); } synchronized void errorOnRead(NioDissipator dissipator, Exception cause) { dissipator.info.close(cause); } NioDissipator getReadyDissipator(long deadline) throws IOException { ThreadNioDissipator dissipator; synchronized (this) { if (current != null) { if (current.dataLeft()) { readyDissipators.enqueue(current); } current = null; } } // FIXME: if a connection doesn't close gracefully, we won't notice while (true) { synchronized (this) { if (closing) { if (connections.size() == 0) { throw new ConnectionClosedException(); } } } dissipator = (ThreadNioDissipator) readyDissipators.dequeue(deadline); if (dissipator == null) { synchronized (this) { if (closing) { if (connections.size() == 0) { throw new ConnectionClosedException(); } } } throw new ReceiveTimedOutException("deadline passed while" + " selecting dissipator"); } try { if (dissipator.messageWaiting()) { synchronized (this) { current = dissipator; return dissipator; } } } catch (IOException e) { if (dissipator != null) { errorOnRead(dissipator, e); } } } } void addToReadyList(ThreadNioDissipator dissipator) { readyDissipators.enqueue(dissipator); } synchronized void closing() { closing = true; } }