I\'m using boost 1.50 with VS2010, reading using a Windows file HANDLE (which seems to be relatively uncommon compared to asio use with sockets).
One option is to fseek()
the file to the next position before the user's ReadHandler is called. Then async_read_some()
can be implemented as async_read_at(ftell())
.
The AsyncReader can use ReadUntilHandle instead of the stream_handle:
class ReadUntilHandle : public boost::asio::windows::random_access_handle
{
public:
ReadUntilHandle(boost::asio::io_service& ios, HANDLE handle)
: boost::asio::windows::random_access_handle(ios, handle)
{}
template
void async_read_some(const MutableBufferSequence& buffers, Handler& handler)
{
LARGE_INTEGER offset;
offset.QuadPart = 0;
if (::SetFilePointerEx(native_handle(), offset, &offset, FILE_CURRENT)) {
async_read_some_at(offset.QuadPart, buffers,
std::bind(&on_read_complete, handler,
native_handle(), std::ref(get_io_service()),
std::placeholders::_1, std::placeholders::_2));
} else {
boost::system::error_code error(::GetLastError(), boost::asio::error::get_system_category());
get_io_service().post(boost::asio::detail::bind_handler(handler, error, 0));
}
}
private:
template static void
on_read_complete(Handler& handler, HANDLE native_handle, boost::asio::io_service& ios,
boost::system::error_code error, std::size_t length)
{
if (0 != length) { // update file position
LARGE_INTEGER offset;
offset.QuadPart = length;
if (!::SetFilePointerEx(native_handle, offset, NULL, FILE_CURRENT) && !error) {
error.assign(::GetLastError(), boost::asio::error::get_system_category());
}
}
ios.dispatch(boost::asio::detail::bind_handler(handler, error, length));
}
};