Correct use of ReadableByteChannel

H

Harald Kirsch

For a piece of code intented to be rather
generic, I thought it would be a good idea
that it reads its input from a
ReadableByteChannel. The main reason to
choose it over an InputStream was that the
channel can be obtained for an InputStream as
well as for a RandomAccessFile.

Now the question:

How do you correctly perform a blocking read
from a ReadableByteChannel given that it does
not necessarily block?

I came up with

ReadableByteChannel source;
ByteBuffer inBuf;
...
int result;
while( 0==(result=source.read(inBuf)) ) Thread.yield();

In case the channel is blocking, the yield()
will never be called. If the channel is
non-blocking, the yield() may be called. But
on a machine without much load, I am afraid
it will generate load because no other thread
is interested in the processor.

Any ideas how this can be done better?

Harald.
 
I

iksrazal

How do you correctly perform a blocking read
from a ReadableByteChannel given that it does
not necessarily block?

I came up with

ReadableByteChannel source;
ByteBuffer inBuf;
...
int result;
while( 0==(result=source.read(inBuf)) ) Thread.yield();

In case the channel is blocking, the yield()
will never be called. If the channel is
non-blocking, the yield() may be called. But
on a machine without much load, I am afraid
it will generate load because no other thread
is interested in the processor.

Any ideas how this can be done better?

Harald.

I don't claim to have a lot of answers here, but I've been looking at
this problem a lot recently. One of the options I'm exploring is using
the emberio nio framework licensed under bsd. The code below does say
its mostly helpful for non-blocking but seemingly that is because it
keeps a read state for retrieval. So may be able to adapt this.
Furthermore, a channel by default is blocking or can be made to ber
blocking by giving a timeout. In any event, this is from emberio:

/**
* Reads data from the underlying channel into the internal
ByteBufer here.
* This attempts to fill up to the limit - and
* returns true if it actually does go up to the limit. Returns
false if it can't
* read all the way up to limit characters. Either way, the read
status is held here
* internally so you can also query it later. This complete/not
complete information
* is most useful for non-blocking readers.
*/
public boolean
read () throws IOException
{
int numBytes = -1;

// Think this little loop is odd? Well it is. The reason for it
// is because TCP stacks have a tendency to activate with only 1
byte
// available, and a subsequent read immediately gets the rest of
the data.
// Very annoying, and this leads to us in the common sense
scenario with
// non-blocking to have to inject multiple READ events for no good
reason.
// This little loop tries the read again if it didn't complete the
first
// time around, and provides a noticable perf boost.
//
// The above of course applies for non-blocking I/O where we
attempt a bit
// more I/O than the socket would indicate. For blocking I/O we
sit around
// snarfing it all.
for (int i = 0; ; i++)
{
if (endpoint.directWritesEnabled())
{
numBytes = channel.read (inBuffer);
}
else
{
synchronized (channel)
{
numBytes = channel.read (inBuffer);
}
}
if (numBytes < 0)
{
endpoint.close (EIOReasonCode.DISCONNECTION);
return (false);
}
else if (!inBuffer.hasRemaining())
{
return (true);
}
if (!endpoint.isBlocking() && i >= 2)
{
break;
}
}
return (!inBuffer.hasRemaining());
}

Lastly, the o'reilly nio book has an example of using
ReadableByteChannel with worker threads.

If you come up with something you think works, could you post it?

HTH

Outsource to an American programmer living in brazil!
http://www.braziloutsource.com/
iksrazal
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top