Can I use a Pipe to make an InputSream or OutputStream nonblocking?
I can create a ReadableByteChannel or WritableByteChannel with Channels.newChannel() but neither is an InterruptibleChannel. So can I create a Pipe with Pipe.open(), put the sink and source into nonblocking mode, register them with a Selector, write bytes into the sink when they come in from the ReadableByteChannel and finally write the bytes back to the WritableByteChannel from the source as it is notified by the Selector?
Thanks in advance,
Originally posted by Michael Morris:
I can't seem to get this to compile. What packages, besides the obvious ones do I need to import?
That's because it isn't a valid class. I had a short comment at the top explaining that and giving a short burst of opinion, but somehow it must have disappeared when I edited the post. Strange.
Anyway, I said that InputStream and OutputStream aren't designed to support non-blocking IO. available() doesn't always work and unless it does you have to start a seperate thread that blocks on read(), thereby defeating the entire purpose of nonblocking IO. If available() does work, you could have a thread sort of like the Swing event thread that just copies bytes around all day long. It would look something like this (note that this code is incomplete):
* refer to code above *
[ February 23, 2003: Message edited by: David Weitzman ]
This is probably a UBB bug that seems to show up when you do a reply-with-quote followed by [code] tags. (I think.) At least in certain situations, the system manages to lose some text before the [code] tag. Very annoying. Personally I just avoid ever using reply-with-quote, and hand-edit text my UBB to include whatever previous text I want (which is usually much less than reply-with-quote gives you).
Re: using available() to guard against blocked reads:
I'm not sure what is meant by classes in which available() doesn't work correctly. I do know that if available() behaves according to its API and you use it to prevent blocked reads, you can't actually detect the end of a file. If a file has 50 bytes and they're all available, the first read will read 50 bytes (assuming buffer is large enough). The next time through the loop, available is 0, so read(buffer, 0, 0) will not even attempt to read anything, so it won't return -1. The program just loops forever, never trying to actually read a byte, and thus never seeing the -1. Very annoying. Is it possible this is why you say available() doesn't work? My impression is that it's the API which is broken; I don't know what they were thinking when they wrote it - but I guess they can't redefine available() (or read()) now.
I still need to spend more time with nio though - there may yet be some n alternative for Michael.
[ February 23, 2003: Message edited by: Jim Yingst ]
Right. The problem is that it requires a separate thread to write bytes into the sink. It's always been possible to deal with blocking I/O by creating a new thread to manage each stream - the big point of nonblocking I/O is that you can manage a large number of different I/O sources with a single thread (or small number of threads), which often improves scalability for servers. It may still be useful to convert a blocking stream to a nonblocking channel at the cost of one thread, if you're interfacing with other code that expects a nonblocking channel. Just don't expect any great improvements over what you could have achieved if the other code had used only traditional I/O instead.
[ April 15, 2003: Message edited by: Jim Yingst ]
NIO introduces non-blocking I/O, and non-blocking usage of stdin (System.in) is something that's often desirable to do. But it's important to remember that NIO operates on channels, not streams. The classic Java stream metaphor never included the notion of non-blocking - that's new with channels.
You can wrap a channel around a stream and then feed it through a pipe as a previous poster described, but you must dedicate a thread per stream to make it work properly. This is not a failing of NIO but rather a limitation of streams. You can't multiplex streams, you can only multiplex channels.
In a case like this you're multiplexing the channel the stream is feeding, not the stream itself. You must dedicate a thread to service each stream.
The most likely scenario is multiplexing a large number of socket connections, which should be instances of SocketChannel. Spinning off one thread to watch stdio is not too much of a penalty.
I have some sample code which encapsulates System.in as a selectable channel on the Java NIO site. Look at SystemInPipe.java and TestStdin.java
but you must dedicate a thread per stream to make it work properly. This is not a failing of NIO but rather a limitation of streams. You can't multiplex streams, you can only multiplex channels.
So, the fact that you can't multiplex streams is because streams block and NIO Channels decorate the streams with non-blocking features in addition to the ability to interrogate a stream whether its ready for read/write ?
[ April 15, 2003: Message edited by: Jim Yingst ]
This is not the sort of decoration done within the java.io package where, for example, a BufferedReader adds functionality to a Reader.
What we're talking about here is more of an adapter. A stream object is accessed by one side of the adapter which presents a channel API to its clients.
The non-blocking capability provided by the Pipe and its dedicated thread could be considered a decorator of the adapter. It takes a simple channel (the adapted stream) and decorates it with a pipeline to present a non-blocking channel to its clients.
The thread is there to transfer data from the simple, blocking channel to the sink end of the Pipe. This allows the source end of the Pipe to present a ready indication when new data arrives. This essentially simulates what happens in the low-level implementations of SocketChannels when the socket data arrives.
[ April 16, 2003: Message edited by: Ron Hitchens ]
Thanks for any help,