asio::stream_file on windows
#include <asio.hpp>
#include <iostream>
int main(int argc, char* argv[])
{
asio::io_context context;
asio::executor_work_guard<asio::io_context::executor_type> guard =
asio::make_work_guard(context);
asio::stream_file file(context, "D:/file.txt",
asio::stream_file::write_only | asio::stream_file::create);
std::vector<char> s1(10, 'a');
std::vector<char> s2(10, 'b');
std::vector<char> s3(10, 'c');
std::array<asio::const_buffer, 3> buffers;
buffers[0] = asio::buffer(s1);
buffers[1] = asio::buffer(s2);
buffers[2] = asio::buffer(s3);
asio::async_write(file, buffers,
[&](const asio::error_code& error, std::size_t length)
{
if (error)
{
std::cerr << "An error occurred: " << error.message() << '\n';
}
file.close();
context.stop();
});
context.run();
return 0;
}
Linux:
aaaaaaaaaabbbbbbbbbbcccccccccc
Windows:
aaaaaaaaaa bbbbbbbbbb cccccccccc
The problem is in how file_stream keeps track of the current position. All win_iocp_file_service async/non-async and read/write functions have the problem. It's easiest to see in write_some
template <typename ConstBufferSequence>
size_t write_some(implementation_type& impl,
const ConstBufferSequence& buffers, asio::error_code& ec)
{
uint64_t offset = impl.offset_;
impl.offset_ += asio::buffer_size(buffers);
return handle_service_.write_some_at(impl, offset, buffers, ec);
}
Where the impl.offset_ is incremented by asio::buffer_size(buffers) instead of the amount of bytes actually written by the function below it.
The solution is trivial for the non-async functions, but I don't know Asio's internals well enough to know how lifetimes of objects, like the impl one, are handled after async operation is finished. Especially seeing that Asio is not using smart pointers internally.
Perhaps someone here might have ideas/hints?