2015-08-25 0:10 GMT+03:00 Niall Douglas
On 24 Aug 2015 at 21:46, Antony Polukhin wrote:
2) "A less toy example: Concatenating files"
That's example not nice in a multiple ways. First of all, it combines explicit usage of `boost::afio::dispatcher` with implicit `current_dispatcher_guard`. It would be good to have single way of dealing with dispatchers in example. `current_dispatcher_guard` seems more simple (and that's what i like in examples :) )
I'm not sure what you mean here. That example creates a dispatcher. It then sets via RAII of the guard variable the current thread local dispatcher.
Let me clarify. In that example you use two approaches, one of wich explicitly uses `dispatcher` (for example `dispatcher->file(ihs_reqs)`) while the other approach uses `dispatcher` implicitly (for example `async_truncate(oh, offset)`). The example would look more solid if only one approach will be used. The implicit dispatcher looks more simple, which I think is good for examples.
Also, thread count 1 seems more right and less error prone (by default this will require no threads synchronization from users).
I'm not sure which thread count you mean here.
By default thread_pool is creted that spawns some performance optimal count of threads. I'm proposing to spawn minimal amount of threads (1 thread) by default. In that way novice user could experiment with library without any need to think of threads synchronization. Such change (1 thread by default) will reduce the library entry barrier. But that's only my opinion, it's not a requirement :)
Additionally this example is hard to understand and requires a lot of code while solves a very common problem. Could AFIO reuse POSIX splice/vmsplice and provide an async_copy function? If yes, then amount of code could be significantly reduced and no memory allocations will be required.
splice/vmsplice are Linux only, not POSIX. FreeBSD implements a subset of them for sockets only.
Unfortunately they have an annoyingly broken API which is incompatible with the ASIO reactor. The problem is SPLICE_F_NONBLOCK because you cannot feed any fd into an alertable wait state for ASIO. That means you need to dedicate a thread to block on the kernel-side copy. I really wish Linux were more like BSD - on BSD you can have a kevent notify you when an async i/o operation changes its state. Lovely API, really efficient too. And is ASIO compatible.
I don't discount looking into them again sometime in the future, but I didn't find any benefit of splice() over read()/write() until 64Kb blocks or bigger, and even then it is not a huge benefit. I suspect the cost of copying memory is low in the single threaded case relative to the cost of the Linux kernel file page cache. Of course, on big thread counts you end up evicting much useful data from the L1/L2/L3 caches with file i/o on Linux, but we're getting into premature optimisation here I think.
You've convinced me. But I still insist on `async_copy` method ready out of
the box. This could be really usefull + will untie your hands for future
modifications (for example you could try to call splice/tee and if that
blocks - do the copying using memory allocations).
OK, good news: I've finally understood the docs and all the interface
decisions that were made. This leads to my decision to review AFIO in two
parts: nonbatch and batch.
This is still not a review, just some discussion. Let's start from the
nonbatch operations...
NONBATCH
I like the interface, I love it. Some comments:
Most part of the functions in table "AFIO single page cheat sheet for the
very impatient" have synchronous analogs in Boost.Filesystem
http://www.boost.org/doc/libs/1_59_0/libs/filesystem/doc/reference.html
How about changing the names to be more close to the Boost.Filesystem. For
example:
async_truncate -> async_resize_file
truncate -> resize_file
async_dir -> async_directory
async_rmfile + async_rmsymlink -> async_remove
async_rmdir -> async_remove_all
I'm not a huge fan of Boost.Filesystem names, but they are almost a part of
the C++ Standard now. Keeping close to them will simplify user's life by
not forcing the user to learn new names. It will make the migration from
sync Filesystem code to async AFIO more easy.
Additionally use the Boost.Interprocess naming for file_flags:
create_only_if_not_exist -> create_only, create -> open_or_create, add
open_only
Probably rename `file_flags` into `open_flags`, because those flags are
also usable for directories and used only at open.
Also describe all the `T` in `async_` operations. For example
template