Boost.Asio extensible to non network i/o?

I've been reading over the documentation for Boost.Asio and as far as I can tell the documentation makes no mention whatsoever about using Asio for anything other than sockets programming. Suppose I wanted to implemented a simple file transfer client (I say client because the server will not be in C++) that reads files off of the disk and sends them to the server. I'd like to do it asynchronously. What would be the basic steps needed to do this with Boost.Asio, if it is indeed even possible? I'd specifically like it to use I/O Completion Ports on Windows if possible, and whatever on Linux. I'd like to be able to configure the number of worker threads on the backend, so that for example I can read from N files at once, or from N different locations in the same file. I'd also like to have a single "controller" thread that receives all the events regarding when reads or writes complete, so that I don't have to use any kind of locking to synchronize things. As a final "nice-to-have", I'd like to be able to plug my own types of "actions" into the model, things that aren't really I/O but that I still want to execute asynchronously that would sit in between a completed disk read and the initiation of writing that same data to the socket. Think, for example, of encrypting the file before sending. I don't want to block on the encryption, so it would be nice if I could do that asynchronously and still be notified of its completion through the same interface. I know I can do all this directly in windows (which is the only system api i'm intimately familiar with) via IOCP, so I'm hoping something similar can be achieved with Boost.Asio. Thanks

Hi,
For disk i/o, you might want to give a look at this thread:
http://osdir.com/ml/lib.boost.asio.user/2006-11/msg00002.html
Cheers,
Lau
On Mon, Jun 1, 2009 at 1:12 PM, Zachary Turner
I've been reading over the documentation for Boost.Asio and as far as I can tell the documentation makes no mention whatsoever about using Asio for anything other than sockets programming. Suppose I wanted to implemented a simple file transfer client (I say client because the server will not be in C++) that reads files off of the disk and sends them to the server. I'd like to do it asynchronously. What would be the basic steps needed to do this with Boost.Asio, if it is indeed even possible? I'd specifically like it to use I/O Completion Ports on Windows if possible, and whatever on Linux. I'd like to be able to configure the number of worker threads on the backend, so that for example I can read from N files at once, or from N different locations in the same file. I'd also like to have a single "controller" thread that receives all the events regarding when reads or writes complete, so that I don't have to use any kind of locking to synchronize things.
As a final "nice-to-have", I'd like to be able to plug my own types of "actions" into the model, things that aren't really I/O but that I still want to execute asynchronously that would sit in between a completed disk read and the initiation of writing that same data to the socket. Think, for example, of encrypting the file before sending. I don't want to block on the encryption, so it would be nice if I could do that asynchronously and still be notified of its completion through the same interface. I know I can do all this directly in windows (which is the only system api i'm intimately familiar with) via IOCP, so I'm hoping something similar can be achieved with Boost.Asio.
Thanks
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Async file reading could be done in Windows. What I can give is the link to Russian blog: http://evgeny-lazin.blogspot.com/2008/12/boostasio.html Everything that you described - could be achieved by asio. You can configure number of working threads by running io_service.run() from each of them. I guess, at this point you _will_ need to syncronize access to "controller" through some mutex or asio::strands and it will not significantly lower performance.

On Mon, Jun 1, 2009 at 1:33 AM, Roman Shmelev
Async file reading could be done in Windows. What I can give is the link to Russian blog: http://evgeny-lazin.blogspot.com/2008/12/boostasio.html
Everything that you described - could be achieved by asio. You can configure number of working threads by running io_service.run() from each of them. I guess, at this point you _will_ need to syncronize access to "controller" through some mutex or asio::strands and it will not significantly lower performance.
So let me see if I understand the basic model correctly. In Windows I only have to "think" about 1 thread, which is the main controller thread that runs the event loop. The event loop looks something like this (pseudocode): int bytes_transferred = 0; event_params params; uint64 next_read_offset = 0; uint64 next_write_offset = 0; int outstanding_reads = 0; int outstanding_writes = 0; //Fill up the threads with read work for (int i=0; i < max_worker_threads; ++i) { async_request(READ_REQUEST, next_read_offset, input_handle, 4096); next_read_offset += 4096; } while (bytes_transferred < bytes_total) { request what_happened; block_until_something_happens(&what_happened); switch (what_happened.code) { case READ_REQUEST: --outstanding_reads; ++outstanding_writes; request.type = WRITE_REQUEST; request.offset = next_write_offset; request.handle = output_handle; request.bytes = request.bytes; /* write the same number of bytes that were just read */ next_write_offset += request.bytes; async_request(&request); break; case WRITE_REQUEST: --outstanding_writes; bytes_transferred += params.bytes_written; if (bytes_transferred < bytes_total) { ++outstanding_reads; request.type = READ_REQUEST; request.offset = next_read_offset; request.handle = input_handle; request.bytes = 4096; /* always read in 4k chunks */ next_read_offset += 4096; async_request(&request); } } } This way nothing ever has to be synchronized because there is only 1 thread initiating all the reads and writes, what happens in the other threads is completely controlled by the operating system, even the threads are created by the operating system. So to achieve something similar with Boost.Asio, my understanding is that: a) I can use a standard io_service (don't need to provide a custom implementation) for the controller thread, and 1 additional io_service instance for all worker threads combined. So a total of 2 io_service instances no matter how many threads I want. b) I create the worker threads manually (so if I want to be able to have 5 outstanding I/O operations spread among reads and writes, I create 5 boost::thread objects, and at the very beginning call service.run() on the single io_service instance used for work. c) In the read_handler() and write_handler() methods that get called on the individual worker threads, I simply call controller_io_service.post(ReadFinished) or controller_io_service.post(WriteFinished). Would something like this work? (I could also just try this and _see_ if it works, but I've already been trying it and for some reason the pieces aren't all fitting together in my head). At what point in this process would I call run() on the master controller io_service?

Zachary Turner wrote:
I've been reading over the documentation for Boost.Asio and as far as I can tell the documentation makes no mention whatsoever about using Asio for anything other than sockets programming.
Boost.Asio supports serial ports as well.
implemented a simple file transfer client (I say client because the server will not be in C++) that reads files off of the disk and sends them to the server. I'd like to do it asynchronously. What would be the basic steps needed to do this with Boost.Asio, if it is indeed even possible?
There are examples of client / server applications, and although based on sockets, with appropriate modifications could run over, say, serial ports.
As a final "nice-to-have", I'd like to be able to plug my own types of "actions" into the model, things that aren't really I/O but that I still want to execute asynchronously that would sit in between a completed disk read and the initiation of writing that same data to the socket.
I use Boost.Asio not only for sockets, serial ports, and files, but also to implement asynchronous message passing between threads. This involves using io_service.post() to post functor objects to the thread. I usually use the "active object" kind of idiom in this case. Anyway, my point is that I believe Boost.Asio can be used for the kinds of things that you describe. Kevin

On Mon, 01 Jun 2009 06:12:35 +0200, Zachary Turner
[...]like to do it asynchronously. What would be the basic steps needed to do this with Boost.Asio, if it is indeed even possible? I'd specifically
There is a section in my book about how to extend Boost.Asio and create a new I/O object. While the book is in German it might already help to see the sample code: http://www.highscore.de/cpp/boost/asio.html#erweiterung There is also a ready-to-use Boost.Asio extension at http://www.highscore.de/boost/dir_monitor.zip (current implementation works only on Windows). HTH, Boris
[...]
participants (5)
-
Boris Schaeling
-
Kevin Scarr
-
Laurent Fert
-
Roman Shmelev
-
Zachary Turner