[asio] multiple simultaneous async_read calls
Hello, all, If i write some code like this: boost::asio::async_read(socket_, bosot::asio::buffer(buffer1_.data(), len1, handler1); boost::asio::async_read(socket_, boost::asio::buffer(buffer2_.data(), len2, handler2); Will asio guarantee len1 bytes received by the first async_read, then schedule async_read2? or the result is undefined(like several bytes filled into buffer1, then next several bytes into buffer, then next several bytes into buffer1)? if the result is undefined, why asio don't add a check here? Thanks all in advance!
On 08/07/2014 09:54 PM, bbxiong wrote:
Hello, all,
If i write some code like this: boost::asio::async_read(socket_, bosot::asio::buffer(buffer1_.data(), len1, handler1); boost::asio::async_read(socket_, boost::asio::buffer(buffer2_.data(), len2, handler2);
Will asio guarantee len1 bytes received by the first async_read, then schedule async_read2?
or the result is undefined(like several bytes filled into buffer1, then next several bytes into buffer, then next several bytes into buffer1)?
I don't believe you're guaranteed that you will get `len1` bytes from the first read; it could be shorter. If you want to ensure that you get exactly that size in the first read, you should use the `transfer_exactly` completion condition: http://www.boost.org/doc/libs/1_56_0/doc/html/boost_asio/reference/transfer_... Jason
Hello, jason,
from asio doc:
async_read will invoke handler one condition is true:
1. the supplied buffers are full.
2. an error occurred.
so if there is no socket error, async_read will return len1 bytes.
My question is, can we make simultaneous async_read calls on one socket,
will they interfere each other?
Thanks!
2014-08-08 10:17 GMT+08:00 Jason Roehm
On 08/07/2014 09:54 PM, bbxiong wrote:
Hello, all,
If i write some code like this: boost::asio::async_read(socket_, bosot::asio::buffer(buffer1_.data(), len1, handler1); boost::asio::async_read(socket_, boost::asio::buffer(buffer2_.data(), len2, handler2);
Will asio guarantee len1 bytes received by the first async_read, then schedule async_read2?
or the result is undefined(like several bytes filled into buffer1, then next several bytes into buffer, then next several bytes into buffer1)?
I don't believe you're guaranteed that you will get `len1` bytes from the first read; it could be shorter. If you want to ensure that you get exactly that size in the first read, you should use the `transfer_exactly` completion condition:
http://www.boost.org/doc/libs/1_56_0/doc/html/boost_asio/ reference/transfer_exactly.html
Jason
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
The latest documentation adds this:
This operation is implemented in terms of zero or more calls to the
stream's async_read_some function, and is known as a *composed operation*.
The program must ensure that the stream performs no other read operations
(such as async_read, the stream's async_read_some function, or any other
composed operations that perform reads) until this operation completes.
So a call to async_read cannot be done until the prior one has finished.
This implementation is necessary on some platforms (Linux comes to mind)
because the epoll mechanism merely signals when more data is available for
reading. The async_read function wraps your callback in another callback
that continually polls for data until the requested amount has been read,
then invokes your callback when the read amount has been reached. So
unfortunately, the system call doesn't take the user buffer and notify when
its been filled. That seems ideal, but maybe someone like Nial could
explain the difficulties of such an implementation at the OS level.
Lee
On Thu, Aug 7, 2014 at 10:31 PM, bbxiong
Hello, jason, from asio doc: async_read will invoke handler one condition is true: 1. the supplied buffers are full. 2. an error occurred.
so if there is no socket error, async_read will return len1 bytes.
My question is, can we make simultaneous async_read calls on one socket, will they interfere each other?
Thanks!
2014-08-08 10:17 GMT+08:00 Jason Roehm
: On 08/07/2014 09:54 PM, bbxiong wrote:
Hello, all,
If i write some code like this: boost::asio::async_read(socket_, bosot::asio::buffer(buffer1_.data(), len1, handler1); boost::asio::async_read(socket_, boost::asio::buffer(buffer2_.data(), len2, handler2);
Will asio guarantee len1 bytes received by the first async_read, then schedule async_read2?
or the result is undefined(like several bytes filled into buffer1, then next several bytes into buffer, then next several bytes into buffer1)?
I don't believe you're guaranteed that you will get `len1` bytes from the first read; it could be shorter. If you want to ensure that you get exactly that size in the first read, you should use the `transfer_exactly` completion condition:
http://www.boost.org/doc/libs/1_56_0/doc/html/boost_asio/ reference/transfer_exactly.html
Jason
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
On 7 Aug 2014 at 23:11, Lee Clagett wrote:
unfortunately, the system call doesn't take the user buffer and notify when its been filled. That seems ideal, but maybe someone like Nial could explain the difficulties of such an implementation at the OS level.
I'd ask a simpler question: what use case is there for configuring multiple concurrent async reads on the same stream? On *files*, yes this makes sense. But on sockets/pipes etc, the use cases are not many (possibly with UDP yes, otherwise no). Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
On Sun, Aug 10, 2014 at 6:52 PM, Niall Douglas
I'd ask a simpler question: what use case is there for configuring multiple concurrent async reads on the same stream?
On *files*, yes this makes sense. But on sockets/pipes etc, the use cases are not many (possibly with UDP yes, otherwise no).
Niall
If you want to queue up multiple reads at a time (data to different buffers), having the framework handle it (ASIO or OS) is easier than writing that portion yourself. Lee
On 11 Aug 2014 at 8:56, Lee Clagett wrote:
I'd ask a simpler question: what use case is there for configuring multiple concurrent async reads on the same stream?
On *files*, yes this makes sense. But on sockets/pipes etc, the use cases are not many (possibly with UDP yes, otherwise no).
If you want to queue up multiple reads at a time (data to different buffers), having the framework handle it (ASIO or OS) is easier than writing that portion yourself.
ASIO (and AFIO) already provides scatter-gather i/o to do just this. Both call the appropriate OS facilities where those are available. See http://www.boost.org/doc/libs/1_56_0/doc/html/boost_asio/overview/core /buffers.html. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
On Mon, Aug 11, 2014 at 9:10 AM, Niall Douglas
On 11 Aug 2014 at 8:56, Lee Clagett wrote:
I'd ask a simpler question: what use case is there for configuring multiple concurrent async reads on the same stream?
On *files*, yes this makes sense. But on sockets/pipes etc, the use cases are not many (possibly with UDP yes, otherwise no).
If you want to queue up multiple reads at a time (data to different buffers), having the framework handle it (ASIO or OS) is easier than writing that portion yourself.
ASIO (and AFIO) already provides scatter-gather i/o to do just this. Both call the appropriate OS facilities where those are available. See http://www.boost.org/doc/libs/1_56_0/doc/html/boost_asio/overview/core /buffers.html.
Niall
I wanted to provide a generic interface for reading from a device. The most
simple interface I can think of would be: virtual std::string read(const
std::size_t) = 0;. Also, std::istream can be used and could be preferable.
However, what if you wanted to make this interface asynchronous? I don't
think std::istream is possible, but the other interface can be: virtual
std::futurestd::string read(const std::size_t) = 0. The interface should
handle the case where a second read was done before the prior read
completed. In that situation the interface either blocks until the other
future is set or tries to have a small queue so the client can continue
working unblocked. I wanted to do the latter. Perhaps it wasn't the best
idea because it was slow (used boost::futures). Although, I had no time to
analyze the performance issues either.
There are certainly ways to achieve that asynchronous interface using
scatter gather and containers (return a future
On 08/08/2014 03:54 AM, bbxiong wrote:
Will asio guarantee len1 bytes received by the first async_read, then schedule async_read2?
No such guarantees are given.
or the result is undefined(like several bytes filled into buffer1, then next several bytes into buffer, then next several bytes into buffer1)?
Yes, this may happen. Asio is opportunistic in the sense that it will try to complete an asynchronous operation immediately if it does not block. However, if the TCP stack does not contain all the requested data, then the first async_read() will read as much as it can, and then be scheduled for further reads. Unfortunately, the second async_read() is invoked inbetween, and if more data has become available in the TCP stack, then it will opportunisticly read that data, before being scheduled for further reads.
if the result is undefined, why asio don't add a check here?
Performance. If you always want to read two buffers at the time, you may consider using scatter I/O.
participants (5)
-
bbxiong
-
Bjorn Reese
-
Jason Roehm
-
Lee Clagett
-
Niall Douglas