On Fri Oct 09 16:51:39 2015, tokuhirom wrote: > When I'm implementing a http client, I need to read 1 packet data > without expecting size. In socket programming context, this case is > generic requirement. > This is what recv does.
> In rakudo's src/core/IO/Socket.pm. It calls nqp::readfh. > > method recv (Cool $chars = Inf, :$bin? = False) { > fail('Socket not available') unless $!PIO; > if $bin { > nqp::readfh($!PIO, nqp::decont(buf8.new), > $chars == Inf ?? 1048576 !! $chars.Int); > } > else { > nqp::p6box_s(nqp::readcharsfh($!PIO, > $chars == Inf ?? 1048576 !! $chars.Int)); > } > } > Correct so far. Note that unlike the implementation of read, there is no loop here. > It's mapped to read_fhb on MoarVM. > > QAST::MASTOperations.add_core_moarop_mapping('readfh', 'read_fhb', 1); > > see src/vm/moar/QAST/QASTOperationsMAST.nqp. > > And then, it calls > MVM_io_syncstream_read_bytes(scrc/io/syncstream.c). If there's no > enough bytes in the buffer, MoarVM calls read_to_buffer, that calls > uv_read_start -> uv_read_stop async. Main thread goes to > MVM_string_decodestream_bytes_to_buf(src/strings/decode_stream.c). The code in question is this: /* See if we've already enough; if not, try and grab more. */ if (!MVM_string_decodestream_have_bytes(tc, data->ds, bytes)) read_to_buffer(tc, data, bytes > CHUNK_SIZE ? bytes : CHUNK_SIZE); /* Read as many as we can, up to the limit. */ return MVM_string_decodestream_bytes_to_buf(tc, data->ds, buf, bytes); Note that there is no loop here. At most we issue one read_to_buffer, which does not contain a loop either. We wait until libuv gives us data exactly once. > It will do a busy loop to read bytes to buffering the requested bytes. Structurally, a decode stream of itself cannot cause another I/O request to be made. It doesn't hold any I/O handles, just a linked list of byte buffers it can decode if it needs to. The loop inside of the decode stream you refer to looks like this: while (taken < bytes && ds->bytes_head) { The first part of the condition is about not handing back data beyond the limit. The second is making sure we terminate the loop when we've consumed all of the byte buffers already in the decode stream. Further, we can see the only calls in this function are to memcpy and MVM_free, so it certainly can't be causing more I/O. In summary, I think recv is already doing what you want. To be sure, I wrote tests in S32-io/socket-recv-vs-read.t to make sure recv does not block, which also pass. Thanks, /jnthn