Update IDF to a0468b2 (#2108)

* Update IDF to a0468b2

* add missing ld file

* Fix PIO builds and change coex policy
This commit is contained in:
Me No Dev
2018-11-26 23:22:11 +01:00
committed by GitHub
parent c3ec91f968
commit 04963009ee
988 changed files with 114643 additions and 65141 deletions

View File

@ -0,0 +1,429 @@
//
// impl/buffered_read_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_BUFFERED_READ_STREAM_HPP
#define ASIO_IMPL_BUFFERED_READ_STREAM_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/associated_allocator.hpp"
#include "asio/associated_executor.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_cont_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/handler_type_requirements.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
template <typename Stream>
std::size_t buffered_read_stream<Stream>::fill()
{
detail::buffer_resize_guard<detail::buffered_stream_storage>
resize_guard(storage_);
std::size_t previous_size = storage_.size();
storage_.resize(storage_.capacity());
storage_.resize(previous_size + next_layer_.read_some(buffer(
storage_.data() + previous_size,
storage_.size() - previous_size)));
resize_guard.commit();
return storage_.size() - previous_size;
}
template <typename Stream>
std::size_t buffered_read_stream<Stream>::fill(asio::error_code& ec)
{
detail::buffer_resize_guard<detail::buffered_stream_storage>
resize_guard(storage_);
std::size_t previous_size = storage_.size();
storage_.resize(storage_.capacity());
storage_.resize(previous_size + next_layer_.read_some(buffer(
storage_.data() + previous_size,
storage_.size() - previous_size),
ec));
resize_guard.commit();
return storage_.size() - previous_size;
}
namespace detail
{
template <typename ReadHandler>
class buffered_fill_handler
{
public:
buffered_fill_handler(detail::buffered_stream_storage& storage,
std::size_t previous_size, ReadHandler& handler)
: storage_(storage),
previous_size_(previous_size),
handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
{
}
#if defined(ASIO_HAS_MOVE)
buffered_fill_handler(const buffered_fill_handler& other)
: storage_(other.storage_),
previous_size_(other.previous_size_),
handler_(other.handler_)
{
}
buffered_fill_handler(buffered_fill_handler&& other)
: storage_(other.storage_),
previous_size_(other.previous_size_),
handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
{
}
#endif // defined(ASIO_HAS_MOVE)
void operator()(const asio::error_code& ec,
const std::size_t bytes_transferred)
{
storage_.resize(previous_size_ + bytes_transferred);
handler_(ec, bytes_transferred);
}
//private:
detail::buffered_stream_storage& storage_;
std::size_t previous_size_;
ReadHandler handler_;
};
template <typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
buffered_fill_handler<ReadHandler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
buffered_fill_handler<ReadHandler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename ReadHandler>
inline bool asio_handler_is_continuation(
buffered_fill_handler<ReadHandler>* this_handler)
{
return asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename ReadHandler>
inline void asio_handler_invoke(Function& function,
buffered_fill_handler<ReadHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
buffered_fill_handler<ReadHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename ReadHandler, typename Allocator>
struct associated_allocator<
detail::buffered_fill_handler<ReadHandler>, Allocator>
{
typedef typename associated_allocator<ReadHandler, Allocator>::type type;
static type get(const detail::buffered_fill_handler<ReadHandler>& h,
const Allocator& a = Allocator()) ASIO_NOEXCEPT
{
return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
}
};
template <typename ReadHandler, typename Executor>
struct associated_executor<
detail::buffered_fill_handler<ReadHandler>, Executor>
{
typedef typename associated_executor<ReadHandler, Executor>::type type;
static type get(const detail::buffered_fill_handler<ReadHandler>& h,
const Executor& ex = Executor()) ASIO_NOEXCEPT
{
return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename Stream>
template <typename ReadHandler>
ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (asio::error_code, std::size_t))
buffered_read_stream<Stream>::async_fill(
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
std::size_t previous_size = storage_.size();
storage_.resize(storage_.capacity());
next_layer_.async_read_some(
buffer(
storage_.data() + previous_size,
storage_.size() - previous_size),
detail::buffered_fill_handler<ASIO_HANDLER_TYPE(
ReadHandler, void (asio::error_code, std::size_t))>(
storage_, previous_size, init.completion_handler));
return init.result.get();
}
template <typename Stream>
template <typename MutableBufferSequence>
std::size_t buffered_read_stream<Stream>::read_some(
const MutableBufferSequence& buffers)
{
using asio::buffer_size;
if (buffer_size(buffers) == 0)
return 0;
if (storage_.empty())
this->fill();
return this->copy(buffers);
}
template <typename Stream>
template <typename MutableBufferSequence>
std::size_t buffered_read_stream<Stream>::read_some(
const MutableBufferSequence& buffers, asio::error_code& ec)
{
ec = asio::error_code();
using asio::buffer_size;
if (buffer_size(buffers) == 0)
return 0;
if (storage_.empty() && !this->fill(ec))
return 0;
return this->copy(buffers);
}
namespace detail
{
template <typename MutableBufferSequence, typename ReadHandler>
class buffered_read_some_handler
{
public:
buffered_read_some_handler(detail::buffered_stream_storage& storage,
const MutableBufferSequence& buffers, ReadHandler& handler)
: storage_(storage),
buffers_(buffers),
handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
{
}
#if defined(ASIO_HAS_MOVE)
buffered_read_some_handler(const buffered_read_some_handler& other)
: storage_(other.storage_),
buffers_(other.buffers_),
handler_(other.handler_)
{
}
buffered_read_some_handler(buffered_read_some_handler&& other)
: storage_(other.storage_),
buffers_(other.buffers_),
handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
{
}
#endif // defined(ASIO_HAS_MOVE)
void operator()(const asio::error_code& ec, std::size_t)
{
if (ec || storage_.empty())
{
const std::size_t length = 0;
handler_(ec, length);
}
else
{
const std::size_t bytes_copied = asio::buffer_copy(
buffers_, storage_.data(), storage_.size());
storage_.consume(bytes_copied);
handler_(ec, bytes_copied);
}
}
//private:
detail::buffered_stream_storage& storage_;
MutableBufferSequence buffers_;
ReadHandler handler_;
};
template <typename MutableBufferSequence, typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
buffered_read_some_handler<
MutableBufferSequence, ReadHandler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename MutableBufferSequence, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
buffered_read_some_handler<
MutableBufferSequence, ReadHandler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename MutableBufferSequence, typename ReadHandler>
inline bool asio_handler_is_continuation(
buffered_read_some_handler<
MutableBufferSequence, ReadHandler>* this_handler)
{
return asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename MutableBufferSequence,
typename ReadHandler>
inline void asio_handler_invoke(Function& function,
buffered_read_some_handler<
MutableBufferSequence, ReadHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename MutableBufferSequence,
typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
buffered_read_some_handler<
MutableBufferSequence, ReadHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename MutableBufferSequence,
typename ReadHandler, typename Allocator>
struct associated_allocator<
detail::buffered_read_some_handler<MutableBufferSequence, ReadHandler>,
Allocator>
{
typedef typename associated_allocator<ReadHandler, Allocator>::type type;
static type get(
const detail::buffered_read_some_handler<
MutableBufferSequence, ReadHandler>& h,
const Allocator& a = Allocator()) ASIO_NOEXCEPT
{
return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
}
};
template <typename MutableBufferSequence,
typename ReadHandler, typename Executor>
struct associated_executor<
detail::buffered_read_some_handler<MutableBufferSequence, ReadHandler>,
Executor>
{
typedef typename associated_executor<ReadHandler, Executor>::type type;
static type get(
const detail::buffered_read_some_handler<
MutableBufferSequence, ReadHandler>& h,
const Executor& ex = Executor()) ASIO_NOEXCEPT
{
return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename Stream>
template <typename MutableBufferSequence, typename ReadHandler>
ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (asio::error_code, std::size_t))
buffered_read_stream<Stream>::async_read_some(
const MutableBufferSequence& buffers,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
using asio::buffer_size;
if (buffer_size(buffers) == 0 || !storage_.empty())
{
next_layer_.async_read_some(ASIO_MUTABLE_BUFFER(0, 0),
detail::buffered_read_some_handler<
MutableBufferSequence, ASIO_HANDLER_TYPE(
ReadHandler, void (asio::error_code, std::size_t))>(
storage_, buffers, init.completion_handler));
}
else
{
this->async_fill(detail::buffered_read_some_handler<
MutableBufferSequence, ASIO_HANDLER_TYPE(
ReadHandler, void (asio::error_code, std::size_t))>(
storage_, buffers, init.completion_handler));
}
return init.result.get();
}
template <typename Stream>
template <typename MutableBufferSequence>
std::size_t buffered_read_stream<Stream>::peek(
const MutableBufferSequence& buffers)
{
if (storage_.empty())
this->fill();
return this->peek_copy(buffers);
}
template <typename Stream>
template <typename MutableBufferSequence>
std::size_t buffered_read_stream<Stream>::peek(
const MutableBufferSequence& buffers, asio::error_code& ec)
{
ec = asio::error_code();
if (storage_.empty() && !this->fill(ec))
return 0;
return this->peek_copy(buffers);
}
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_BUFFERED_READ_STREAM_HPP

View File

@ -0,0 +1,411 @@
//
// impl/buffered_write_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_BUFFERED_WRITE_STREAM_HPP
#define ASIO_IMPL_BUFFERED_WRITE_STREAM_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/associated_allocator.hpp"
#include "asio/associated_executor.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_cont_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/handler_type_requirements.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
template <typename Stream>
std::size_t buffered_write_stream<Stream>::flush()
{
std::size_t bytes_written = write(next_layer_,
buffer(storage_.data(), storage_.size()));
storage_.consume(bytes_written);
return bytes_written;
}
template <typename Stream>
std::size_t buffered_write_stream<Stream>::flush(asio::error_code& ec)
{
std::size_t bytes_written = write(next_layer_,
buffer(storage_.data(), storage_.size()),
transfer_all(), ec);
storage_.consume(bytes_written);
return bytes_written;
}
namespace detail
{
template <typename WriteHandler>
class buffered_flush_handler
{
public:
buffered_flush_handler(detail::buffered_stream_storage& storage,
WriteHandler& handler)
: storage_(storage),
handler_(ASIO_MOVE_CAST(WriteHandler)(handler))
{
}
#if defined(ASIO_HAS_MOVE)
buffered_flush_handler(const buffered_flush_handler& other)
: storage_(other.storage_),
handler_(other.handler_)
{
}
buffered_flush_handler(buffered_flush_handler&& other)
: storage_(other.storage_),
handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))
{
}
#endif // defined(ASIO_HAS_MOVE)
void operator()(const asio::error_code& ec,
const std::size_t bytes_written)
{
storage_.consume(bytes_written);
handler_(ec, bytes_written);
}
//private:
detail::buffered_stream_storage& storage_;
WriteHandler handler_;
};
template <typename WriteHandler>
inline void* asio_handler_allocate(std::size_t size,
buffered_flush_handler<WriteHandler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename WriteHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
buffered_flush_handler<WriteHandler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename WriteHandler>
inline bool asio_handler_is_continuation(
buffered_flush_handler<WriteHandler>* this_handler)
{
return asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename WriteHandler>
inline void asio_handler_invoke(Function& function,
buffered_flush_handler<WriteHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename WriteHandler>
inline void asio_handler_invoke(const Function& function,
buffered_flush_handler<WriteHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename WriteHandler, typename Allocator>
struct associated_allocator<
detail::buffered_flush_handler<WriteHandler>, Allocator>
{
typedef typename associated_allocator<WriteHandler, Allocator>::type type;
static type get(const detail::buffered_flush_handler<WriteHandler>& h,
const Allocator& a = Allocator()) ASIO_NOEXCEPT
{
return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
}
};
template <typename WriteHandler, typename Executor>
struct associated_executor<
detail::buffered_flush_handler<WriteHandler>, Executor>
{
typedef typename associated_executor<WriteHandler, Executor>::type type;
static type get(const detail::buffered_flush_handler<WriteHandler>& h,
const Executor& ex = Executor()) ASIO_NOEXCEPT
{
return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename Stream>
template <typename WriteHandler>
ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (asio::error_code, std::size_t))
buffered_write_stream<Stream>::async_flush(
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
async_write(next_layer_, buffer(storage_.data(), storage_.size()),
detail::buffered_flush_handler<ASIO_HANDLER_TYPE(
WriteHandler, void (asio::error_code, std::size_t))>(
storage_, init.completion_handler));
return init.result.get();
}
template <typename Stream>
template <typename ConstBufferSequence>
std::size_t buffered_write_stream<Stream>::write_some(
const ConstBufferSequence& buffers)
{
using asio::buffer_size;
if (buffer_size(buffers) == 0)
return 0;
if (storage_.size() == storage_.capacity())
this->flush();
return this->copy(buffers);
}
template <typename Stream>
template <typename ConstBufferSequence>
std::size_t buffered_write_stream<Stream>::write_some(
const ConstBufferSequence& buffers, asio::error_code& ec)
{
ec = asio::error_code();
using asio::buffer_size;
if (buffer_size(buffers) == 0)
return 0;
if (storage_.size() == storage_.capacity() && !flush(ec))
return 0;
return this->copy(buffers);
}
namespace detail
{
template <typename ConstBufferSequence, typename WriteHandler>
class buffered_write_some_handler
{
public:
buffered_write_some_handler(detail::buffered_stream_storage& storage,
const ConstBufferSequence& buffers, WriteHandler& handler)
: storage_(storage),
buffers_(buffers),
handler_(ASIO_MOVE_CAST(WriteHandler)(handler))
{
}
#if defined(ASIO_HAS_MOVE)
buffered_write_some_handler(const buffered_write_some_handler& other)
: storage_(other.storage_),
buffers_(other.buffers_),
handler_(other.handler_)
{
}
buffered_write_some_handler(buffered_write_some_handler&& other)
: storage_(other.storage_),
buffers_(other.buffers_),
handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))
{
}
#endif // defined(ASIO_HAS_MOVE)
void operator()(const asio::error_code& ec, std::size_t)
{
if (ec)
{
const std::size_t length = 0;
handler_(ec, length);
}
else
{
using asio::buffer_size;
std::size_t orig_size = storage_.size();
std::size_t space_avail = storage_.capacity() - orig_size;
std::size_t bytes_avail = buffer_size(buffers_);
std::size_t length = bytes_avail < space_avail
? bytes_avail : space_avail;
storage_.resize(orig_size + length);
const std::size_t bytes_copied = asio::buffer_copy(
storage_.data() + orig_size, buffers_, length);
handler_(ec, bytes_copied);
}
}
//private:
detail::buffered_stream_storage& storage_;
ConstBufferSequence buffers_;
WriteHandler handler_;
};
template <typename ConstBufferSequence, typename WriteHandler>
inline void* asio_handler_allocate(std::size_t size,
buffered_write_some_handler<
ConstBufferSequence, WriteHandler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename ConstBufferSequence, typename WriteHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
buffered_write_some_handler<
ConstBufferSequence, WriteHandler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename ConstBufferSequence, typename WriteHandler>
inline bool asio_handler_is_continuation(
buffered_write_some_handler<
ConstBufferSequence, WriteHandler>* this_handler)
{
return asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename ConstBufferSequence,
typename WriteHandler>
inline void asio_handler_invoke(Function& function,
buffered_write_some_handler<
ConstBufferSequence, WriteHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename ConstBufferSequence,
typename WriteHandler>
inline void asio_handler_invoke(const Function& function,
buffered_write_some_handler<
ConstBufferSequence, WriteHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename ConstBufferSequence,
typename WriteHandler, typename Allocator>
struct associated_allocator<
detail::buffered_write_some_handler<ConstBufferSequence, WriteHandler>,
Allocator>
{
typedef typename associated_allocator<WriteHandler, Allocator>::type type;
static type get(
const detail::buffered_write_some_handler<
ConstBufferSequence, WriteHandler>& h,
const Allocator& a = Allocator()) ASIO_NOEXCEPT
{
return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
}
};
template <typename ConstBufferSequence,
typename WriteHandler, typename Executor>
struct associated_executor<
detail::buffered_write_some_handler<ConstBufferSequence, WriteHandler>,
Executor>
{
typedef typename associated_executor<WriteHandler, Executor>::type type;
static type get(
const detail::buffered_write_some_handler<
ConstBufferSequence, WriteHandler>& h,
const Executor& ex = Executor()) ASIO_NOEXCEPT
{
return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename Stream>
template <typename ConstBufferSequence, typename WriteHandler>
ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (asio::error_code, std::size_t))
buffered_write_stream<Stream>::async_write_some(
const ConstBufferSequence& buffers,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
using asio::buffer_size;
if (buffer_size(buffers) == 0
|| storage_.size() < storage_.capacity())
{
next_layer_.async_write_some(ASIO_CONST_BUFFER(0, 0),
detail::buffered_write_some_handler<
ConstBufferSequence, ASIO_HANDLER_TYPE(
WriteHandler, void (asio::error_code, std::size_t))>(
storage_, buffers, init.completion_handler));
}
else
{
this->async_flush(detail::buffered_write_some_handler<
ConstBufferSequence, ASIO_HANDLER_TYPE(
WriteHandler, void (asio::error_code, std::size_t))>(
storage_, buffers, init.completion_handler));
}
return init.result.get();
}
template <typename Stream>
template <typename ConstBufferSequence>
std::size_t buffered_write_stream<Stream>::copy(
const ConstBufferSequence& buffers)
{
using asio::buffer_size;
std::size_t orig_size = storage_.size();
std::size_t space_avail = storage_.capacity() - orig_size;
std::size_t bytes_avail = buffer_size(buffers);
std::size_t length = bytes_avail < space_avail ? bytes_avail : space_avail;
storage_.resize(orig_size + length);
return asio::buffer_copy(
storage_.data() + orig_size, buffers, length);
}
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_BUFFERED_WRITE_STREAM_HPP

View File

@ -0,0 +1,860 @@
//
// impl/connect.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_CONNECT_HPP
#define ASIO_IMPL_CONNECT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <algorithm>
#include "asio/associated_allocator.hpp"
#include "asio/associated_executor.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_cont_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/handler_type_requirements.hpp"
#include "asio/detail/throw_error.hpp"
#include "asio/error.hpp"
#include "asio/post.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail
{
struct default_connect_condition
{
template <typename Endpoint>
bool operator()(const asio::error_code&, const Endpoint&)
{
return true;
}
};
template <typename Protocol, typename Iterator>
inline typename Protocol::endpoint deref_connect_result(
Iterator iter, asio::error_code& ec)
{
return ec ? typename Protocol::endpoint() : *iter;
}
template <typename T, typename Iterator>
struct legacy_connect_condition_helper : T
{
typedef char (*fallback_func_type)(...);
operator fallback_func_type() const;
};
template <typename R, typename Arg1, typename Arg2, typename Iterator>
struct legacy_connect_condition_helper<R (*)(Arg1, Arg2), Iterator>
{
R operator()(Arg1, Arg2) const;
char operator()(...) const;
};
template <typename T, typename Iterator>
struct is_legacy_connect_condition
{
static char asio_connect_condition_check(char);
static char (&asio_connect_condition_check(Iterator))[2];
static const bool value =
sizeof(asio_connect_condition_check(
(*static_cast<legacy_connect_condition_helper<T, Iterator>*>(0))(
*static_cast<const asio::error_code*>(0),
*static_cast<const Iterator*>(0)))) != 1;
};
template <typename ConnectCondition, typename Iterator>
inline Iterator call_connect_condition(ConnectCondition& connect_condition,
const asio::error_code& ec, Iterator next, Iterator end,
typename enable_if<is_legacy_connect_condition<
ConnectCondition, Iterator>::value>::type* = 0)
{
if (next != end)
return connect_condition(ec, next);
return end;
}
template <typename ConnectCondition, typename Iterator>
inline Iterator call_connect_condition(ConnectCondition& connect_condition,
const asio::error_code& ec, Iterator next, Iterator end,
typename enable_if<!is_legacy_connect_condition<
ConnectCondition, Iterator>::value>::type* = 0)
{
for (;next != end; ++next)
if (connect_condition(ec, *next))
return next;
return end;
}
}
template <typename Protocol ASIO_SVC_TPARAM, typename EndpointSequence>
typename Protocol::endpoint connect(
basic_socket<Protocol ASIO_SVC_TARG>& s,
const EndpointSequence& endpoints,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type*)
{
asio::error_code ec;
typename Protocol::endpoint result = connect(s, endpoints, ec);
asio::detail::throw_error(ec, "connect");
return result;
}
template <typename Protocol ASIO_SVC_TPARAM, typename EndpointSequence>
typename Protocol::endpoint connect(
basic_socket<Protocol ASIO_SVC_TARG>& s,
const EndpointSequence& endpoints, asio::error_code& ec,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type*)
{
return detail::deref_connect_result<Protocol>(
connect(s, endpoints.begin(), endpoints.end(),
detail::default_connect_condition(), ec), ec);
}
#if !defined(ASIO_NO_DEPRECATED)
template <typename Protocol ASIO_SVC_TPARAM, typename Iterator>
Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s, Iterator begin,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
{
asio::error_code ec;
Iterator result = connect(s, begin, ec);
asio::detail::throw_error(ec, "connect");
return result;
}
template <typename Protocol ASIO_SVC_TPARAM, typename Iterator>
inline Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
Iterator begin, asio::error_code& ec,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
{
return connect(s, begin, Iterator(), detail::default_connect_condition(), ec);
}
#endif // !defined(ASIO_NO_DEPRECATED)
template <typename Protocol ASIO_SVC_TPARAM, typename Iterator>
Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
Iterator begin, Iterator end)
{
asio::error_code ec;
Iterator result = connect(s, begin, end, ec);
asio::detail::throw_error(ec, "connect");
return result;
}
template <typename Protocol ASIO_SVC_TPARAM, typename Iterator>
inline Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
Iterator begin, Iterator end, asio::error_code& ec)
{
return connect(s, begin, end, detail::default_connect_condition(), ec);
}
template <typename Protocol ASIO_SVC_TPARAM,
typename EndpointSequence, typename ConnectCondition>
typename Protocol::endpoint connect(
basic_socket<Protocol ASIO_SVC_TARG>& s,
const EndpointSequence& endpoints, ConnectCondition connect_condition,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type*)
{
asio::error_code ec;
typename Protocol::endpoint result = connect(
s, endpoints, connect_condition, ec);
asio::detail::throw_error(ec, "connect");
return result;
}
template <typename Protocol ASIO_SVC_TPARAM,
typename EndpointSequence, typename ConnectCondition>
typename Protocol::endpoint connect(
basic_socket<Protocol ASIO_SVC_TARG>& s,
const EndpointSequence& endpoints, ConnectCondition connect_condition,
asio::error_code& ec,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type*)
{
return detail::deref_connect_result<Protocol>(
connect(s, endpoints.begin(), endpoints.end(),
connect_condition, ec), ec);
}
#if !defined(ASIO_NO_DEPRECATED)
template <typename Protocol ASIO_SVC_TPARAM,
typename Iterator, typename ConnectCondition>
Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
Iterator begin, ConnectCondition connect_condition,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
{
asio::error_code ec;
Iterator result = connect(s, begin, connect_condition, ec);
asio::detail::throw_error(ec, "connect");
return result;
}
template <typename Protocol ASIO_SVC_TPARAM,
typename Iterator, typename ConnectCondition>
inline Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
Iterator begin, ConnectCondition connect_condition,
asio::error_code& ec,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
{
return connect(s, begin, Iterator(), connect_condition, ec);
}
#endif // !defined(ASIO_NO_DEPRECATED)
template <typename Protocol ASIO_SVC_TPARAM,
typename Iterator, typename ConnectCondition>
Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
Iterator begin, Iterator end, ConnectCondition connect_condition)
{
asio::error_code ec;
Iterator result = connect(s, begin, end, connect_condition, ec);
asio::detail::throw_error(ec, "connect");
return result;
}
template <typename Protocol ASIO_SVC_TPARAM,
typename Iterator, typename ConnectCondition>
Iterator connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
Iterator begin, Iterator end, ConnectCondition connect_condition,
asio::error_code& ec)
{
ec = asio::error_code();
for (Iterator iter = begin; iter != end; ++iter)
{
iter = (detail::call_connect_condition(connect_condition, ec, iter, end));
if (iter != end)
{
s.close(ec);
s.connect(*iter, ec);
if (!ec)
return iter;
}
else
break;
}
if (!ec)
ec = asio::error::not_found;
return end;
}
namespace detail
{
// Enable the empty base class optimisation for the connect condition.
template <typename ConnectCondition>
class base_from_connect_condition
{
protected:
explicit base_from_connect_condition(
const ConnectCondition& connect_condition)
: connect_condition_(connect_condition)
{
}
template <typename Iterator>
void check_condition(const asio::error_code& ec,
Iterator& iter, Iterator& end)
{
iter = detail::call_connect_condition(connect_condition_, ec, iter, end);
}
private:
ConnectCondition connect_condition_;
};
// The default_connect_condition implementation is essentially a no-op. This
// template specialisation lets us eliminate all costs associated with it.
template <>
class base_from_connect_condition<default_connect_condition>
{
protected:
explicit base_from_connect_condition(const default_connect_condition&)
{
}
template <typename Iterator>
void check_condition(const asio::error_code&, Iterator&, Iterator&)
{
}
};
template <typename Protocol ASIO_SVC_TPARAM,
typename EndpointSequence, typename ConnectCondition,
typename RangeConnectHandler>
class range_connect_op : base_from_connect_condition<ConnectCondition>
{
public:
range_connect_op(basic_socket<Protocol ASIO_SVC_TARG>& sock,
const EndpointSequence& endpoints,
const ConnectCondition& connect_condition,
RangeConnectHandler& handler)
: base_from_connect_condition<ConnectCondition>(connect_condition),
socket_(sock),
endpoints_(endpoints),
index_(0),
start_(0),
handler_(ASIO_MOVE_CAST(RangeConnectHandler)(handler))
{
}
#if defined(ASIO_HAS_MOVE)
range_connect_op(const range_connect_op& other)
: base_from_connect_condition<ConnectCondition>(other),
socket_(other.socket_),
endpoints_(other.endpoints_),
index_(other.index_),
start_(other.start_),
handler_(other.handler_)
{
}
range_connect_op(range_connect_op&& other)
: base_from_connect_condition<ConnectCondition>(other),
socket_(other.socket_),
endpoints_(other.endpoints_),
index_(other.index_),
start_(other.start_),
handler_(ASIO_MOVE_CAST(RangeConnectHandler)(other.handler_))
{
}
#endif // defined(ASIO_HAS_MOVE)
void operator()(asio::error_code ec, int start = 0)
{
typename EndpointSequence::const_iterator begin = endpoints_.begin();
typename EndpointSequence::const_iterator iter = begin;
std::advance(iter, index_);
typename EndpointSequence::const_iterator end = endpoints_.end();
switch (start_ = start)
{
case 1:
for (;;)
{
this->check_condition(ec, iter, end);
index_ = std::distance(begin, iter);
if (iter != end)
{
socket_.close(ec);
socket_.async_connect(*iter,
ASIO_MOVE_CAST(range_connect_op)(*this));
return;
}
if (start)
{
ec = asio::error::not_found;
asio::post(socket_.get_executor(),
detail::bind_handler(
ASIO_MOVE_CAST(range_connect_op)(*this), ec));
return;
}
default:
if (iter == end)
break;
if (!socket_.is_open())
{
ec = asio::error::operation_aborted;
break;
}
if (!ec)
break;
++iter;
++index_;
}
handler_(static_cast<const asio::error_code&>(ec),
static_cast<const typename Protocol::endpoint&>(
ec || iter == end ? typename Protocol::endpoint() : *iter));
}
}
//private:
basic_socket<Protocol ASIO_SVC_TARG>& socket_;
EndpointSequence endpoints_;
std::size_t index_;
int start_;
RangeConnectHandler handler_;
};
template <typename Protocol ASIO_SVC_TPARAM,
typename EndpointSequence, typename ConnectCondition,
typename RangeConnectHandler>
inline void* asio_handler_allocate(std::size_t size,
range_connect_op<Protocol ASIO_SVC_TARG, EndpointSequence,
ConnectCondition, RangeConnectHandler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename Protocol ASIO_SVC_TPARAM,
typename EndpointSequence, typename ConnectCondition,
typename RangeConnectHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
range_connect_op<Protocol ASIO_SVC_TARG, EndpointSequence,
ConnectCondition, RangeConnectHandler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename Protocol ASIO_SVC_TPARAM,
typename EndpointSequence, typename ConnectCondition,
typename RangeConnectHandler>
inline bool asio_handler_is_continuation(
range_connect_op<Protocol ASIO_SVC_TARG, EndpointSequence,
ConnectCondition, RangeConnectHandler>* this_handler)
{
return asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename Protocol
ASIO_SVC_TPARAM, typename EndpointSequence,
typename ConnectCondition, typename RangeConnectHandler>
inline void asio_handler_invoke(Function& function,
range_connect_op<Protocol ASIO_SVC_TARG, EndpointSequence,
ConnectCondition, RangeConnectHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename Protocol
ASIO_SVC_TPARAM, typename EndpointSequence,
typename ConnectCondition, typename RangeConnectHandler>
inline void asio_handler_invoke(const Function& function,
range_connect_op<Protocol ASIO_SVC_TARG, EndpointSequence,
ConnectCondition, RangeConnectHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Protocol ASIO_SVC_TPARAM, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
class iterator_connect_op : base_from_connect_condition<ConnectCondition>
{
public:
iterator_connect_op(basic_socket<Protocol ASIO_SVC_TARG>& sock,
const Iterator& begin, const Iterator& end,
const ConnectCondition& connect_condition,
IteratorConnectHandler& handler)
: base_from_connect_condition<ConnectCondition>(connect_condition),
socket_(sock),
iter_(begin),
end_(end),
start_(0),
handler_(ASIO_MOVE_CAST(IteratorConnectHandler)(handler))
{
}
#if defined(ASIO_HAS_MOVE)
iterator_connect_op(const iterator_connect_op& other)
: base_from_connect_condition<ConnectCondition>(other),
socket_(other.socket_),
iter_(other.iter_),
end_(other.end_),
start_(other.start_),
handler_(other.handler_)
{
}
iterator_connect_op(iterator_connect_op&& other)
: base_from_connect_condition<ConnectCondition>(other),
socket_(other.socket_),
iter_(other.iter_),
end_(other.end_),
start_(other.start_),
handler_(ASIO_MOVE_CAST(IteratorConnectHandler)(other.handler_))
{
}
#endif // defined(ASIO_HAS_MOVE)
void operator()(asio::error_code ec, int start = 0)
{
switch (start_ = start)
{
case 1:
for (;;)
{
this->check_condition(ec, iter_, end_);
if (iter_ != end_)
{
socket_.close(ec);
socket_.async_connect(*iter_,
ASIO_MOVE_CAST(iterator_connect_op)(*this));
return;
}
if (start)
{
ec = asio::error::not_found;
asio::post(socket_.get_executor(),
detail::bind_handler(
ASIO_MOVE_CAST(iterator_connect_op)(*this), ec));
return;
}
default:
if (iter_ == end_)
break;
if (!socket_.is_open())
{
ec = asio::error::operation_aborted;
break;
}
if (!ec)
break;
++iter_;
}
handler_(static_cast<const asio::error_code&>(ec),
static_cast<const Iterator&>(iter_));
}
}
//private:
basic_socket<Protocol ASIO_SVC_TARG>& socket_;
Iterator iter_;
Iterator end_;
int start_;
IteratorConnectHandler handler_;
};
template <typename Protocol ASIO_SVC_TPARAM, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
inline void* asio_handler_allocate(std::size_t size,
iterator_connect_op<Protocol ASIO_SVC_TARG, Iterator,
ConnectCondition, IteratorConnectHandler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename Protocol ASIO_SVC_TPARAM, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
iterator_connect_op<Protocol ASIO_SVC_TARG, Iterator,
ConnectCondition, IteratorConnectHandler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename Protocol ASIO_SVC_TPARAM, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
inline bool asio_handler_is_continuation(
iterator_connect_op<Protocol ASIO_SVC_TARG, Iterator,
ConnectCondition, IteratorConnectHandler>* this_handler)
{
return asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename Protocol
ASIO_SVC_TPARAM, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
inline void asio_handler_invoke(Function& function,
iterator_connect_op<Protocol ASIO_SVC_TARG, Iterator,
ConnectCondition, IteratorConnectHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename Protocol
ASIO_SVC_TPARAM, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
inline void asio_handler_invoke(const Function& function,
iterator_connect_op<Protocol ASIO_SVC_TARG, Iterator,
ConnectCondition, IteratorConnectHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename Protocol ASIO_SVC_TPARAM,
typename EndpointSequence, typename ConnectCondition,
typename RangeConnectHandler, typename Allocator>
struct associated_allocator<
detail::range_connect_op<Protocol ASIO_SVC_TARG,
EndpointSequence, ConnectCondition, RangeConnectHandler>,
Allocator>
{
typedef typename associated_allocator<
RangeConnectHandler, Allocator>::type type;
static type get(
const detail::range_connect_op<Protocol ASIO_SVC_TARG,
EndpointSequence, ConnectCondition, RangeConnectHandler>& h,
const Allocator& a = Allocator()) ASIO_NOEXCEPT
{
return associated_allocator<RangeConnectHandler,
Allocator>::get(h.handler_, a);
}
};
template <typename Protocol ASIO_SVC_TPARAM,
typename EndpointSequence, typename ConnectCondition,
typename RangeConnectHandler, typename Executor>
struct associated_executor<
detail::range_connect_op<Protocol ASIO_SVC_TARG,
EndpointSequence, ConnectCondition, RangeConnectHandler>,
Executor>
{
typedef typename associated_executor<
RangeConnectHandler, Executor>::type type;
static type get(
const detail::range_connect_op<Protocol ASIO_SVC_TARG,
EndpointSequence, ConnectCondition, RangeConnectHandler>& h,
const Executor& ex = Executor()) ASIO_NOEXCEPT
{
return associated_executor<RangeConnectHandler,
Executor>::get(h.handler_, ex);
}
};
template <typename Protocol ASIO_SVC_TPARAM,
typename Iterator, typename ConnectCondition,
typename IteratorConnectHandler, typename Allocator>
struct associated_allocator<
detail::iterator_connect_op<Protocol ASIO_SVC_TARG, Iterator,
ConnectCondition, IteratorConnectHandler>,
Allocator>
{
typedef typename associated_allocator<
IteratorConnectHandler, Allocator>::type type;
static type get(
const detail::iterator_connect_op<Protocol ASIO_SVC_TARG,
Iterator, ConnectCondition, IteratorConnectHandler>& h,
const Allocator& a = Allocator()) ASIO_NOEXCEPT
{
return associated_allocator<IteratorConnectHandler,
Allocator>::get(h.handler_, a);
}
};
template <typename Protocol ASIO_SVC_TPARAM,
typename Iterator, typename ConnectCondition,
typename IteratorConnectHandler, typename Executor>
struct associated_executor<
detail::iterator_connect_op<Protocol ASIO_SVC_TARG, Iterator,
ConnectCondition, IteratorConnectHandler>,
Executor>
{
typedef typename associated_executor<
IteratorConnectHandler, Executor>::type type;
static type get(
const detail::iterator_connect_op<Protocol ASIO_SVC_TARG,
Iterator, ConnectCondition, IteratorConnectHandler>& h,
const Executor& ex = Executor()) ASIO_NOEXCEPT
{
return associated_executor<IteratorConnectHandler,
Executor>::get(h.handler_, ex);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename Protocol ASIO_SVC_TPARAM,
typename EndpointSequence, typename RangeConnectHandler>
inline ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
void (asio::error_code, typename Protocol::endpoint))
async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
const EndpointSequence& endpoints,
ASIO_MOVE_ARG(RangeConnectHandler) handler,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type*)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a RangeConnectHandler.
ASIO_RANGE_CONNECT_HANDLER_CHECK(
RangeConnectHandler, handler, typename Protocol::endpoint) type_check;
async_completion<RangeConnectHandler,
void (asio::error_code, typename Protocol::endpoint)>
init(handler);
detail::range_connect_op<Protocol ASIO_SVC_TARG, EndpointSequence,
detail::default_connect_condition,
ASIO_HANDLER_TYPE(RangeConnectHandler,
void (asio::error_code, typename Protocol::endpoint))>(s,
endpoints, detail::default_connect_condition(),
init.completion_handler)(asio::error_code(), 1);
return init.result.get();
}
#if !defined(ASIO_NO_DEPRECATED)
template <typename Protocol ASIO_SVC_TPARAM,
typename Iterator, typename IteratorConnectHandler>
inline ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (asio::error_code, Iterator))
async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
Iterator begin, ASIO_MOVE_ARG(IteratorConnectHandler) handler,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a IteratorConnectHandler.
ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
IteratorConnectHandler, handler, Iterator) type_check;
async_completion<IteratorConnectHandler,
void (asio::error_code, Iterator)> init(handler);
detail::iterator_connect_op<Protocol ASIO_SVC_TARG, Iterator,
detail::default_connect_condition, ASIO_HANDLER_TYPE(
IteratorConnectHandler, void (asio::error_code, Iterator))>(s,
begin, Iterator(), detail::default_connect_condition(),
init.completion_handler)(asio::error_code(), 1);
return init.result.get();
}
#endif // !defined(ASIO_NO_DEPRECATED)
template <typename Protocol ASIO_SVC_TPARAM,
typename Iterator, typename IteratorConnectHandler>
inline ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (asio::error_code, Iterator))
async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
Iterator begin, Iterator end,
ASIO_MOVE_ARG(IteratorConnectHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a IteratorConnectHandler.
ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
IteratorConnectHandler, handler, Iterator) type_check;
async_completion<IteratorConnectHandler,
void (asio::error_code, Iterator)> init(handler);
detail::iterator_connect_op<Protocol ASIO_SVC_TARG, Iterator,
detail::default_connect_condition, ASIO_HANDLER_TYPE(
IteratorConnectHandler, void (asio::error_code, Iterator))>(s,
begin, end, detail::default_connect_condition(),
init.completion_handler)(asio::error_code(), 1);
return init.result.get();
}
template <typename Protocol ASIO_SVC_TPARAM, typename EndpointSequence,
typename ConnectCondition, typename RangeConnectHandler>
inline ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
void (asio::error_code, typename Protocol::endpoint))
async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
const EndpointSequence& endpoints, ConnectCondition connect_condition,
ASIO_MOVE_ARG(RangeConnectHandler) handler,
typename enable_if<is_endpoint_sequence<
EndpointSequence>::value>::type*)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a RangeConnectHandler.
ASIO_RANGE_CONNECT_HANDLER_CHECK(
RangeConnectHandler, handler, typename Protocol::endpoint) type_check;
async_completion<RangeConnectHandler,
void (asio::error_code, typename Protocol::endpoint)>
init(handler);
detail::range_connect_op<Protocol ASIO_SVC_TARG, EndpointSequence,
ConnectCondition, ASIO_HANDLER_TYPE(RangeConnectHandler,
void (asio::error_code, typename Protocol::endpoint))>(s,
endpoints, connect_condition, init.completion_handler)(
asio::error_code(), 1);
return init.result.get();
}
#if !defined(ASIO_NO_DEPRECATED)
template <typename Protocol ASIO_SVC_TPARAM, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
inline ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (asio::error_code, Iterator))
async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
Iterator begin, ConnectCondition connect_condition,
ASIO_MOVE_ARG(IteratorConnectHandler) handler,
typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a IteratorConnectHandler.
ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
IteratorConnectHandler, handler, Iterator) type_check;
async_completion<IteratorConnectHandler,
void (asio::error_code, Iterator)> init(handler);
detail::iterator_connect_op<Protocol ASIO_SVC_TARG, Iterator,
ConnectCondition, ASIO_HANDLER_TYPE(
IteratorConnectHandler, void (asio::error_code, Iterator))>(s,
begin, Iterator(), connect_condition, init.completion_handler)(
asio::error_code(), 1);
return init.result.get();
}
#endif // !defined(ASIO_NO_DEPRECATED)
template <typename Protocol ASIO_SVC_TPARAM, typename Iterator,
typename ConnectCondition, typename IteratorConnectHandler>
inline ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (asio::error_code, Iterator))
async_connect(basic_socket<Protocol ASIO_SVC_TARG>& s,
Iterator begin, Iterator end, ConnectCondition connect_condition,
ASIO_MOVE_ARG(IteratorConnectHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a IteratorConnectHandler.
ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
IteratorConnectHandler, handler, Iterator) type_check;
async_completion<IteratorConnectHandler,
void (asio::error_code, Iterator)> init(handler);
detail::iterator_connect_op<Protocol ASIO_SVC_TARG, Iterator,
ConnectCondition, ASIO_HANDLER_TYPE(
IteratorConnectHandler, void (asio::error_code, Iterator))>(s,
begin, end, connect_condition, init.completion_handler)(
asio::error_code(), 1);
return init.result.get();
}
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_CONNECT_HPP

View File

@ -0,0 +1,77 @@
//
// impl/defer.hpp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_DEFER_HPP
#define ASIO_IMPL_DEFER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#include "asio/associated_allocator.hpp"
#include "asio/associated_executor.hpp"
#include "asio/detail/work_dispatcher.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
template <typename CompletionToken>
ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer(
ASIO_MOVE_ARG(CompletionToken) token)
{
typedef ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
async_completion<CompletionToken, void()> init(token);
typename associated_executor<handler>::type ex(
(get_associated_executor)(init.completion_handler));
typename associated_allocator<handler>::type alloc(
(get_associated_allocator)(init.completion_handler));
ex.defer(ASIO_MOVE_CAST(handler)(init.completion_handler), alloc);
return init.result.get();
}
template <typename Executor, typename CompletionToken>
ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer(
const Executor& ex, ASIO_MOVE_ARG(CompletionToken) token,
typename enable_if<is_executor<Executor>::value>::type*)
{
typedef ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
async_completion<CompletionToken, void()> init(token);
typename associated_allocator<handler>::type alloc(
(get_associated_allocator)(init.completion_handler));
ex.defer(detail::work_dispatcher<handler>(init.completion_handler), alloc);
return init.result.get();
}
template <typename ExecutionContext, typename CompletionToken>
inline ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer(
ExecutionContext& ctx, ASIO_MOVE_ARG(CompletionToken) token,
typename enable_if<is_convertible<
ExecutionContext&, execution_context&>::value>::type*)
{
return (defer)(ctx.get_executor(),
ASIO_MOVE_CAST(CompletionToken)(token));
}
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_DEFER_HPP

View File

@ -0,0 +1,78 @@
//
// impl/dispatch.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_DISPATCH_HPP
#define ASIO_IMPL_DISPATCH_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#include "asio/associated_allocator.hpp"
#include "asio/associated_executor.hpp"
#include "asio/detail/work_dispatcher.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
template <typename CompletionToken>
ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch(
ASIO_MOVE_ARG(CompletionToken) token)
{
typedef ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
async_completion<CompletionToken, void()> init(token);
typename associated_executor<handler>::type ex(
(get_associated_executor)(init.completion_handler));
typename associated_allocator<handler>::type alloc(
(get_associated_allocator)(init.completion_handler));
ex.dispatch(ASIO_MOVE_CAST(handler)(init.completion_handler), alloc);
return init.result.get();
}
template <typename Executor, typename CompletionToken>
ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch(
const Executor& ex, ASIO_MOVE_ARG(CompletionToken) token,
typename enable_if<is_executor<Executor>::value>::type*)
{
typedef ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
async_completion<CompletionToken, void()> init(token);
typename associated_allocator<handler>::type alloc(
(get_associated_allocator)(init.completion_handler));
ex.dispatch(detail::work_dispatcher<handler>(
init.completion_handler), alloc);
return init.result.get();
}
template <typename ExecutionContext, typename CompletionToken>
inline ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch(
ExecutionContext& ctx, ASIO_MOVE_ARG(CompletionToken) token,
typename enable_if<is_convertible<
ExecutionContext&, execution_context&>::value>::type*)
{
return (dispatch)(ctx.get_executor(),
ASIO_MOVE_CAST(CompletionToken)(token));
}
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_DISPATCH_HPP

View File

@ -0,0 +1,107 @@
//
// impl/execution_context.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_EXECUTION_CONTEXT_HPP
#define ASIO_IMPL_EXECUTION_CONTEXT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/handler_type_requirements.hpp"
#include "asio/detail/scoped_ptr.hpp"
#include "asio/detail/service_registry.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
template <typename Service>
inline Service& use_service(execution_context& e)
{
// Check that Service meets the necessary type requirements.
(void)static_cast<execution_context::service*>(static_cast<Service*>(0));
return e.service_registry_->template use_service<Service>();
}
#if !defined(GENERATING_DOCUMENTATION)
# if defined(ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Service, typename... Args>
Service& make_service(execution_context& e, ASIO_MOVE_ARG(Args)... args)
{
detail::scoped_ptr<Service> svc(
new Service(e, ASIO_MOVE_CAST(Args)(args)...));
e.service_registry_->template add_service<Service>(svc.get());
Service& result = *svc;
svc.release();
return result;
}
# else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Service>
Service& make_service(execution_context& e)
{
detail::scoped_ptr<Service> svc(new Service(e));
e.service_registry_->template add_service<Service>(svc.get());
Service& result = *svc;
svc.release();
return result;
}
#define ASIO_PRIVATE_MAKE_SERVICE_DEF(n) \
template <typename Service, ASIO_VARIADIC_TPARAMS(n)> \
Service& make_service(execution_context& e, \
ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
detail::scoped_ptr<Service> svc( \
new Service(e, ASIO_VARIADIC_MOVE_ARGS(n))); \
e.service_registry_->template add_service<Service>(svc.get()); \
Service& result = *svc; \
svc.release(); \
return result; \
} \
/**/
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_MAKE_SERVICE_DEF)
#undef ASIO_PRIVATE_MAKE_SERVICE_DEF
# endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename Service>
inline void add_service(execution_context& e, Service* svc)
{
// Check that Service meets the necessary type requirements.
(void)static_cast<execution_context::service*>(static_cast<Service*>(0));
e.service_registry_->template add_service<Service>(svc);
}
template <typename Service>
inline bool has_service(execution_context& e)
{
// Check that Service meets the necessary type requirements.
(void)static_cast<execution_context::service*>(static_cast<Service*>(0));
return e.service_registry_->template has_service<Service>();
}
inline execution_context& execution_context::service::context()
{
return owner_;
}
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_EXECUTION_CONTEXT_HPP

View File

@ -0,0 +1,386 @@
//
// impl/executor.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_EXECUTOR_HPP
#define ASIO_IMPL_EXECUTOR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#include "asio/detail/atomic_count.hpp"
#include "asio/detail/executor_op.hpp"
#include "asio/detail/global.hpp"
#include "asio/detail/memory.hpp"
#include "asio/detail/recycling_allocator.hpp"
#include "asio/executor.hpp"
#include "asio/system_executor.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
#if !defined(GENERATING_DOCUMENTATION)
#if defined(ASIO_HAS_MOVE)
// Lightweight, move-only function object wrapper.
class executor::function
{
public:
template <typename F, typename Alloc>
explicit function(F f, const Alloc& a)
{
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<F, Alloc> op;
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
op_ = new (p.v) op(ASIO_MOVE_CAST(F)(f), a);
p.v = 0;
}
function(function&& other)
: op_(other.op_)
{
other.op_ = 0;
}
~function()
{
if (op_)
op_->destroy();
}
void operator()()
{
if (op_)
{
detail::scheduler_operation* op = op_;
op_ = 0;
op->complete(this, asio::error_code(), 0);
}
}
private:
detail::scheduler_operation* op_;
};
#else // defined(ASIO_HAS_MOVE)
// Not so lightweight, copyable function object wrapper.
class executor::function
{
public:
template <typename F, typename Alloc>
explicit function(const F& f, const Alloc&)
: impl_(new impl<F>(f))
{
}
void operator()()
{
impl_->invoke_(impl_.get());
}
private:
// Base class for polymorphic function implementations.
struct impl_base
{
void (*invoke_)(impl_base*);
};
// Polymorphic function implementation.
template <typename F>
struct impl : impl_base
{
impl(const F& f)
: function_(f)
{
invoke_ = &function::invoke<F>;
}
F function_;
};
// Helper to invoke a function.
template <typename F>
static void invoke(impl_base* i)
{
static_cast<impl<F>*>(i)->function_();
}
detail::shared_ptr<impl_base> impl_;
};
#endif // defined(ASIO_HAS_MOVE)
// Default polymorphic allocator implementation.
template <typename Executor, typename Allocator>
class executor::impl
: public executor::impl_base
{
public:
typedef ASIO_REBIND_ALLOC(Allocator, impl) allocator_type;
static impl_base* create(const Executor& e, Allocator a = Allocator())
{
raw_mem mem(a);
impl* p = new (mem.ptr_) impl(e, a);
mem.ptr_ = 0;
return p;
}
impl(const Executor& e, const Allocator& a) ASIO_NOEXCEPT
: impl_base(false),
ref_count_(1),
executor_(e),
allocator_(a)
{
}
impl_base* clone() const ASIO_NOEXCEPT
{
++ref_count_;
return const_cast<impl_base*>(static_cast<const impl_base*>(this));
}
void destroy() ASIO_NOEXCEPT
{
if (--ref_count_ == 0)
{
allocator_type alloc(allocator_);
impl* p = this;
p->~impl();
alloc.deallocate(p, 1);
}
}
void on_work_started() ASIO_NOEXCEPT
{
executor_.on_work_started();
}
void on_work_finished() ASIO_NOEXCEPT
{
executor_.on_work_finished();
}
execution_context& context() ASIO_NOEXCEPT
{
return executor_.context();
}
void dispatch(ASIO_MOVE_ARG(function) f)
{
executor_.dispatch(ASIO_MOVE_CAST(function)(f), allocator_);
}
void post(ASIO_MOVE_ARG(function) f)
{
executor_.post(ASIO_MOVE_CAST(function)(f), allocator_);
}
void defer(ASIO_MOVE_ARG(function) f)
{
executor_.defer(ASIO_MOVE_CAST(function)(f), allocator_);
}
type_id_result_type target_type() const ASIO_NOEXCEPT
{
return type_id<Executor>();
}
void* target() ASIO_NOEXCEPT
{
return &executor_;
}
const void* target() const ASIO_NOEXCEPT
{
return &executor_;
}
bool equals(const impl_base* e) const ASIO_NOEXCEPT
{
if (this == e)
return true;
if (target_type() != e->target_type())
return false;
return executor_ == *static_cast<const Executor*>(e->target());
}
private:
mutable detail::atomic_count ref_count_;
Executor executor_;
Allocator allocator_;
struct raw_mem
{
allocator_type allocator_;
impl* ptr_;
explicit raw_mem(const Allocator& a)
: allocator_(a),
ptr_(allocator_.allocate(1))
{
}
~raw_mem()
{
if (ptr_)
allocator_.deallocate(ptr_, 1);
}
private:
// Disallow copying and assignment.
raw_mem(const raw_mem&);
raw_mem operator=(const raw_mem&);
};
};
// Polymorphic allocator specialisation for system_executor.
template <typename Allocator>
class executor::impl<system_executor, Allocator>
: public executor::impl_base
{
public:
static impl_base* create(const system_executor&,
const Allocator& = Allocator())
{
return &detail::global<impl<system_executor, std::allocator<void> > >();
}
impl()
: impl_base(true)
{
}
impl_base* clone() const ASIO_NOEXCEPT
{
return const_cast<impl_base*>(static_cast<const impl_base*>(this));
}
void destroy() ASIO_NOEXCEPT
{
}
void on_work_started() ASIO_NOEXCEPT
{
executor_.on_work_started();
}
void on_work_finished() ASIO_NOEXCEPT
{
executor_.on_work_finished();
}
execution_context& context() ASIO_NOEXCEPT
{
return executor_.context();
}
void dispatch(ASIO_MOVE_ARG(function) f)
{
executor_.dispatch(ASIO_MOVE_CAST(function)(f), allocator_);
}
void post(ASIO_MOVE_ARG(function) f)
{
executor_.post(ASIO_MOVE_CAST(function)(f), allocator_);
}
void defer(ASIO_MOVE_ARG(function) f)
{
executor_.defer(ASIO_MOVE_CAST(function)(f), allocator_);
}
type_id_result_type target_type() const ASIO_NOEXCEPT
{
return type_id<system_executor>();
}
void* target() ASIO_NOEXCEPT
{
return &executor_;
}
const void* target() const ASIO_NOEXCEPT
{
return &executor_;
}
bool equals(const impl_base* e) const ASIO_NOEXCEPT
{
return this == e;
}
private:
system_executor executor_;
Allocator allocator_;
};
template <typename Executor>
executor::executor(Executor e)
: impl_(impl<Executor, std::allocator<void> >::create(e))
{
}
template <typename Executor, typename Allocator>
executor::executor(allocator_arg_t, const Allocator& a, Executor e)
: impl_(impl<Executor, Allocator>::create(e, a))
{
}
template <typename Function, typename Allocator>
void executor::dispatch(ASIO_MOVE_ARG(Function) f,
const Allocator& a) const
{
impl_base* i = get_impl();
if (i->fast_dispatch_)
system_executor().dispatch(ASIO_MOVE_CAST(Function)(f), a);
else
i->dispatch(function(ASIO_MOVE_CAST(Function)(f), a));
}
template <typename Function, typename Allocator>
void executor::post(ASIO_MOVE_ARG(Function) f,
const Allocator& a) const
{
get_impl()->post(function(ASIO_MOVE_CAST(Function)(f), a));
}
template <typename Function, typename Allocator>
void executor::defer(ASIO_MOVE_ARG(Function) f,
const Allocator& a) const
{
get_impl()->defer(function(ASIO_MOVE_CAST(Function)(f), a));
}
template <typename Executor>
Executor* executor::target() ASIO_NOEXCEPT
{
return impl_ && impl_->target_type() == type_id<Executor>()
? static_cast<Executor*>(impl_->target()) : 0;
}
template <typename Executor>
const Executor* executor::target() const ASIO_NOEXCEPT
{
return impl_ && impl_->target_type() == type_id<Executor>()
? static_cast<Executor*>(impl_->target()) : 0;
}
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_EXECUTOR_HPP

View File

@ -0,0 +1,343 @@
//
// impl/io_context.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_IO_CONTEXT_HPP
#define ASIO_IMPL_IO_CONTEXT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/completion_handler.hpp"
#include "asio/detail/executor_op.hpp"
#include "asio/detail/fenced_block.hpp"
#include "asio/detail/handler_type_requirements.hpp"
#include "asio/detail/recycling_allocator.hpp"
#include "asio/detail/service_registry.hpp"
#include "asio/detail/throw_error.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
template <typename Service>
inline Service& use_service(io_context& ioc)
{
// Check that Service meets the necessary type requirements.
(void)static_cast<execution_context::service*>(static_cast<Service*>(0));
(void)static_cast<const execution_context::id*>(&Service::id);
return ioc.service_registry_->template use_service<Service>(ioc);
}
template <>
inline detail::io_context_impl& use_service<detail::io_context_impl>(
io_context& ioc)
{
return ioc.impl_;
}
} // namespace asio
#include "asio/detail/pop_options.hpp"
#if defined(ASIO_HAS_IOCP)
# include "asio/detail/win_iocp_io_context.hpp"
#else
# include "asio/detail/scheduler.hpp"
#endif
#include "asio/detail/push_options.hpp"
namespace asio {
inline io_context::executor_type
io_context::get_executor() ASIO_NOEXCEPT
{
return executor_type(*this);
}
#if defined(ASIO_HAS_CHRONO)
template <typename Rep, typename Period>
std::size_t io_context::run_for(
const chrono::duration<Rep, Period>& rel_time)
{
return this->run_until(chrono::steady_clock::now() + rel_time);
}
template <typename Clock, typename Duration>
std::size_t io_context::run_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
std::size_t n = 0;
while (this->run_one_until(abs_time))
if (n != (std::numeric_limits<std::size_t>::max)())
++n;
return n;
}
template <typename Rep, typename Period>
std::size_t io_context::run_one_for(
const chrono::duration<Rep, Period>& rel_time)
{
return this->run_one_until(chrono::steady_clock::now() + rel_time);
}
template <typename Clock, typename Duration>
std::size_t io_context::run_one_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
typename Clock::time_point now = Clock::now();
while (now < abs_time)
{
typename Clock::duration rel_time = abs_time - now;
if (rel_time > chrono::seconds(1))
rel_time = chrono::seconds(1);
asio::error_code ec;
std::size_t s = impl_.wait_one(
static_cast<long>(chrono::duration_cast<
chrono::microseconds>(rel_time).count()), ec);
asio::detail::throw_error(ec);
if (s || impl_.stopped())
return s;
now = Clock::now();
}
return 0;
}
#endif // defined(ASIO_HAS_CHRONO)
#if !defined(ASIO_NO_DEPRECATED)
inline void io_context::reset()
{
restart();
}
template <typename LegacyCompletionHandler>
ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ())
io_context::dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a LegacyCompletionHandler.
ASIO_LEGACY_COMPLETION_HANDLER_CHECK(
LegacyCompletionHandler, handler) type_check;
async_completion<LegacyCompletionHandler, void ()> init(handler);
if (impl_.can_dispatch())
{
detail::fenced_block b(detail::fenced_block::full);
asio_handler_invoke_helpers::invoke(
init.completion_handler, init.completion_handler);
}
else
{
// Allocate and construct an operation to wrap the handler.
typedef detail::completion_handler<
typename handler_type<LegacyCompletionHandler, void ()>::type> op;
typename op::ptr p = { detail::addressof(init.completion_handler),
op::ptr::allocate(init.completion_handler), 0 };
p.p = new (p.v) op(init.completion_handler);
ASIO_HANDLER_CREATION((*this, *p.p,
"io_context", this, 0, "dispatch"));
impl_.do_dispatch(p.p);
p.v = p.p = 0;
}
return init.result.get();
}
template <typename LegacyCompletionHandler>
ASIO_INITFN_RESULT_TYPE(LegacyCompletionHandler, void ())
io_context::post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a LegacyCompletionHandler.
ASIO_LEGACY_COMPLETION_HANDLER_CHECK(
LegacyCompletionHandler, handler) type_check;
async_completion<LegacyCompletionHandler, void ()> init(handler);
bool is_continuation =
asio_handler_cont_helpers::is_continuation(init.completion_handler);
// Allocate and construct an operation to wrap the handler.
typedef detail::completion_handler<
typename handler_type<LegacyCompletionHandler, void ()>::type> op;
typename op::ptr p = { detail::addressof(init.completion_handler),
op::ptr::allocate(init.completion_handler), 0 };
p.p = new (p.v) op(init.completion_handler);
ASIO_HANDLER_CREATION((*this, *p.p,
"io_context", this, 0, "post"));
impl_.post_immediate_completion(p.p, is_continuation);
p.v = p.p = 0;
return init.result.get();
}
template <typename Handler>
#if defined(GENERATING_DOCUMENTATION)
unspecified
#else
inline detail::wrapped_handler<io_context&, Handler>
#endif
io_context::wrap(Handler handler)
{
return detail::wrapped_handler<io_context&, Handler>(*this, handler);
}
#endif // !defined(ASIO_NO_DEPRECATED)
inline io_context&
io_context::executor_type::context() const ASIO_NOEXCEPT
{
return io_context_;
}
inline void
io_context::executor_type::on_work_started() const ASIO_NOEXCEPT
{
io_context_.impl_.work_started();
}
inline void
io_context::executor_type::on_work_finished() const ASIO_NOEXCEPT
{
io_context_.impl_.work_finished();
}
template <typename Function, typename Allocator>
void io_context::executor_type::dispatch(
ASIO_MOVE_ARG(Function) f, const Allocator& a) const
{
typedef typename decay<Function>::type function_type;
// Invoke immediately if we are already inside the thread pool.
if (io_context_.impl_.can_dispatch())
{
// Make a local, non-const copy of the function.
function_type tmp(ASIO_MOVE_CAST(Function)(f));
detail::fenced_block b(detail::fenced_block::full);
asio_handler_invoke_helpers::invoke(tmp, tmp);
return;
}
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator, detail::operation> op;
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
ASIO_HANDLER_CREATION((this->context(), *p.p,
"io_context", &this->context(), 0, "post"));
io_context_.impl_.post_immediate_completion(p.p, false);
p.v = p.p = 0;
}
template <typename Function, typename Allocator>
void io_context::executor_type::post(
ASIO_MOVE_ARG(Function) f, const Allocator& a) const
{
typedef typename decay<Function>::type function_type;
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator, detail::operation> op;
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
ASIO_HANDLER_CREATION((this->context(), *p.p,
"io_context", &this->context(), 0, "post"));
io_context_.impl_.post_immediate_completion(p.p, false);
p.v = p.p = 0;
}
template <typename Function, typename Allocator>
void io_context::executor_type::defer(
ASIO_MOVE_ARG(Function) f, const Allocator& a) const
{
typedef typename decay<Function>::type function_type;
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator, detail::operation> op;
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
ASIO_HANDLER_CREATION((this->context(), *p.p,
"io_context", &this->context(), 0, "defer"));
io_context_.impl_.post_immediate_completion(p.p, true);
p.v = p.p = 0;
}
inline bool
io_context::executor_type::running_in_this_thread() const ASIO_NOEXCEPT
{
return io_context_.impl_.can_dispatch();
}
#if !defined(ASIO_NO_DEPRECATED)
inline io_context::work::work(asio::io_context& io_context)
: io_context_impl_(io_context.impl_)
{
io_context_impl_.work_started();
}
inline io_context::work::work(const work& other)
: io_context_impl_(other.io_context_impl_)
{
io_context_impl_.work_started();
}
inline io_context::work::~work()
{
io_context_impl_.work_finished();
}
inline asio::io_context& io_context::work::get_io_context()
{
return static_cast<asio::io_context&>(io_context_impl_.context());
}
inline asio::io_context& io_context::work::get_io_service()
{
return static_cast<asio::io_context&>(io_context_impl_.context());
}
#endif // !defined(ASIO_NO_DEPRECATED)
inline asio::io_context& io_context::service::get_io_context()
{
return static_cast<asio::io_context&>(context());
}
#if !defined(ASIO_NO_DEPRECATED)
inline asio::io_context& io_context::service::get_io_service()
{
return static_cast<asio::io_context&>(context());
}
#endif // !defined(ASIO_NO_DEPRECATED)
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_IO_CONTEXT_HPP

View File

@ -0,0 +1,77 @@
//
// impl/post.hpp
// ~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_POST_HPP
#define ASIO_IMPL_POST_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#include "asio/associated_allocator.hpp"
#include "asio/associated_executor.hpp"
#include "asio/detail/work_dispatcher.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
template <typename CompletionToken>
ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post(
ASIO_MOVE_ARG(CompletionToken) token)
{
typedef ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
async_completion<CompletionToken, void()> init(token);
typename associated_executor<handler>::type ex(
(get_associated_executor)(init.completion_handler));
typename associated_allocator<handler>::type alloc(
(get_associated_allocator)(init.completion_handler));
ex.post(ASIO_MOVE_CAST(handler)(init.completion_handler), alloc);
return init.result.get();
}
template <typename Executor, typename CompletionToken>
ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post(
const Executor& ex, ASIO_MOVE_ARG(CompletionToken) token,
typename enable_if<is_executor<Executor>::value>::type*)
{
typedef ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
async_completion<CompletionToken, void()> init(token);
typename associated_allocator<handler>::type alloc(
(get_associated_allocator)(init.completion_handler));
ex.post(detail::work_dispatcher<handler>(init.completion_handler), alloc);
return init.result.get();
}
template <typename ExecutionContext, typename CompletionToken>
inline ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post(
ExecutionContext& ctx, ASIO_MOVE_ARG(CompletionToken) token,
typename enable_if<is_convertible<
ExecutionContext&, execution_context&>::value>::type*)
{
return (post)(ctx.get_executor(),
ASIO_MOVE_CAST(CompletionToken)(token));
}
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_POST_HPP

View File

@ -0,0 +1,715 @@
//
// impl/read.hpp
// ~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_READ_HPP
#define ASIO_IMPL_READ_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <algorithm>
#include "asio/associated_allocator.hpp"
#include "asio/associated_executor.hpp"
#include "asio/buffer.hpp"
#include "asio/completion_condition.hpp"
#include "asio/detail/array_fwd.hpp"
#include "asio/detail/base_from_completion_cond.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/consuming_buffers.hpp"
#include "asio/detail/dependent_type.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_cont_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/handler_type_requirements.hpp"
#include "asio/detail/throw_error.hpp"
#include "asio/error.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail
{
template <typename SyncReadStream, typename MutableBufferSequence,
typename MutableBufferIterator, typename CompletionCondition>
std::size_t read_buffer_sequence(SyncReadStream& s,
const MutableBufferSequence& buffers, const MutableBufferIterator&,
CompletionCondition completion_condition, asio::error_code& ec)
{
ec = asio::error_code();
asio::detail::consuming_buffers<mutable_buffer,
MutableBufferSequence, MutableBufferIterator> tmp(buffers);
while (!tmp.empty())
{
if (std::size_t max_size = detail::adapt_completion_condition_result(
completion_condition(ec, tmp.total_consumed())))
tmp.consume(s.read_some(tmp.prepare(max_size), ec));
else
break;
}
return tmp.total_consumed();;
}
} // namespace detail
template <typename SyncReadStream, typename MutableBufferSequence,
typename CompletionCondition>
std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
CompletionCondition completion_condition, asio::error_code& ec,
typename enable_if<
is_mutable_buffer_sequence<MutableBufferSequence>::value
>::type*)
{
return detail::read_buffer_sequence(s, buffers,
asio::buffer_sequence_begin(buffers), completion_condition, ec);
}
template <typename SyncReadStream, typename MutableBufferSequence>
inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
typename enable_if<
is_mutable_buffer_sequence<MutableBufferSequence>::value
>::type*)
{
asio::error_code ec;
std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
asio::detail::throw_error(ec, "read");
return bytes_transferred;
}
template <typename SyncReadStream, typename MutableBufferSequence>
inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
asio::error_code& ec,
typename enable_if<
is_mutable_buffer_sequence<MutableBufferSequence>::value
>::type*)
{
return read(s, buffers, transfer_all(), ec);
}
template <typename SyncReadStream, typename MutableBufferSequence,
typename CompletionCondition>
inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
CompletionCondition completion_condition,
typename enable_if<
is_mutable_buffer_sequence<MutableBufferSequence>::value
>::type*)
{
asio::error_code ec;
std::size_t bytes_transferred = read(s, buffers, completion_condition, ec);
asio::detail::throw_error(ec, "read");
return bytes_transferred;
}
template <typename SyncReadStream, typename DynamicBuffer,
typename CompletionCondition>
std::size_t read(SyncReadStream& s,
ASIO_MOVE_ARG(DynamicBuffer) buffers,
CompletionCondition completion_condition, asio::error_code& ec,
typename enable_if<
is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
>::type*)
{
typename decay<DynamicBuffer>::type b(
ASIO_MOVE_CAST(DynamicBuffer)(buffers));
ec = asio::error_code();
std::size_t total_transferred = 0;
std::size_t max_size = detail::adapt_completion_condition_result(
completion_condition(ec, total_transferred));
std::size_t bytes_available = std::min<std::size_t>(
std::max<std::size_t>(512, b.capacity() - b.size()),
std::min<std::size_t>(max_size, b.max_size() - b.size()));
while (bytes_available > 0)
{
std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
b.commit(bytes_transferred);
total_transferred += bytes_transferred;
max_size = detail::adapt_completion_condition_result(
completion_condition(ec, total_transferred));
bytes_available = std::min<std::size_t>(
std::max<std::size_t>(512, b.capacity() - b.size()),
std::min<std::size_t>(max_size, b.max_size() - b.size()));
}
return total_transferred;
}
template <typename SyncReadStream, typename DynamicBuffer>
inline std::size_t read(SyncReadStream& s,
ASIO_MOVE_ARG(DynamicBuffer) buffers,
typename enable_if<
is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
>::type*)
{
asio::error_code ec;
std::size_t bytes_transferred = read(s,
ASIO_MOVE_CAST(DynamicBuffer)(buffers), transfer_all(), ec);
asio::detail::throw_error(ec, "read");
return bytes_transferred;
}
template <typename SyncReadStream, typename DynamicBuffer>
inline std::size_t read(SyncReadStream& s,
ASIO_MOVE_ARG(DynamicBuffer) buffers,
asio::error_code& ec,
typename enable_if<
is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
>::type*)
{
return read(s, ASIO_MOVE_CAST(DynamicBuffer)(buffers),
transfer_all(), ec);
}
template <typename SyncReadStream, typename DynamicBuffer,
typename CompletionCondition>
inline std::size_t read(SyncReadStream& s,
ASIO_MOVE_ARG(DynamicBuffer) buffers,
CompletionCondition completion_condition,
typename enable_if<
is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
>::type*)
{
asio::error_code ec;
std::size_t bytes_transferred = read(s,
ASIO_MOVE_CAST(DynamicBuffer)(buffers),
completion_condition, ec);
asio::detail::throw_error(ec, "read");
return bytes_transferred;
}
#if !defined(ASIO_NO_EXTENSIONS)
#if !defined(ASIO_NO_IOSTREAM)
template <typename SyncReadStream, typename Allocator,
typename CompletionCondition>
inline std::size_t read(SyncReadStream& s,
asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition, asio::error_code& ec)
{
return read(s, basic_streambuf_ref<Allocator>(b), completion_condition, ec);
}
template <typename SyncReadStream, typename Allocator>
inline std::size_t read(SyncReadStream& s,
asio::basic_streambuf<Allocator>& b)
{
return read(s, basic_streambuf_ref<Allocator>(b));
}
template <typename SyncReadStream, typename Allocator>
inline std::size_t read(SyncReadStream& s,
asio::basic_streambuf<Allocator>& b,
asio::error_code& ec)
{
return read(s, basic_streambuf_ref<Allocator>(b), ec);
}
template <typename SyncReadStream, typename Allocator,
typename CompletionCondition>
inline std::size_t read(SyncReadStream& s,
asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition)
{
return read(s, basic_streambuf_ref<Allocator>(b), completion_condition);
}
#endif // !defined(ASIO_NO_IOSTREAM)
#endif // !defined(ASIO_NO_EXTENSIONS)
namespace detail
{
template <typename AsyncReadStream, typename MutableBufferSequence,
typename MutableBufferIterator, typename CompletionCondition,
typename ReadHandler>
class read_op
: detail::base_from_completion_cond<CompletionCondition>
{
public:
read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,
CompletionCondition completion_condition, ReadHandler& handler)
: detail::base_from_completion_cond<
CompletionCondition>(completion_condition),
stream_(stream),
buffers_(buffers),
start_(0),
handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
{
}
#if defined(ASIO_HAS_MOVE)
read_op(const read_op& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
stream_(other.stream_),
buffers_(other.buffers_),
start_(other.start_),
handler_(other.handler_)
{
}
read_op(read_op&& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
stream_(other.stream_),
buffers_(other.buffers_),
start_(other.start_),
handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
{
}
#endif // defined(ASIO_HAS_MOVE)
void operator()(const asio::error_code& ec,
std::size_t bytes_transferred, int start = 0)
{
std::size_t max_size;
switch (start_ = start)
{
case 1:
max_size = this->check_for_completion(ec, buffers_.total_consumed());
do
{
stream_.async_read_some(buffers_.prepare(max_size),
ASIO_MOVE_CAST(read_op)(*this));
return; default:
buffers_.consume(bytes_transferred);
if ((!ec && bytes_transferred == 0) || buffers_.empty())
break;
max_size = this->check_for_completion(ec, buffers_.total_consumed());
} while (max_size > 0);
handler_(ec, buffers_.total_consumed());
}
}
//private:
AsyncReadStream& stream_;
asio::detail::consuming_buffers<mutable_buffer,
MutableBufferSequence, MutableBufferIterator> buffers_;
int start_;
ReadHandler handler_;
};
template <typename AsyncReadStream, typename MutableBufferSequence,
typename MutableBufferIterator, typename CompletionCondition,
typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
CompletionCondition, ReadHandler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename AsyncReadStream, typename MutableBufferSequence,
typename MutableBufferIterator, typename CompletionCondition,
typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
CompletionCondition, ReadHandler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename AsyncReadStream, typename MutableBufferSequence,
typename MutableBufferIterator, typename CompletionCondition,
typename ReadHandler>
inline bool asio_handler_is_continuation(
read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
CompletionCondition, ReadHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
: asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename AsyncReadStream,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler>
inline void asio_handler_invoke(Function& function,
read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
CompletionCondition, ReadHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename AsyncReadStream,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
CompletionCondition, ReadHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename AsyncReadStream, typename MutableBufferSequence,
typename MutableBufferIterator, typename CompletionCondition,
typename ReadHandler>
inline void start_read_buffer_sequence_op(AsyncReadStream& stream,
const MutableBufferSequence& buffers, const MutableBufferIterator&,
CompletionCondition completion_condition, ReadHandler& handler)
{
detail::read_op<AsyncReadStream, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>(
stream, buffers, completion_condition, handler)(
asio::error_code(), 0, 1);
}
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename AsyncReadStream, typename MutableBufferSequence,
typename MutableBufferIterator, typename CompletionCondition,
typename ReadHandler, typename Allocator>
struct associated_allocator<
detail::read_op<AsyncReadStream, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>,
Allocator>
{
typedef typename associated_allocator<ReadHandler, Allocator>::type type;
static type get(
const detail::read_op<AsyncReadStream, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>& h,
const Allocator& a = Allocator()) ASIO_NOEXCEPT
{
return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
}
};
template <typename AsyncReadStream, typename MutableBufferSequence,
typename MutableBufferIterator, typename CompletionCondition,
typename ReadHandler, typename Executor>
struct associated_executor<
detail::read_op<AsyncReadStream, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>,
Executor>
{
typedef typename associated_executor<ReadHandler, Executor>::type type;
static type get(
const detail::read_op<AsyncReadStream, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>& h,
const Executor& ex = Executor()) ASIO_NOEXCEPT
{
return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename AsyncReadStream, typename MutableBufferSequence,
typename CompletionCondition, typename ReadHandler>
inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (asio::error_code, std::size_t))
async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
CompletionCondition completion_condition,
ASIO_MOVE_ARG(ReadHandler) handler,
typename enable_if<
is_mutable_buffer_sequence<MutableBufferSequence>::value
>::type*)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
detail::start_read_buffer_sequence_op(s, buffers,
asio::buffer_sequence_begin(buffers), completion_condition,
init.completion_handler);
return init.result.get();
}
template <typename AsyncReadStream, typename MutableBufferSequence,
typename ReadHandler>
inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (asio::error_code, std::size_t))
async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
ASIO_MOVE_ARG(ReadHandler) handler,
typename enable_if<
is_mutable_buffer_sequence<MutableBufferSequence>::value
>::type*)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
detail::start_read_buffer_sequence_op(s, buffers,
asio::buffer_sequence_begin(buffers), transfer_all(),
init.completion_handler);
return init.result.get();
}
namespace detail
{
template <typename AsyncReadStream, typename DynamicBuffer,
typename CompletionCondition, typename ReadHandler>
class read_dynbuf_op
: detail::base_from_completion_cond<CompletionCondition>
{
public:
template <typename BufferSequence>
read_dynbuf_op(AsyncReadStream& stream,
ASIO_MOVE_ARG(BufferSequence) buffers,
CompletionCondition completion_condition, ReadHandler& handler)
: detail::base_from_completion_cond<
CompletionCondition>(completion_condition),
stream_(stream),
buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),
start_(0),
total_transferred_(0),
handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
{
}
#if defined(ASIO_HAS_MOVE)
read_dynbuf_op(const read_dynbuf_op& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
stream_(other.stream_),
buffers_(other.buffers_),
start_(other.start_),
total_transferred_(other.total_transferred_),
handler_(other.handler_)
{
}
read_dynbuf_op(read_dynbuf_op&& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
stream_(other.stream_),
buffers_(ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
start_(other.start_),
total_transferred_(other.total_transferred_),
handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
{
}
#endif // defined(ASIO_HAS_MOVE)
void operator()(const asio::error_code& ec,
std::size_t bytes_transferred, int start = 0)
{
std::size_t max_size, bytes_available;
switch (start_ = start)
{
case 1:
max_size = this->check_for_completion(ec, total_transferred_);
bytes_available = std::min<std::size_t>(
std::max<std::size_t>(512,
buffers_.capacity() - buffers_.size()),
std::min<std::size_t>(max_size,
buffers_.max_size() - buffers_.size()));
for (;;)
{
stream_.async_read_some(buffers_.prepare(bytes_available),
ASIO_MOVE_CAST(read_dynbuf_op)(*this));
return; default:
total_transferred_ += bytes_transferred;
buffers_.commit(bytes_transferred);
max_size = this->check_for_completion(ec, total_transferred_);
bytes_available = std::min<std::size_t>(
std::max<std::size_t>(512,
buffers_.capacity() - buffers_.size()),
std::min<std::size_t>(max_size,
buffers_.max_size() - buffers_.size()));
if ((!ec && bytes_transferred == 0) || bytes_available == 0)
break;
}
handler_(ec, static_cast<const std::size_t&>(total_transferred_));
}
}
//private:
AsyncReadStream& stream_;
DynamicBuffer buffers_;
int start_;
std::size_t total_transferred_;
ReadHandler handler_;
};
template <typename AsyncReadStream, typename DynamicBuffer,
typename CompletionCondition, typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
read_dynbuf_op<AsyncReadStream, DynamicBuffer,
CompletionCondition, ReadHandler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename AsyncReadStream, typename DynamicBuffer,
typename CompletionCondition, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
read_dynbuf_op<AsyncReadStream, DynamicBuffer,
CompletionCondition, ReadHandler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename AsyncReadStream, typename DynamicBuffer,
typename CompletionCondition, typename ReadHandler>
inline bool asio_handler_is_continuation(
read_dynbuf_op<AsyncReadStream, DynamicBuffer,
CompletionCondition, ReadHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
: asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename AsyncReadStream,
typename DynamicBuffer, typename CompletionCondition,
typename ReadHandler>
inline void asio_handler_invoke(Function& function,
read_dynbuf_op<AsyncReadStream, DynamicBuffer,
CompletionCondition, ReadHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename AsyncReadStream,
typename DynamicBuffer, typename CompletionCondition,
typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
read_dynbuf_op<AsyncReadStream, DynamicBuffer,
CompletionCondition, ReadHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename AsyncReadStream, typename DynamicBuffer,
typename CompletionCondition, typename ReadHandler, typename Allocator>
struct associated_allocator<
detail::read_dynbuf_op<AsyncReadStream,
DynamicBuffer, CompletionCondition, ReadHandler>,
Allocator>
{
typedef typename associated_allocator<ReadHandler, Allocator>::type type;
static type get(
const detail::read_dynbuf_op<AsyncReadStream,
DynamicBuffer, CompletionCondition, ReadHandler>& h,
const Allocator& a = Allocator()) ASIO_NOEXCEPT
{
return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
}
};
template <typename AsyncReadStream, typename DynamicBuffer,
typename CompletionCondition, typename ReadHandler, typename Executor>
struct associated_executor<
detail::read_dynbuf_op<AsyncReadStream,
DynamicBuffer, CompletionCondition, ReadHandler>,
Executor>
{
typedef typename associated_executor<ReadHandler, Executor>::type type;
static type get(
const detail::read_dynbuf_op<AsyncReadStream,
DynamicBuffer, CompletionCondition, ReadHandler>& h,
const Executor& ex = Executor()) ASIO_NOEXCEPT
{
return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename AsyncReadStream,
typename DynamicBuffer, typename ReadHandler>
inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (asio::error_code, std::size_t))
async_read(AsyncReadStream& s,
ASIO_MOVE_ARG(DynamicBuffer) buffers,
ASIO_MOVE_ARG(ReadHandler) handler,
typename enable_if<
is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
>::type*)
{
return async_read(s,
ASIO_MOVE_CAST(DynamicBuffer)(buffers),
transfer_all(), ASIO_MOVE_CAST(ReadHandler)(handler));
}
template <typename AsyncReadStream, typename DynamicBuffer,
typename CompletionCondition, typename ReadHandler>
inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (asio::error_code, std::size_t))
async_read(AsyncReadStream& s,
ASIO_MOVE_ARG(DynamicBuffer) buffers,
CompletionCondition completion_condition,
ASIO_MOVE_ARG(ReadHandler) handler,
typename enable_if<
is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
>::type*)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
detail::read_dynbuf_op<AsyncReadStream,
typename decay<DynamicBuffer>::type,
CompletionCondition, ASIO_HANDLER_TYPE(
ReadHandler, void (asio::error_code, std::size_t))>(
s, ASIO_MOVE_CAST(DynamicBuffer)(buffers),
completion_condition, init.completion_handler)(
asio::error_code(), 0, 1);
return init.result.get();
}
#if !defined(ASIO_NO_EXTENSIONS)
#if !defined(ASIO_NO_IOSTREAM)
template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (asio::error_code, std::size_t))
async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
ASIO_MOVE_ARG(ReadHandler) handler)
{
return async_read(s, basic_streambuf_ref<Allocator>(b),
ASIO_MOVE_CAST(ReadHandler)(handler));
}
template <typename AsyncReadStream, typename Allocator,
typename CompletionCondition, typename ReadHandler>
inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (asio::error_code, std::size_t))
async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
CompletionCondition completion_condition,
ASIO_MOVE_ARG(ReadHandler) handler)
{
return async_read(s, basic_streambuf_ref<Allocator>(b),
completion_condition, ASIO_MOVE_CAST(ReadHandler)(handler));
}
#endif // !defined(ASIO_NO_IOSTREAM)
#endif // !defined(ASIO_NO_EXTENSIONS)
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_READ_HPP

View File

@ -0,0 +1,640 @@
//
// impl/read_at.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_READ_AT_HPP
#define ASIO_IMPL_READ_AT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <algorithm>
#include "asio/associated_allocator.hpp"
#include "asio/associated_executor.hpp"
#include "asio/buffer.hpp"
#include "asio/completion_condition.hpp"
#include "asio/detail/array_fwd.hpp"
#include "asio/detail/base_from_completion_cond.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/consuming_buffers.hpp"
#include "asio/detail/dependent_type.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_cont_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/handler_type_requirements.hpp"
#include "asio/detail/throw_error.hpp"
#include "asio/error.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail
{
template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
typename MutableBufferIterator, typename CompletionCondition>
std::size_t read_at_buffer_sequence(SyncRandomAccessReadDevice& d,
uint64_t offset, const MutableBufferSequence& buffers,
const MutableBufferIterator&, CompletionCondition completion_condition,
asio::error_code& ec)
{
ec = asio::error_code();
asio::detail::consuming_buffers<mutable_buffer,
MutableBufferSequence, MutableBufferIterator> tmp(buffers);
while (!tmp.empty())
{
if (std::size_t max_size = detail::adapt_completion_condition_result(
completion_condition(ec, tmp.total_consumed())))
{
tmp.consume(d.read_some_at(offset + tmp.total_consumed(),
tmp.prepare(max_size), ec));
}
else
break;
}
return tmp.total_consumed();;
}
} // namespace detail
template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
typename CompletionCondition>
std::size_t read_at(SyncRandomAccessReadDevice& d,
uint64_t offset, const MutableBufferSequence& buffers,
CompletionCondition completion_condition, asio::error_code& ec)
{
return detail::read_at_buffer_sequence(d, offset, buffers,
asio::buffer_sequence_begin(buffers), completion_condition, ec);
}
template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
inline std::size_t read_at(SyncRandomAccessReadDevice& d,
uint64_t offset, const MutableBufferSequence& buffers)
{
asio::error_code ec;
std::size_t bytes_transferred = read_at(
d, offset, buffers, transfer_all(), ec);
asio::detail::throw_error(ec, "read_at");
return bytes_transferred;
}
template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
inline std::size_t read_at(SyncRandomAccessReadDevice& d,
uint64_t offset, const MutableBufferSequence& buffers,
asio::error_code& ec)
{
return read_at(d, offset, buffers, transfer_all(), ec);
}
template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
typename CompletionCondition>
inline std::size_t read_at(SyncRandomAccessReadDevice& d,
uint64_t offset, const MutableBufferSequence& buffers,
CompletionCondition completion_condition)
{
asio::error_code ec;
std::size_t bytes_transferred = read_at(
d, offset, buffers, completion_condition, ec);
asio::detail::throw_error(ec, "read_at");
return bytes_transferred;
}
#if !defined(ASIO_NO_EXTENSIONS)
#if !defined(ASIO_NO_IOSTREAM)
template <typename SyncRandomAccessReadDevice, typename Allocator,
typename CompletionCondition>
std::size_t read_at(SyncRandomAccessReadDevice& d,
uint64_t offset, asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition, asio::error_code& ec)
{
ec = asio::error_code();
std::size_t total_transferred = 0;
std::size_t max_size = detail::adapt_completion_condition_result(
completion_condition(ec, total_transferred));
std::size_t bytes_available = read_size_helper(b, max_size);
while (bytes_available > 0)
{
std::size_t bytes_transferred = d.read_some_at(
offset + total_transferred, b.prepare(bytes_available), ec);
b.commit(bytes_transferred);
total_transferred += bytes_transferred;
max_size = detail::adapt_completion_condition_result(
completion_condition(ec, total_transferred));
bytes_available = read_size_helper(b, max_size);
}
return total_transferred;
}
template <typename SyncRandomAccessReadDevice, typename Allocator>
inline std::size_t read_at(SyncRandomAccessReadDevice& d,
uint64_t offset, asio::basic_streambuf<Allocator>& b)
{
asio::error_code ec;
std::size_t bytes_transferred = read_at(
d, offset, b, transfer_all(), ec);
asio::detail::throw_error(ec, "read_at");
return bytes_transferred;
}
template <typename SyncRandomAccessReadDevice, typename Allocator>
inline std::size_t read_at(SyncRandomAccessReadDevice& d,
uint64_t offset, asio::basic_streambuf<Allocator>& b,
asio::error_code& ec)
{
return read_at(d, offset, b, transfer_all(), ec);
}
template <typename SyncRandomAccessReadDevice, typename Allocator,
typename CompletionCondition>
inline std::size_t read_at(SyncRandomAccessReadDevice& d,
uint64_t offset, asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition)
{
asio::error_code ec;
std::size_t bytes_transferred = read_at(
d, offset, b, completion_condition, ec);
asio::detail::throw_error(ec, "read_at");
return bytes_transferred;
}
#endif // !defined(ASIO_NO_IOSTREAM)
#endif // !defined(ASIO_NO_EXTENSIONS)
namespace detail
{
template <typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler>
class read_at_op
: detail::base_from_completion_cond<CompletionCondition>
{
public:
read_at_op(AsyncRandomAccessReadDevice& device,
uint64_t offset, const MutableBufferSequence& buffers,
CompletionCondition completion_condition, ReadHandler& handler)
: detail::base_from_completion_cond<
CompletionCondition>(completion_condition),
device_(device),
offset_(offset),
buffers_(buffers),
start_(0),
handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
{
}
#if defined(ASIO_HAS_MOVE)
read_at_op(const read_at_op& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
device_(other.device_),
offset_(other.offset_),
buffers_(other.buffers_),
start_(other.start_),
handler_(other.handler_)
{
}
read_at_op(read_at_op&& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
device_(other.device_),
offset_(other.offset_),
buffers_(other.buffers_),
start_(other.start_),
handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
{
}
#endif // defined(ASIO_HAS_MOVE)
void operator()(const asio::error_code& ec,
std::size_t bytes_transferred, int start = 0)
{
std::size_t max_size;
switch (start_ = start)
{
case 1:
max_size = this->check_for_completion(ec, buffers_.total_consumed());
do
{
device_.async_read_some_at(
offset_ + buffers_.total_consumed(), buffers_.prepare(max_size),
ASIO_MOVE_CAST(read_at_op)(*this));
return; default:
buffers_.consume(bytes_transferred);
if ((!ec && bytes_transferred == 0) || buffers_.empty())
break;
max_size = this->check_for_completion(ec, buffers_.total_consumed());
} while (max_size > 0);
handler_(ec, buffers_.total_consumed());
}
}
//private:
AsyncRandomAccessReadDevice& device_;
uint64_t offset_;
asio::detail::consuming_buffers<mutable_buffer,
MutableBufferSequence, MutableBufferIterator> buffers_;
int start_;
ReadHandler handler_;
};
template <typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler>
inline bool asio_handler_is_continuation(
read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
: asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler>
inline void asio_handler_invoke(Function& function,
read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler>
inline void start_read_at_buffer_sequence_op(AsyncRandomAccessReadDevice& d,
uint64_t offset, const MutableBufferSequence& buffers,
const MutableBufferIterator&, CompletionCondition completion_condition,
ReadHandler& handler)
{
detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>(
d, offset, buffers, completion_condition, handler)(
asio::error_code(), 0, 1);
}
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler, typename Allocator>
struct associated_allocator<
detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>,
Allocator>
{
typedef typename associated_allocator<ReadHandler, Allocator>::type type;
static type get(
const detail::read_at_op<AsyncRandomAccessReadDevice,
MutableBufferSequence, MutableBufferIterator,
CompletionCondition, ReadHandler>& h,
const Allocator& a = Allocator()) ASIO_NOEXCEPT
{
return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
}
};
template <typename AsyncRandomAccessReadDevice,
typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler, typename Executor>
struct associated_executor<
detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
MutableBufferIterator, CompletionCondition, ReadHandler>,
Executor>
{
typedef typename associated_executor<ReadHandler, Executor>::type type;
static type get(
const detail::read_at_op<AsyncRandomAccessReadDevice,
MutableBufferSequence, MutableBufferIterator,
CompletionCondition, ReadHandler>& h,
const Executor& ex = Executor()) ASIO_NOEXCEPT
{
return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
typename CompletionCondition, typename ReadHandler>
inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (asio::error_code, std::size_t))
async_read_at(AsyncRandomAccessReadDevice& d,
uint64_t offset, const MutableBufferSequence& buffers,
CompletionCondition completion_condition,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
detail::start_read_at_buffer_sequence_op(d, offset, buffers,
asio::buffer_sequence_begin(buffers), completion_condition,
init.completion_handler);
return init.result.get();
}
template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
typename ReadHandler>
inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (asio::error_code, std::size_t))
async_read_at(AsyncRandomAccessReadDevice& d,
uint64_t offset, const MutableBufferSequence& buffers,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
detail::start_read_at_buffer_sequence_op(d, offset, buffers,
asio::buffer_sequence_begin(buffers), transfer_all(),
init.completion_handler);
return init.result.get();
}
#if !defined(ASIO_NO_EXTENSIONS)
#if !defined(ASIO_NO_IOSTREAM)
namespace detail
{
template <typename AsyncRandomAccessReadDevice, typename Allocator,
typename CompletionCondition, typename ReadHandler>
class read_at_streambuf_op
: detail::base_from_completion_cond<CompletionCondition>
{
public:
read_at_streambuf_op(AsyncRandomAccessReadDevice& device,
uint64_t offset, basic_streambuf<Allocator>& streambuf,
CompletionCondition completion_condition, ReadHandler& handler)
: detail::base_from_completion_cond<
CompletionCondition>(completion_condition),
device_(device),
offset_(offset),
streambuf_(streambuf),
start_(0),
total_transferred_(0),
handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
{
}
#if defined(ASIO_HAS_MOVE)
read_at_streambuf_op(const read_at_streambuf_op& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
device_(other.device_),
offset_(other.offset_),
streambuf_(other.streambuf_),
start_(other.start_),
total_transferred_(other.total_transferred_),
handler_(other.handler_)
{
}
read_at_streambuf_op(read_at_streambuf_op&& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
device_(other.device_),
offset_(other.offset_),
streambuf_(other.streambuf_),
start_(other.start_),
total_transferred_(other.total_transferred_),
handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
{
}
#endif // defined(ASIO_HAS_MOVE)
void operator()(const asio::error_code& ec,
std::size_t bytes_transferred, int start = 0)
{
std::size_t max_size, bytes_available;
switch (start_ = start)
{
case 1:
max_size = this->check_for_completion(ec, total_transferred_);
bytes_available = read_size_helper(streambuf_, max_size);
for (;;)
{
device_.async_read_some_at(offset_ + total_transferred_,
streambuf_.prepare(bytes_available),
ASIO_MOVE_CAST(read_at_streambuf_op)(*this));
return; default:
total_transferred_ += bytes_transferred;
streambuf_.commit(bytes_transferred);
max_size = this->check_for_completion(ec, total_transferred_);
bytes_available = read_size_helper(streambuf_, max_size);
if ((!ec && bytes_transferred == 0) || bytes_available == 0)
break;
}
handler_(ec, static_cast<const std::size_t&>(total_transferred_));
}
}
//private:
AsyncRandomAccessReadDevice& device_;
uint64_t offset_;
asio::basic_streambuf<Allocator>& streambuf_;
int start_;
std::size_t total_transferred_;
ReadHandler handler_;
};
template <typename AsyncRandomAccessReadDevice, typename Allocator,
typename CompletionCondition, typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
CompletionCondition, ReadHandler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename AsyncRandomAccessReadDevice, typename Allocator,
typename CompletionCondition, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
CompletionCondition, ReadHandler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename AsyncRandomAccessReadDevice, typename Allocator,
typename CompletionCondition, typename ReadHandler>
inline bool asio_handler_is_continuation(
read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
CompletionCondition, ReadHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
: asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename AsyncRandomAccessReadDevice,
typename Allocator, typename CompletionCondition, typename ReadHandler>
inline void asio_handler_invoke(Function& function,
read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
CompletionCondition, ReadHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename AsyncRandomAccessReadDevice,
typename Allocator, typename CompletionCondition, typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
CompletionCondition, ReadHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename AsyncRandomAccessReadDevice, typename Allocator,
typename CompletionCondition, typename ReadHandler, typename Allocator1>
struct associated_allocator<
detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
Allocator, CompletionCondition, ReadHandler>,
Allocator1>
{
typedef typename associated_allocator<ReadHandler, Allocator1>::type type;
static type get(
const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
Allocator, CompletionCondition, ReadHandler>& h,
const Allocator1& a = Allocator1()) ASIO_NOEXCEPT
{
return associated_allocator<ReadHandler, Allocator1>::get(h.handler_, a);
}
};
template <typename AsyncRandomAccessReadDevice, typename Executor,
typename CompletionCondition, typename ReadHandler, typename Executor1>
struct associated_executor<
detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
Executor, CompletionCondition, ReadHandler>,
Executor1>
{
typedef typename associated_executor<ReadHandler, Executor1>::type type;
static type get(
const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
Executor, CompletionCondition, ReadHandler>& h,
const Executor1& ex = Executor1()) ASIO_NOEXCEPT
{
return associated_executor<ReadHandler, Executor1>::get(h.handler_, ex);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename AsyncRandomAccessReadDevice, typename Allocator,
typename CompletionCondition, typename ReadHandler>
inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (asio::error_code, std::size_t))
async_read_at(AsyncRandomAccessReadDevice& d,
uint64_t offset, asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
CompletionCondition, ASIO_HANDLER_TYPE(ReadHandler,
void (asio::error_code, std::size_t))>(
d, offset, b, completion_condition, init.completion_handler)(
asio::error_code(), 0, 1);
return init.result.get();
}
template <typename AsyncRandomAccessReadDevice, typename Allocator,
typename ReadHandler>
inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (asio::error_code, std::size_t))
async_read_at(AsyncRandomAccessReadDevice& d,
uint64_t offset, asio::basic_streambuf<Allocator>& b,
ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
async_completion<ReadHandler,
void (asio::error_code, std::size_t)> init(handler);
detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
detail::transfer_all_t, ASIO_HANDLER_TYPE(ReadHandler,
void (asio::error_code, std::size_t))>(
d, offset, b, transfer_all(), init.completion_handler)(
asio::error_code(), 0, 1);
return init.result.get();
}
#endif // !defined(ASIO_NO_IOSTREAM)
#endif // !defined(ASIO_NO_EXTENSIONS)
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_READ_AT_HPP

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,59 @@
//
// impl/serial_port_base.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_SERIAL_PORT_BASE_HPP
#define ASIO_IMPL_SERIAL_PORT_BASE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
namespace asio {
inline serial_port_base::baud_rate::baud_rate(unsigned int rate)
: value_(rate)
{
}
inline unsigned int serial_port_base::baud_rate::value() const
{
return value_;
}
inline serial_port_base::flow_control::type
serial_port_base::flow_control::value() const
{
return value_;
}
inline serial_port_base::parity::type serial_port_base::parity::value() const
{
return value_;
}
inline serial_port_base::stop_bits::type
serial_port_base::stop_bits::value() const
{
return value_;
}
inline unsigned int serial_port_base::character_size::value() const
{
return value_;
}
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_SERIAL_PORT_BASE_HPP

View File

@ -0,0 +1,535 @@
//
// impl/spawn.hpp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_SPAWN_HPP
#define ASIO_IMPL_SPAWN_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#include "asio/associated_allocator.hpp"
#include "asio/associated_executor.hpp"
#include "asio/async_result.hpp"
#include "asio/bind_executor.hpp"
#include "asio/detail/atomic_count.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_cont_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/memory.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/system_error.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
template <typename Handler, typename T>
class coro_handler
{
public:
coro_handler(basic_yield_context<Handler> ctx)
: coro_(ctx.coro_.lock()),
ca_(ctx.ca_),
handler_(ctx.handler_),
ready_(0),
ec_(ctx.ec_),
value_(0)
{
}
void operator()(T value)
{
*ec_ = asio::error_code();
*value_ = ASIO_MOVE_CAST(T)(value);
if (--*ready_ == 0)
(*coro_)();
}
void operator()(asio::error_code ec, T value)
{
*ec_ = ec;
*value_ = ASIO_MOVE_CAST(T)(value);
if (--*ready_ == 0)
(*coro_)();
}
//private:
shared_ptr<typename basic_yield_context<Handler>::callee_type> coro_;
typename basic_yield_context<Handler>::caller_type& ca_;
Handler handler_;
atomic_count* ready_;
asio::error_code* ec_;
T* value_;
};
template <typename Handler>
class coro_handler<Handler, void>
{
public:
coro_handler(basic_yield_context<Handler> ctx)
: coro_(ctx.coro_.lock()),
ca_(ctx.ca_),
handler_(ctx.handler_),
ready_(0),
ec_(ctx.ec_)
{
}
void operator()()
{
*ec_ = asio::error_code();
if (--*ready_ == 0)
(*coro_)();
}
void operator()(asio::error_code ec)
{
*ec_ = ec;
if (--*ready_ == 0)
(*coro_)();
}
//private:
shared_ptr<typename basic_yield_context<Handler>::callee_type> coro_;
typename basic_yield_context<Handler>::caller_type& ca_;
Handler handler_;
atomic_count* ready_;
asio::error_code* ec_;
};
template <typename Handler, typename T>
inline void* asio_handler_allocate(std::size_t size,
coro_handler<Handler, T>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename Handler, typename T>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
coro_handler<Handler, T>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename Handler, typename T>
inline bool asio_handler_is_continuation(coro_handler<Handler, T>*)
{
return true;
}
template <typename Function, typename Handler, typename T>
inline void asio_handler_invoke(Function& function,
coro_handler<Handler, T>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename Handler, typename T>
inline void asio_handler_invoke(const Function& function,
coro_handler<Handler, T>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Handler, typename T>
class coro_async_result
{
public:
typedef coro_handler<Handler, T> completion_handler_type;
typedef T return_type;
explicit coro_async_result(completion_handler_type& h)
: handler_(h),
ca_(h.ca_),
ready_(2)
{
h.ready_ = &ready_;
out_ec_ = h.ec_;
if (!out_ec_) h.ec_ = &ec_;
h.value_ = &value_;
}
return_type get()
{
// Must not hold shared_ptr to coro while suspended.
handler_.coro_.reset();
if (--ready_ != 0)
ca_();
if (!out_ec_ && ec_) throw asio::system_error(ec_);
return ASIO_MOVE_CAST(return_type)(value_);
}
private:
completion_handler_type& handler_;
typename basic_yield_context<Handler>::caller_type& ca_;
atomic_count ready_;
asio::error_code* out_ec_;
asio::error_code ec_;
return_type value_;
};
template <typename Handler>
class coro_async_result<Handler, void>
{
public:
typedef coro_handler<Handler, void> completion_handler_type;
typedef void return_type;
explicit coro_async_result(completion_handler_type& h)
: handler_(h),
ca_(h.ca_),
ready_(2)
{
h.ready_ = &ready_;
out_ec_ = h.ec_;
if (!out_ec_) h.ec_ = &ec_;
}
void get()
{
// Must not hold shared_ptr to coro while suspended.
handler_.coro_.reset();
if (--ready_ != 0)
ca_();
if (!out_ec_ && ec_) throw asio::system_error(ec_);
}
private:
completion_handler_type& handler_;
typename basic_yield_context<Handler>::caller_type& ca_;
atomic_count ready_;
asio::error_code* out_ec_;
asio::error_code ec_;
};
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename Handler, typename ReturnType>
class async_result<basic_yield_context<Handler>, ReturnType()>
: public detail::coro_async_result<Handler, void>
{
public:
explicit async_result(
typename detail::coro_async_result<Handler,
void>::completion_handler_type& h)
: detail::coro_async_result<Handler, void>(h)
{
}
};
template <typename Handler, typename ReturnType, typename Arg1>
class async_result<basic_yield_context<Handler>, ReturnType(Arg1)>
: public detail::coro_async_result<Handler, typename decay<Arg1>::type>
{
public:
explicit async_result(
typename detail::coro_async_result<Handler,
typename decay<Arg1>::type>::completion_handler_type& h)
: detail::coro_async_result<Handler, typename decay<Arg1>::type>(h)
{
}
};
template <typename Handler, typename ReturnType>
class async_result<basic_yield_context<Handler>,
ReturnType(asio::error_code)>
: public detail::coro_async_result<Handler, void>
{
public:
explicit async_result(
typename detail::coro_async_result<Handler,
void>::completion_handler_type& h)
: detail::coro_async_result<Handler, void>(h)
{
}
};
template <typename Handler, typename ReturnType, typename Arg2>
class async_result<basic_yield_context<Handler>,
ReturnType(asio::error_code, Arg2)>
: public detail::coro_async_result<Handler, typename decay<Arg2>::type>
{
public:
explicit async_result(
typename detail::coro_async_result<Handler,
typename decay<Arg2>::type>::completion_handler_type& h)
: detail::coro_async_result<Handler, typename decay<Arg2>::type>(h)
{
}
};
#if !defined(ASIO_NO_DEPRECATED)
template <typename Handler, typename ReturnType>
struct handler_type<basic_yield_context<Handler>, ReturnType()>
{
typedef detail::coro_handler<Handler, void> type;
};
template <typename Handler, typename ReturnType, typename Arg1>
struct handler_type<basic_yield_context<Handler>, ReturnType(Arg1)>
{
typedef detail::coro_handler<Handler, typename decay<Arg1>::type> type;
};
template <typename Handler, typename ReturnType>
struct handler_type<basic_yield_context<Handler>,
ReturnType(asio::error_code)>
{
typedef detail::coro_handler<Handler, void> type;
};
template <typename Handler, typename ReturnType, typename Arg2>
struct handler_type<basic_yield_context<Handler>,
ReturnType(asio::error_code, Arg2)>
{
typedef detail::coro_handler<Handler, typename decay<Arg2>::type> type;
};
template <typename Handler, typename T>
class async_result<detail::coro_handler<Handler, T> >
: public detail::coro_async_result<Handler, T>
{
public:
typedef typename detail::coro_async_result<Handler, T>::return_type type;
explicit async_result(
typename detail::coro_async_result<Handler,
T>::completion_handler_type& h)
: detail::coro_async_result<Handler, T>(h)
{
}
};
#endif // !defined(ASIO_NO_DEPRECATED)
template <typename Handler, typename T, typename Allocator>
struct associated_allocator<detail::coro_handler<Handler, T>, Allocator>
{
typedef typename associated_allocator<Handler, Allocator>::type type;
static type get(const detail::coro_handler<Handler, T>& h,
const Allocator& a = Allocator()) ASIO_NOEXCEPT
{
return associated_allocator<Handler, Allocator>::get(h.handler_, a);
}
};
template <typename Handler, typename T, typename Executor>
struct associated_executor<detail::coro_handler<Handler, T>, Executor>
{
typedef typename associated_executor<Handler, Executor>::type type;
static type get(const detail::coro_handler<Handler, T>& h,
const Executor& ex = Executor()) ASIO_NOEXCEPT
{
return associated_executor<Handler, Executor>::get(h.handler_, ex);
}
};
namespace detail {
template <typename Handler, typename Function>
struct spawn_data : private noncopyable
{
template <typename Hand, typename Func>
spawn_data(ASIO_MOVE_ARG(Hand) handler,
bool call_handler, ASIO_MOVE_ARG(Func) function)
: handler_(ASIO_MOVE_CAST(Hand)(handler)),
call_handler_(call_handler),
function_(ASIO_MOVE_CAST(Func)(function))
{
}
weak_ptr<typename basic_yield_context<Handler>::callee_type> coro_;
Handler handler_;
bool call_handler_;
Function function_;
};
template <typename Handler, typename Function>
struct coro_entry_point
{
void operator()(typename basic_yield_context<Handler>::caller_type& ca)
{
shared_ptr<spawn_data<Handler, Function> > data(data_);
#if !defined(BOOST_COROUTINES_UNIDIRECT) && !defined(BOOST_COROUTINES_V2)
ca(); // Yield until coroutine pointer has been initialised.
#endif // !defined(BOOST_COROUTINES_UNIDIRECT) && !defined(BOOST_COROUTINES_V2)
const basic_yield_context<Handler> yield(
data->coro_, ca, data->handler_);
(data->function_)(yield);
if (data->call_handler_)
(data->handler_)();
}
shared_ptr<spawn_data<Handler, Function> > data_;
};
template <typename Handler, typename Function>
struct spawn_helper
{
void operator()()
{
typedef typename basic_yield_context<Handler>::callee_type callee_type;
coro_entry_point<Handler, Function> entry_point = { data_ };
shared_ptr<callee_type> coro(new callee_type(entry_point, attributes_));
data_->coro_ = coro;
(*coro)();
}
shared_ptr<spawn_data<Handler, Function> > data_;
boost::coroutines::attributes attributes_;
};
template <typename Function, typename Handler, typename Function1>
inline void asio_handler_invoke(Function& function,
spawn_helper<Handler, Function1>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->data_->handler_);
}
template <typename Function, typename Handler, typename Function1>
inline void asio_handler_invoke(const Function& function,
spawn_helper<Handler, Function1>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->data_->handler_);
}
inline void default_spawn_handler() {}
} // namespace detail
template <typename Function>
inline void spawn(ASIO_MOVE_ARG(Function) function,
const boost::coroutines::attributes& attributes)
{
typedef typename decay<Function>::type function_type;
typename associated_executor<function_type>::type ex(
(get_associated_executor)(function));
asio::spawn(ex, ASIO_MOVE_CAST(Function)(function), attributes);
}
template <typename Handler, typename Function>
void spawn(ASIO_MOVE_ARG(Handler) handler,
ASIO_MOVE_ARG(Function) function,
const boost::coroutines::attributes& attributes,
typename enable_if<!is_executor<typename decay<Handler>::type>::value &&
!is_convertible<Handler&, execution_context&>::value>::type*)
{
typedef typename decay<Handler>::type handler_type;
typedef typename decay<Function>::type function_type;
typename associated_executor<handler_type>::type ex(
(get_associated_executor)(handler));
typename associated_allocator<handler_type>::type a(
(get_associated_allocator)(handler));
detail::spawn_helper<handler_type, function_type> helper;
helper.data_.reset(
new detail::spawn_data<handler_type, function_type>(
ASIO_MOVE_CAST(Handler)(handler), true,
ASIO_MOVE_CAST(Function)(function)));
helper.attributes_ = attributes;
ex.dispatch(helper, a);
}
template <typename Handler, typename Function>
void spawn(basic_yield_context<Handler> ctx,
ASIO_MOVE_ARG(Function) function,
const boost::coroutines::attributes& attributes)
{
typedef typename decay<Function>::type function_type;
Handler handler(ctx.handler_); // Explicit copy that might be moved from.
typename associated_executor<Handler>::type ex(
(get_associated_executor)(handler));
typename associated_allocator<Handler>::type a(
(get_associated_allocator)(handler));
detail::spawn_helper<Handler, function_type> helper;
helper.data_.reset(
new detail::spawn_data<Handler, function_type>(
ASIO_MOVE_CAST(Handler)(handler), false,
ASIO_MOVE_CAST(Function)(function)));
helper.attributes_ = attributes;
ex.dispatch(helper, a);
}
template <typename Function, typename Executor>
inline void spawn(const Executor& ex,
ASIO_MOVE_ARG(Function) function,
const boost::coroutines::attributes& attributes,
typename enable_if<is_executor<Executor>::value>::type*)
{
asio::spawn(asio::strand<Executor>(ex),
ASIO_MOVE_CAST(Function)(function), attributes);
}
template <typename Function, typename Executor>
inline void spawn(const strand<Executor>& ex,
ASIO_MOVE_ARG(Function) function,
const boost::coroutines::attributes& attributes)
{
asio::spawn(asio::bind_executor(
ex, &detail::default_spawn_handler),
ASIO_MOVE_CAST(Function)(function), attributes);
}
template <typename Function>
inline void spawn(const asio::io_context::strand& s,
ASIO_MOVE_ARG(Function) function,
const boost::coroutines::attributes& attributes)
{
asio::spawn(asio::bind_executor(
s, &detail::default_spawn_handler),
ASIO_MOVE_CAST(Function)(function), attributes);
}
template <typename Function, typename ExecutionContext>
inline void spawn(ExecutionContext& ctx,
ASIO_MOVE_ARG(Function) function,
const boost::coroutines::attributes& attributes,
typename enable_if<is_convertible<
ExecutionContext&, execution_context&>::value>::type*)
{
asio::spawn(ctx.get_executor(),
ASIO_MOVE_CAST(Function)(function), attributes);
}
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_SPAWN_HPP

View File

@ -0,0 +1,82 @@
//
// impl/src.hpp
// ~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_SRC_HPP
#define ASIO_IMPL_SRC_HPP
#define ASIO_SOURCE
#include "asio/detail/config.hpp"
#if defined(ASIO_HEADER_ONLY)
# error Do not compile Asio library source with ASIO_HEADER_ONLY defined
#endif
#include "asio/impl/error.ipp"
#include "asio/impl/error_code.ipp"
#include "asio/impl/execution_context.ipp"
#include "asio/impl/executor.ipp"
#include "asio/impl/handler_alloc_hook.ipp"
#include "asio/impl/io_context.ipp"
#include "asio/impl/serial_port_base.ipp"
#include "asio/impl/system_context.ipp"
#include "asio/impl/thread_pool.ipp"
#include "asio/detail/impl/buffer_sequence_adapter.ipp"
#include "asio/detail/impl/descriptor_ops.ipp"
#include "asio/detail/impl/dev_poll_reactor.ipp"
#include "asio/detail/impl/epoll_reactor.ipp"
#include "asio/detail/impl/eventfd_select_interrupter.ipp"
#include "asio/detail/impl/handler_tracking.ipp"
#include "asio/detail/impl/kqueue_reactor.ipp"
#include "asio/detail/impl/null_event.ipp"
#include "asio/detail/impl/pipe_select_interrupter.ipp"
#include "asio/detail/impl/posix_event.ipp"
#include "asio/detail/impl/posix_mutex.ipp"
#include "asio/detail/impl/posix_thread.ipp"
#include "asio/detail/impl/posix_tss_ptr.ipp"
#include "asio/detail/impl/reactive_descriptor_service.ipp"
#include "asio/detail/impl/reactive_serial_port_service.ipp"
#include "asio/detail/impl/reactive_socket_service_base.ipp"
#include "asio/detail/impl/resolver_service_base.ipp"
#include "asio/detail/impl/scheduler.ipp"
#include "asio/detail/impl/select_reactor.ipp"
#include "asio/detail/impl/service_registry.ipp"
#include "asio/detail/impl/signal_set_service.ipp"
#include "asio/detail/impl/socket_ops.ipp"
#include "asio/detail/impl/socket_select_interrupter.ipp"
#include "asio/detail/impl/strand_executor_service.ipp"
#include "asio/detail/impl/strand_service.ipp"
#include "asio/detail/impl/throw_error.ipp"
#include "asio/detail/impl/timer_queue_ptime.ipp"
#include "asio/detail/impl/timer_queue_set.ipp"
#include "asio/detail/impl/win_iocp_handle_service.ipp"
#include "asio/detail/impl/win_iocp_io_context.ipp"
#include "asio/detail/impl/win_iocp_serial_port_service.ipp"
#include "asio/detail/impl/win_iocp_socket_service_base.ipp"
#include "asio/detail/impl/win_event.ipp"
#include "asio/detail/impl/win_mutex.ipp"
#include "asio/detail/impl/win_object_handle_service.ipp"
#include "asio/detail/impl/win_static_mutex.ipp"
#include "asio/detail/impl/win_thread.ipp"
#include "asio/detail/impl/win_tss_ptr.ipp"
#include "asio/detail/impl/winrt_ssocket_service_base.ipp"
#include "asio/detail/impl/winrt_timer_scheduler.ipp"
#include "asio/detail/impl/winsock_init.ipp"
#include "asio/generic/detail/impl/endpoint.ipp"
#include "asio/ip/impl/address.ipp"
#include "asio/ip/impl/address_v4.ipp"
#include "asio/ip/impl/address_v6.ipp"
#include "asio/ip/impl/host_name.ipp"
#include "asio/ip/impl/network_v4.ipp"
#include "asio/ip/impl/network_v6.ipp"
#include "asio/ip/detail/impl/endpoint.ipp"
#include "asio/local/detail/impl/endpoint.ipp"
#endif // ASIO_IMPL_SRC_HPP

View File

@ -0,0 +1,34 @@
//
// impl/system_context.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_SYSTEM_CONTEXT_HPP
#define ASIO_IMPL_SYSTEM_CONTEXT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/system_executor.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
inline system_context::executor_type
system_context::get_executor() ASIO_NOEXCEPT
{
return system_executor();
}
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_SYSTEM_CONTEXT_HPP

View File

@ -0,0 +1,85 @@
//
// impl/system_executor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_SYSTEM_EXECUTOR_HPP
#define ASIO_IMPL_SYSTEM_EXECUTOR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/executor_op.hpp"
#include "asio/detail/global.hpp"
#include "asio/detail/recycling_allocator.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/system_context.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
inline system_context& system_executor::context() const ASIO_NOEXCEPT
{
return detail::global<system_context>();
}
template <typename Function, typename Allocator>
void system_executor::dispatch(
ASIO_MOVE_ARG(Function) f, const Allocator&) const
{
typename decay<Function>::type tmp(ASIO_MOVE_CAST(Function)(f));
asio_handler_invoke_helpers::invoke(tmp, tmp);
}
template <typename Function, typename Allocator>
void system_executor::post(
ASIO_MOVE_ARG(Function) f, const Allocator& a) const
{
typedef typename decay<Function>::type function_type;
system_context& ctx = detail::global<system_context>();
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator> op;
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
ASIO_HANDLER_CREATION((ctx, *p.p,
"system_executor", &this->context(), 0, "post"));
ctx.scheduler_.post_immediate_completion(p.p, false);
p.v = p.p = 0;
}
template <typename Function, typename Allocator>
void system_executor::defer(
ASIO_MOVE_ARG(Function) f, const Allocator& a) const
{
typedef typename decay<Function>::type function_type;
system_context& ctx = detail::global<system_context>();
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator> op;
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
ASIO_HANDLER_CREATION((ctx, *p.p,
"system_executor", &this->context(), 0, "defer"));
ctx.scheduler_.post_immediate_completion(p.p, true);
p.v = p.p = 0;
}
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_SYSTEM_EXECUTOR_HPP

View File

@ -0,0 +1,127 @@
//
// impl/thread_pool.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_THREAD_POOL_HPP
#define ASIO_IMPL_THREAD_POOL_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/executor_op.hpp"
#include "asio/detail/fenced_block.hpp"
#include "asio/detail/recycling_allocator.hpp"
#include "asio/detail/type_traits.hpp"
#include "asio/execution_context.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
inline thread_pool::executor_type
thread_pool::get_executor() ASIO_NOEXCEPT
{
return executor_type(*this);
}
inline thread_pool&
thread_pool::executor_type::context() const ASIO_NOEXCEPT
{
return pool_;
}
inline void
thread_pool::executor_type::on_work_started() const ASIO_NOEXCEPT
{
pool_.scheduler_.work_started();
}
inline void thread_pool::executor_type::on_work_finished()
const ASIO_NOEXCEPT
{
pool_.scheduler_.work_finished();
}
template <typename Function, typename Allocator>
void thread_pool::executor_type::dispatch(
ASIO_MOVE_ARG(Function) f, const Allocator& a) const
{
typedef typename decay<Function>::type function_type;
// Invoke immediately if we are already inside the thread pool.
if (pool_.scheduler_.can_dispatch())
{
// Make a local, non-const copy of the function.
function_type tmp(ASIO_MOVE_CAST(Function)(f));
detail::fenced_block b(detail::fenced_block::full);
asio_handler_invoke_helpers::invoke(tmp, tmp);
return;
}
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator> op;
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
ASIO_HANDLER_CREATION((pool_, *p.p,
"thread_pool", &this->context(), 0, "dispatch"));
pool_.scheduler_.post_immediate_completion(p.p, false);
p.v = p.p = 0;
}
template <typename Function, typename Allocator>
void thread_pool::executor_type::post(
ASIO_MOVE_ARG(Function) f, const Allocator& a) const
{
typedef typename decay<Function>::type function_type;
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator> op;
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
ASIO_HANDLER_CREATION((pool_, *p.p,
"thread_pool", &this->context(), 0, "post"));
pool_.scheduler_.post_immediate_completion(p.p, false);
p.v = p.p = 0;
}
template <typename Function, typename Allocator>
void thread_pool::executor_type::defer(
ASIO_MOVE_ARG(Function) f, const Allocator& a) const
{
typedef typename decay<Function>::type function_type;
// Allocate and construct an operation to wrap the function.
typedef detail::executor_op<function_type, Allocator> op;
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
ASIO_HANDLER_CREATION((pool_, *p.p,
"thread_pool", &this->context(), 0, "defer"));
pool_.scheduler_.post_immediate_completion(p.p, true);
p.v = p.p = 0;
}
inline bool
thread_pool::executor_type::running_in_this_thread() const ASIO_NOEXCEPT
{
return pool_.scheduler_.can_dispatch();
}
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_THREAD_POOL_HPP

View File

@ -0,0 +1,938 @@
//
// impl/use_future.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_USE_FUTURE_HPP
#define ASIO_IMPL_USE_FUTURE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/config.hpp"
#include <future>
#include <tuple>
#include "asio/async_result.hpp"
#include "asio/detail/memory.hpp"
#include "asio/error_code.hpp"
#include "asio/packaged_task.hpp"
#include "asio/system_error.hpp"
#include "asio/system_executor.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
#if defined(ASIO_HAS_VARIADIC_TEMPLATES)
template <typename T, typename F, typename... Args>
inline void promise_invoke_and_set(std::promise<T>& p,
F& f, ASIO_MOVE_ARG(Args)... args)
{
#if !defined(ASIO_NO_EXCEPTIONS)
try
#endif // !defined(ASIO_NO_EXCEPTIONS)
{
p.set_value(f(ASIO_MOVE_CAST(Args)(args)...));
}
#if !defined(ASIO_NO_EXCEPTIONS)
catch (...)
{
p.set_exception(std::current_exception());
}
#endif // !defined(ASIO_NO_EXCEPTIONS)
}
template <typename F, typename... Args>
inline void promise_invoke_and_set(std::promise<void>& p,
F& f, ASIO_MOVE_ARG(Args)... args)
{
#if !defined(ASIO_NO_EXCEPTIONS)
try
#endif // !defined(ASIO_NO_EXCEPTIONS)
{
f(ASIO_MOVE_CAST(Args)(args)...);
p.set_value();
}
#if !defined(ASIO_NO_EXCEPTIONS)
catch (...)
{
p.set_exception(std::current_exception());
}
#endif // !defined(ASIO_NO_EXCEPTIONS)
}
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
template <typename T, typename F>
inline void promise_invoke_and_set(std::promise<T>& p, F& f)
{
#if !defined(ASIO_NO_EXCEPTIONS)
try
#endif // !defined(ASIO_NO_EXCEPTIONS)
{
p.set_value(f());
}
#if !defined(ASIO_NO_EXCEPTIONS)
catch (...)
{
p.set_exception(std::current_exception());
}
#endif // !defined(ASIO_NO_EXCEPTIONS)
}
template <typename F, typename Args>
inline void promise_invoke_and_set(std::promise<void>& p, F& f)
{
#if !defined(ASIO_NO_EXCEPTIONS)
try
#endif // !defined(ASIO_NO_EXCEPTIONS)
{
f();
p.set_value();
#if !defined(ASIO_NO_EXCEPTIONS)
}
catch (...)
{
p.set_exception(std::current_exception());
}
#endif // !defined(ASIO_NO_EXCEPTIONS)
}
#if defined(ASIO_NO_EXCEPTIONS)
#define ASIO_PRIVATE_PROMISE_INVOKE_DEF(n) \
template <typename T, typename F, ASIO_VARIADIC_TPARAMS(n)> \
inline void promise_invoke_and_set(std::promise<T>& p, \
F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
p.set_value(f(ASIO_VARIADIC_MOVE_ARGS(n))); \
} \
\
template <typename F, ASIO_VARIADIC_TPARAMS(n)> \
inline void promise_invoke_and_set(std::promise<void>& p, \
F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
f(ASIO_VARIADIC_MOVE_ARGS(n)); \
p.set_value(); \
} \
/**/
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_PROMISE_INVOKE_DEF)
#undef ASIO_PRIVATE_PROMISE_INVOKE_DEF
#else // defined(ASIO_NO_EXCEPTIONS)
#define ASIO_PRIVATE_PROMISE_INVOKE_DEF(n) \
template <typename T, typename F, ASIO_VARIADIC_TPARAMS(n)> \
inline void promise_invoke_and_set(std::promise<T>& p, \
F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
try \
{ \
p.set_value(f(ASIO_VARIADIC_MOVE_ARGS(n))); \
} \
catch (...) \
{ \
p.set_exception(std::current_exception()); \
} \
} \
\
template <typename F, ASIO_VARIADIC_TPARAMS(n)> \
inline void promise_invoke_and_set(std::promise<void>& p, \
F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \
{ \
try \
{ \
f(ASIO_VARIADIC_MOVE_ARGS(n)); \
p.set_value(); \
} \
catch (...) \
{ \
p.set_exception(std::current_exception()); \
} \
} \
/**/
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_PROMISE_INVOKE_DEF)
#undef ASIO_PRIVATE_PROMISE_INVOKE_DEF
#endif // defined(ASIO_NO_EXCEPTIONS)
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
// A function object adapter to invoke a nullary function object and capture
// any exception thrown into a promise.
template <typename T, typename F>
class promise_invoker
{
public:
promise_invoker(const shared_ptr<std::promise<T> >& p,
ASIO_MOVE_ARG(F) f)
: p_(p), f_(ASIO_MOVE_CAST(F)(f))
{
}
void operator()()
{
#if !defined(ASIO_NO_EXCEPTIONS)
try
#endif // !defined(ASIO_NO_EXCEPTIONS)
{
f_();
}
#if !defined(ASIO_NO_EXCEPTIONS)
catch (...)
{
p_->set_exception(std::current_exception());
}
#endif // !defined(ASIO_NO_EXCEPTIONS)
}
private:
shared_ptr<std::promise<T> > p_;
typename decay<F>::type f_;
};
// An executor that adapts the system_executor to capture any exeption thrown
// by a submitted function object and save it into a promise.
template <typename T>
class promise_executor
{
public:
explicit promise_executor(const shared_ptr<std::promise<T> >& p)
: p_(p)
{
}
execution_context& context() const ASIO_NOEXCEPT
{
return system_executor().context();
}
void on_work_started() const ASIO_NOEXCEPT {}
void on_work_finished() const ASIO_NOEXCEPT {}
template <typename F, typename A>
void dispatch(ASIO_MOVE_ARG(F) f, const A&) const
{
promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f))();
}
template <typename F, typename A>
void post(ASIO_MOVE_ARG(F) f, const A& a) const
{
system_executor().post(
promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f)), a);
}
template <typename F, typename A>
void defer(ASIO_MOVE_ARG(F) f, const A& a) const
{
system_executor().defer(
promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f)), a);
}
friend bool operator==(const promise_executor& a,
const promise_executor& b) ASIO_NOEXCEPT
{
return a.p_ == b.p_;
}
friend bool operator!=(const promise_executor& a,
const promise_executor& b) ASIO_NOEXCEPT
{
return a.p_ != b.p_;
}
private:
shared_ptr<std::promise<T> > p_;
};
// The base class for all completion handlers that create promises.
template <typename T>
class promise_creator
{
public:
typedef promise_executor<T> executor_type;
executor_type get_executor() const ASIO_NOEXCEPT
{
return executor_type(p_);
}
typedef std::future<T> future_type;
future_type get_future()
{
return p_->get_future();
}
protected:
template <typename Allocator>
void create_promise(const Allocator& a)
{
ASIO_REBIND_ALLOC(Allocator, char) b(a);
p_ = std::allocate_shared<std::promise<T>>(b, std::allocator_arg, b);
}
shared_ptr<std::promise<T> > p_;
};
// For completion signature void().
class promise_handler_0
: public promise_creator<void>
{
public:
void operator()()
{
this->p_->set_value();
}
};
// For completion signature void(error_code).
class promise_handler_ec_0
: public promise_creator<void>
{
public:
void operator()(const asio::error_code& ec)
{
if (ec)
{
this->p_->set_exception(
std::make_exception_ptr(
asio::system_error(ec)));
}
else
{
this->p_->set_value();
}
}
};
// For completion signature void(exception_ptr).
class promise_handler_ex_0
: public promise_creator<void>
{
public:
void operator()(const std::exception_ptr& ex)
{
if (ex)
{
this->p_->set_exception(ex);
}
else
{
this->p_->set_value();
}
}
};
// For completion signature void(T).
template <typename T>
class promise_handler_1
: public promise_creator<T>
{
public:
template <typename Arg>
void operator()(ASIO_MOVE_ARG(Arg) arg)
{
this->p_->set_value(ASIO_MOVE_CAST(Arg)(arg));
}
};
// For completion signature void(error_code, T).
template <typename T>
class promise_handler_ec_1
: public promise_creator<T>
{
public:
template <typename Arg>
void operator()(const asio::error_code& ec,
ASIO_MOVE_ARG(Arg) arg)
{
if (ec)
{
this->p_->set_exception(
std::make_exception_ptr(
asio::system_error(ec)));
}
else
this->p_->set_value(ASIO_MOVE_CAST(Arg)(arg));
}
};
// For completion signature void(exception_ptr, T).
template <typename T>
class promise_handler_ex_1
: public promise_creator<T>
{
public:
template <typename Arg>
void operator()(const std::exception_ptr& ex,
ASIO_MOVE_ARG(Arg) arg)
{
if (ex)
this->p_->set_exception(ex);
else
this->p_->set_value(ASIO_MOVE_CAST(Arg)(arg));
}
};
// For completion signature void(T1, ..., Tn);
template <typename T>
class promise_handler_n
: public promise_creator<T>
{
public:
#if defined(ASIO_HAS_VARIADIC_TEMPLATES)
template <typename... Args>
void operator()(ASIO_MOVE_ARG(Args)... args)
{
this->p_->set_value(
std::forward_as_tuple(
ASIO_MOVE_CAST(Args)(args)...));
}
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
#define ASIO_PRIVATE_CALL_OP_DEF(n) \
template <ASIO_VARIADIC_TPARAMS(n)> \
void operator()(ASIO_VARIADIC_MOVE_PARAMS(n)) \
{\
this->p_->set_value( \
std::forward_as_tuple( \
ASIO_VARIADIC_MOVE_ARGS(n))); \
} \
/**/
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF)
#undef ASIO_PRIVATE_CALL_OP_DEF
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
};
// For completion signature void(error_code, T1, ..., Tn);
template <typename T>
class promise_handler_ec_n
: public promise_creator<T>
{
public:
#if defined(ASIO_HAS_VARIADIC_TEMPLATES)
template <typename... Args>
void operator()(const asio::error_code& ec,
ASIO_MOVE_ARG(Args)... args)
{
if (ec)
{
this->p_->set_exception(
std::make_exception_ptr(
asio::system_error(ec)));
}
else
{
this->p_->set_value(
std::forward_as_tuple(
ASIO_MOVE_CAST(Args)(args)...));
}
}
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
#define ASIO_PRIVATE_CALL_OP_DEF(n) \
template <ASIO_VARIADIC_TPARAMS(n)> \
void operator()(const asio::error_code& ec, \
ASIO_VARIADIC_MOVE_PARAMS(n)) \
{\
if (ec) \
{ \
this->p_->set_exception( \
std::make_exception_ptr( \
asio::system_error(ec))); \
} \
else \
{ \
this->p_->set_value( \
std::forward_as_tuple( \
ASIO_VARIADIC_MOVE_ARGS(n))); \
} \
} \
/**/
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF)
#undef ASIO_PRIVATE_CALL_OP_DEF
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
};
// For completion signature void(exception_ptr, T1, ..., Tn);
template <typename T>
class promise_handler_ex_n
: public promise_creator<T>
{
public:
#if defined(ASIO_HAS_VARIADIC_TEMPLATES)
template <typename... Args>
void operator()(const std::exception_ptr& ex,
ASIO_MOVE_ARG(Args)... args)
{
if (ex)
this->p_->set_exception(ex);
else
{
this->p_->set_value(
std::forward_as_tuple(
ASIO_MOVE_CAST(Args)(args)...));
}
}
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
#define ASIO_PRIVATE_CALL_OP_DEF(n) \
template <ASIO_VARIADIC_TPARAMS(n)> \
void operator()(const std::exception_ptr& ex, \
ASIO_VARIADIC_MOVE_PARAMS(n)) \
{\
if (ex) \
this->p_->set_exception(ex); \
else \
{ \
this->p_->set_value( \
std::forward_as_tuple( \
ASIO_VARIADIC_MOVE_ARGS(n))); \
} \
} \
/**/
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF)
#undef ASIO_PRIVATE_CALL_OP_DEF
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
};
// Helper template to choose the appropriate concrete promise handler
// implementation based on the supplied completion signature.
template <typename> class promise_handler_selector;
template <>
class promise_handler_selector<void()>
: public promise_handler_0 {};
template <>
class promise_handler_selector<void(asio::error_code)>
: public promise_handler_ec_0 {};
template <>
class promise_handler_selector<void(std::exception_ptr)>
: public promise_handler_ex_0 {};
template <typename Arg>
class promise_handler_selector<void(Arg)>
: public promise_handler_1<Arg> {};
template <typename Arg>
class promise_handler_selector<void(asio::error_code, Arg)>
: public promise_handler_ec_1<Arg> {};
template <typename Arg>
class promise_handler_selector<void(std::exception_ptr, Arg)>
: public promise_handler_ex_1<Arg> {};
#if defined(ASIO_HAS_VARIADIC_TEMPLATES)
template <typename... Arg>
class promise_handler_selector<void(Arg...)>
: public promise_handler_n<std::tuple<Arg...> > {};
template <typename... Arg>
class promise_handler_selector<void(asio::error_code, Arg...)>
: public promise_handler_ec_n<std::tuple<Arg...> > {};
template <typename... Arg>
class promise_handler_selector<void(std::exception_ptr, Arg...)>
: public promise_handler_ex_n<std::tuple<Arg...> > {};
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
#define ASIO_PRIVATE_PROMISE_SELECTOR_DEF(n) \
template <typename Arg, ASIO_VARIADIC_TPARAMS(n)> \
class promise_handler_selector< \
void(Arg, ASIO_VARIADIC_TARGS(n))> \
: public promise_handler_n< \
std::tuple<Arg, ASIO_VARIADIC_TARGS(n)> > {}; \
\
template <typename Arg, ASIO_VARIADIC_TPARAMS(n)> \
class promise_handler_selector< \
void(asio::error_code, Arg, ASIO_VARIADIC_TARGS(n))> \
: public promise_handler_ec_n< \
std::tuple<Arg, ASIO_VARIADIC_TARGS(n)> > {}; \
\
template <typename Arg, ASIO_VARIADIC_TPARAMS(n)> \
class promise_handler_selector< \
void(std::exception_ptr, Arg, ASIO_VARIADIC_TARGS(n))> \
: public promise_handler_ex_n< \
std::tuple<Arg, ASIO_VARIADIC_TARGS(n)> > {}; \
/**/
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_PROMISE_SELECTOR_DEF)
#undef ASIO_PRIVATE_PROMISE_SELECTOR_DEF
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
// Completion handlers produced from the use_future completion token, when not
// using use_future::operator().
template <typename Signature, typename Allocator>
class promise_handler
: public promise_handler_selector<Signature>
{
public:
typedef Allocator allocator_type;
typedef void result_type;
promise_handler(use_future_t<Allocator> u)
: allocator_(u.get_allocator())
{
this->create_promise(allocator_);
}
allocator_type get_allocator() const ASIO_NOEXCEPT
{
return allocator_;
}
private:
Allocator allocator_;
};
template <typename Function, typename Signature, typename Allocator>
inline void asio_handler_invoke(Function& f,
promise_handler<Signature, Allocator>* h)
{
typename promise_handler<Signature, Allocator>::executor_type
ex(h->get_executor());
ex.dispatch(ASIO_MOVE_CAST(Function)(f), std::allocator<void>());
}
template <typename Function, typename Signature, typename Allocator>
inline void asio_handler_invoke(const Function& f,
promise_handler<Signature, Allocator>* h)
{
typename promise_handler<Signature, Allocator>::executor_type
ex(h->get_executor());
ex.dispatch(f, std::allocator<void>());
}
// Helper base class for async_result specialisation.
template <typename Signature, typename Allocator>
class promise_async_result
{
public:
typedef promise_handler<Signature, Allocator> completion_handler_type;
typedef typename completion_handler_type::future_type return_type;
explicit promise_async_result(completion_handler_type& h)
: future_(h.get_future())
{
}
return_type get()
{
return ASIO_MOVE_CAST(return_type)(future_);
}
private:
return_type future_;
};
// Return value from use_future::operator().
template <typename Function, typename Allocator>
class packaged_token
{
public:
packaged_token(Function f, const Allocator& a)
: function_(ASIO_MOVE_CAST(Function)(f)),
allocator_(a)
{
}
//private:
Function function_;
Allocator allocator_;
};
// Completion handlers produced from the use_future completion token, when
// using use_future::operator().
template <typename Function, typename Allocator, typename Result>
class packaged_handler
: public promise_creator<Result>
{
public:
typedef Allocator allocator_type;
typedef void result_type;
packaged_handler(packaged_token<Function, Allocator> t)
: function_(ASIO_MOVE_CAST(Function)(t.function_)),
allocator_(t.allocator_)
{
this->create_promise(allocator_);
}
allocator_type get_allocator() const ASIO_NOEXCEPT
{
return allocator_;
}
#if defined(ASIO_HAS_VARIADIC_TEMPLATES)
template <typename... Args>
void operator()(ASIO_MOVE_ARG(Args)... args)
{
(promise_invoke_and_set)(*this->p_,
function_, ASIO_MOVE_CAST(Args)(args)...);
}
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
void operator()()
{
(promise_invoke_and_set)(*this->p_, function_);
}
#define ASIO_PRIVATE_CALL_OP_DEF(n) \
template <ASIO_VARIADIC_TPARAMS(n)> \
void operator()(ASIO_VARIADIC_MOVE_PARAMS(n)) \
{\
(promise_invoke_and_set)(*this->p_, \
function_, ASIO_VARIADIC_MOVE_ARGS(n)); \
} \
/**/
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF)
#undef ASIO_PRIVATE_CALL_OP_DEF
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
private:
Function function_;
Allocator allocator_;
};
template <typename Function,
typename Function1, typename Allocator, typename Result>
inline void asio_handler_invoke(Function& f,
packaged_handler<Function1, Allocator, Result>* h)
{
typename packaged_handler<Function1, Allocator, Result>::executor_type
ex(h->get_executor());
ex.dispatch(ASIO_MOVE_CAST(Function)(f), std::allocator<void>());
}
template <typename Function,
typename Function1, typename Allocator, typename Result>
inline void asio_handler_invoke(const Function& f,
packaged_handler<Function1, Allocator, Result>* h)
{
typename packaged_handler<Function1, Allocator, Result>::executor_type
ex(h->get_executor());
ex.dispatch(f, std::allocator<void>());
}
// Helper base class for async_result specialisation.
template <typename Function, typename Allocator, typename Result>
class packaged_async_result
{
public:
typedef packaged_handler<Function, Allocator, Result> completion_handler_type;
typedef typename completion_handler_type::future_type return_type;
explicit packaged_async_result(completion_handler_type& h)
: future_(h.get_future())
{
}
return_type get()
{
return ASIO_MOVE_CAST(return_type)(future_);
}
private:
return_type future_;
};
} // namespace detail
template <typename Allocator> template <typename Function>
inline detail::packaged_token<typename decay<Function>::type, Allocator>
use_future_t<Allocator>::operator()(ASIO_MOVE_ARG(Function) f) const
{
return detail::packaged_token<typename decay<Function>::type, Allocator>(
ASIO_MOVE_CAST(Function)(f), allocator_);
}
#if !defined(GENERATING_DOCUMENTATION)
#if defined(ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Allocator, typename Result, typename... Args>
class async_result<use_future_t<Allocator>, Result(Args...)>
: public detail::promise_async_result<
void(typename decay<Args>::type...), Allocator>
{
public:
explicit async_result(
typename detail::promise_async_result<void(typename decay<Args>::type...),
Allocator>::completion_handler_type& h)
: detail::promise_async_result<
void(typename decay<Args>::type...), Allocator>(h)
{
}
};
template <typename Function, typename Allocator,
typename Result, typename... Args>
class async_result<detail::packaged_token<Function, Allocator>, Result(Args...)>
: public detail::packaged_async_result<Function, Allocator,
typename result_of<Function(Args...)>::type>
{
public:
explicit async_result(
typename detail::packaged_async_result<Function, Allocator,
typename result_of<Function(Args...)>::type>::completion_handler_type& h)
: detail::packaged_async_result<Function, Allocator,
typename result_of<Function(Args...)>::type>(h)
{
}
};
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
template <typename Allocator, typename Result>
class async_result<use_future_t<Allocator>, Result()>
: public detail::promise_async_result<void(), Allocator>
{
public:
explicit async_result(
typename detail::promise_async_result<
void(), Allocator>::completion_handler_type& h)
: detail::promise_async_result<void(), Allocator>(h)
{
}
};
template <typename Function, typename Allocator, typename Result>
class async_result<detail::packaged_token<Function, Allocator>, Result()>
: public detail::packaged_async_result<Function, Allocator,
typename result_of<Function()>::type>
{
public:
explicit async_result(
typename detail::packaged_async_result<Function, Allocator,
typename result_of<Function()>::type>::completion_handler_type& h)
: detail::packaged_async_result<Function, Allocator,
typename result_of<Function()>::type>(h)
{
}
};
#define ASIO_PRIVATE_ASYNC_RESULT_DEF(n) \
template <typename Allocator, \
typename Result, ASIO_VARIADIC_TPARAMS(n)> \
class async_result<use_future_t<Allocator>, \
Result(ASIO_VARIADIC_TARGS(n))> \
: public detail::promise_async_result< \
void(ASIO_VARIADIC_DECAY(n)), Allocator> \
{ \
public: \
explicit async_result( \
typename detail::promise_async_result< \
void(ASIO_VARIADIC_DECAY(n)), \
Allocator>::completion_handler_type& h) \
: detail::promise_async_result< \
void(ASIO_VARIADIC_DECAY(n)), Allocator>(h) \
{ \
} \
}; \
\
template <typename Function, typename Allocator, \
typename Result, ASIO_VARIADIC_TPARAMS(n)> \
class async_result<detail::packaged_token<Function, Allocator>, \
Result(ASIO_VARIADIC_TARGS(n))> \
: public detail::packaged_async_result<Function, Allocator, \
typename result_of<Function(ASIO_VARIADIC_TARGS(n))>::type> \
{ \
public: \
explicit async_result( \
typename detail::packaged_async_result<Function, Allocator, \
typename result_of<Function(ASIO_VARIADIC_TARGS(n))>::type \
>::completion_handler_type& h) \
: detail::packaged_async_result<Function, Allocator, \
typename result_of<Function(ASIO_VARIADIC_TARGS(n))>::type>(h) \
{ \
} \
}; \
/**/
ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ASYNC_RESULT_DEF)
#undef ASIO_PRIVATE_ASYNC_RESULT_DEF
#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
#if !defined(ASIO_NO_DEPRECATED)
template <typename Allocator, typename Signature>
struct handler_type<use_future_t<Allocator>, Signature>
{
typedef typename async_result<use_future_t<Allocator>,
Signature>::completion_handler_type type;
};
template <typename Signature, typename Allocator>
class async_result<detail::promise_handler<Signature, Allocator> >
: public detail::promise_async_result<Signature, Allocator>
{
public:
typedef typename detail::promise_async_result<
Signature, Allocator>::return_type type;
explicit async_result(
typename detail::promise_async_result<
Signature, Allocator>::completion_handler_type& h)
: detail::promise_async_result<Signature, Allocator>(h)
{
}
};
template <typename Function, typename Allocator, typename Signature>
struct handler_type<detail::packaged_token<Function, Allocator>, Signature>
{
typedef typename async_result<detail::packaged_token<Function, Allocator>,
Signature>::completion_handler_type type;
};
template <typename Function, typename Allocator, typename Result>
class async_result<detail::packaged_handler<Function, Allocator, Result> >
: public detail::packaged_async_result<Function, Allocator, Result>
{
public:
typedef typename detail::packaged_async_result<
Function, Allocator, Result>::return_type type;
explicit async_result(
typename detail::packaged_async_result<
Function, Allocator, Result>::completion_handler_type& h)
: detail::packaged_async_result<Function, Allocator, Result>(h)
{
}
};
#endif // !defined(ASIO_NO_DEPRECATED)
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_USE_FUTURE_HPP

View File

@ -0,0 +1,674 @@
//
// impl/write.hpp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_WRITE_HPP
#define ASIO_IMPL_WRITE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/associated_allocator.hpp"
#include "asio/associated_executor.hpp"
#include "asio/buffer.hpp"
#include "asio/completion_condition.hpp"
#include "asio/detail/array_fwd.hpp"
#include "asio/detail/base_from_completion_cond.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/consuming_buffers.hpp"
#include "asio/detail/dependent_type.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_cont_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/handler_type_requirements.hpp"
#include "asio/detail/throw_error.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail
{
template <typename SyncWriteStream, typename ConstBufferSequence,
typename ConstBufferIterator, typename CompletionCondition>
std::size_t write_buffer_sequence(SyncWriteStream& s,
const ConstBufferSequence& buffers, const ConstBufferIterator&,
CompletionCondition completion_condition, asio::error_code& ec)
{
ec = asio::error_code();
asio::detail::consuming_buffers<const_buffer,
ConstBufferSequence, ConstBufferIterator> tmp(buffers);
while (!tmp.empty())
{
if (std::size_t max_size = detail::adapt_completion_condition_result(
completion_condition(ec, tmp.total_consumed())))
tmp.consume(s.write_some(tmp.prepare(max_size), ec));
else
break;
}
return tmp.total_consumed();;
}
} // namespace detail
template <typename SyncWriteStream, typename ConstBufferSequence,
typename CompletionCondition>
inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
CompletionCondition completion_condition, asio::error_code& ec,
typename enable_if<
is_const_buffer_sequence<ConstBufferSequence>::value
>::type*)
{
return detail::write_buffer_sequence(s, buffers,
asio::buffer_sequence_begin(buffers), completion_condition, ec);
}
template <typename SyncWriteStream, typename ConstBufferSequence>
inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
typename enable_if<
is_const_buffer_sequence<ConstBufferSequence>::value
>::type*)
{
asio::error_code ec;
std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);
asio::detail::throw_error(ec, "write");
return bytes_transferred;
}
template <typename SyncWriteStream, typename ConstBufferSequence>
inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
asio::error_code& ec,
typename enable_if<
is_const_buffer_sequence<ConstBufferSequence>::value
>::type*)
{
return write(s, buffers, transfer_all(), ec);
}
template <typename SyncWriteStream, typename ConstBufferSequence,
typename CompletionCondition>
inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
CompletionCondition completion_condition,
typename enable_if<
is_const_buffer_sequence<ConstBufferSequence>::value
>::type*)
{
asio::error_code ec;
std::size_t bytes_transferred = write(s, buffers, completion_condition, ec);
asio::detail::throw_error(ec, "write");
return bytes_transferred;
}
template <typename SyncWriteStream, typename DynamicBuffer,
typename CompletionCondition>
std::size_t write(SyncWriteStream& s,
ASIO_MOVE_ARG(DynamicBuffer) buffers,
CompletionCondition completion_condition, asio::error_code& ec,
typename enable_if<
is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
>::type*)
{
typename decay<DynamicBuffer>::type b(
ASIO_MOVE_CAST(DynamicBuffer)(buffers));
std::size_t bytes_transferred = write(s, b.data(), completion_condition, ec);
b.consume(bytes_transferred);
return bytes_transferred;
}
template <typename SyncWriteStream, typename DynamicBuffer>
inline std::size_t write(SyncWriteStream& s,
ASIO_MOVE_ARG(DynamicBuffer) buffers,
typename enable_if<
is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
>::type*)
{
asio::error_code ec;
std::size_t bytes_transferred = write(s,
ASIO_MOVE_CAST(DynamicBuffer)(buffers),
transfer_all(), ec);
asio::detail::throw_error(ec, "write");
return bytes_transferred;
}
template <typename SyncWriteStream, typename DynamicBuffer>
inline std::size_t write(SyncWriteStream& s,
ASIO_MOVE_ARG(DynamicBuffer) buffers,
asio::error_code& ec,
typename enable_if<
is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
>::type*)
{
return write(s, ASIO_MOVE_CAST(DynamicBuffer)(buffers),
transfer_all(), ec);
}
template <typename SyncWriteStream, typename DynamicBuffer,
typename CompletionCondition>
inline std::size_t write(SyncWriteStream& s,
ASIO_MOVE_ARG(DynamicBuffer) buffers,
CompletionCondition completion_condition,
typename enable_if<
is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
>::type*)
{
asio::error_code ec;
std::size_t bytes_transferred = write(s,
ASIO_MOVE_CAST(DynamicBuffer)(buffers),
completion_condition, ec);
asio::detail::throw_error(ec, "write");
return bytes_transferred;
}
#if !defined(ASIO_NO_EXTENSIONS)
#if !defined(ASIO_NO_IOSTREAM)
template <typename SyncWriteStream, typename Allocator,
typename CompletionCondition>
inline std::size_t write(SyncWriteStream& s,
asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition, asio::error_code& ec)
{
return write(s, basic_streambuf_ref<Allocator>(b), completion_condition, ec);
}
template <typename SyncWriteStream, typename Allocator>
inline std::size_t write(SyncWriteStream& s,
asio::basic_streambuf<Allocator>& b)
{
return write(s, basic_streambuf_ref<Allocator>(b));
}
template <typename SyncWriteStream, typename Allocator>
inline std::size_t write(SyncWriteStream& s,
asio::basic_streambuf<Allocator>& b,
asio::error_code& ec)
{
return write(s, basic_streambuf_ref<Allocator>(b), ec);
}
template <typename SyncWriteStream, typename Allocator,
typename CompletionCondition>
inline std::size_t write(SyncWriteStream& s,
asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition)
{
return write(s, basic_streambuf_ref<Allocator>(b), completion_condition);
}
#endif // !defined(ASIO_NO_IOSTREAM)
#endif // !defined(ASIO_NO_EXTENSIONS)
namespace detail
{
template <typename AsyncWriteStream, typename ConstBufferSequence,
typename ConstBufferIterator, typename CompletionCondition,
typename WriteHandler>
class write_op
: detail::base_from_completion_cond<CompletionCondition>
{
public:
write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,
CompletionCondition completion_condition, WriteHandler& handler)
: detail::base_from_completion_cond<
CompletionCondition>(completion_condition),
stream_(stream),
buffers_(buffers),
start_(0),
handler_(ASIO_MOVE_CAST(WriteHandler)(handler))
{
}
#if defined(ASIO_HAS_MOVE)
write_op(const write_op& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
stream_(other.stream_),
buffers_(other.buffers_),
start_(other.start_),
handler_(other.handler_)
{
}
write_op(write_op&& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
stream_(other.stream_),
buffers_(other.buffers_),
start_(other.start_),
handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))
{
}
#endif // defined(ASIO_HAS_MOVE)
void operator()(const asio::error_code& ec,
std::size_t bytes_transferred, int start = 0)
{
std::size_t max_size;
switch (start_ = start)
{
case 1:
max_size = this->check_for_completion(ec, buffers_.total_consumed());
do
{
stream_.async_write_some(buffers_.prepare(max_size),
ASIO_MOVE_CAST(write_op)(*this));
return; default:
buffers_.consume(bytes_transferred);
if ((!ec && bytes_transferred == 0) || buffers_.empty())
break;
max_size = this->check_for_completion(ec, buffers_.total_consumed());
} while (max_size > 0);
handler_(ec, buffers_.total_consumed());
}
}
//private:
AsyncWriteStream& stream_;
asio::detail::consuming_buffers<const_buffer,
ConstBufferSequence, ConstBufferIterator> buffers_;
int start_;
WriteHandler handler_;
};
template <typename AsyncWriteStream, typename ConstBufferSequence,
typename ConstBufferIterator, typename CompletionCondition,
typename WriteHandler>
inline void* asio_handler_allocate(std::size_t size,
write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
CompletionCondition, WriteHandler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename AsyncWriteStream, typename ConstBufferSequence,
typename ConstBufferIterator, typename CompletionCondition,
typename WriteHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
CompletionCondition, WriteHandler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename AsyncWriteStream, typename ConstBufferSequence,
typename ConstBufferIterator, typename CompletionCondition,
typename WriteHandler>
inline bool asio_handler_is_continuation(
write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
CompletionCondition, WriteHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
: asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename AsyncWriteStream,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
inline void asio_handler_invoke(Function& function,
write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
CompletionCondition, WriteHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename AsyncWriteStream,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
inline void asio_handler_invoke(const Function& function,
write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
CompletionCondition, WriteHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename AsyncWriteStream, typename ConstBufferSequence,
typename ConstBufferIterator, typename CompletionCondition,
typename WriteHandler>
inline void start_write_buffer_sequence_op(AsyncWriteStream& stream,
const ConstBufferSequence& buffers, const ConstBufferIterator&,
CompletionCondition completion_condition, WriteHandler& handler)
{
detail::write_op<AsyncWriteStream, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>(
stream, buffers, completion_condition, handler)(
asio::error_code(), 0, 1);
}
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename AsyncWriteStream, typename ConstBufferSequence,
typename ConstBufferIterator, typename CompletionCondition,
typename WriteHandler, typename Allocator>
struct associated_allocator<
detail::write_op<AsyncWriteStream, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>,
Allocator>
{
typedef typename associated_allocator<WriteHandler, Allocator>::type type;
static type get(
const detail::write_op<AsyncWriteStream, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>& h,
const Allocator& a = Allocator()) ASIO_NOEXCEPT
{
return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
}
};
template <typename AsyncWriteStream, typename ConstBufferSequence,
typename ConstBufferIterator, typename CompletionCondition,
typename WriteHandler, typename Executor>
struct associated_executor<
detail::write_op<AsyncWriteStream, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>,
Executor>
{
typedef typename associated_executor<WriteHandler, Executor>::type type;
static type get(
const detail::write_op<AsyncWriteStream, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>& h,
const Executor& ex = Executor()) ASIO_NOEXCEPT
{
return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename AsyncWriteStream, typename ConstBufferSequence,
typename CompletionCondition, typename WriteHandler>
inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (asio::error_code, std::size_t))
async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
CompletionCondition completion_condition,
ASIO_MOVE_ARG(WriteHandler) handler,
typename enable_if<
is_const_buffer_sequence<ConstBufferSequence>::value
>::type*)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
detail::start_write_buffer_sequence_op(s, buffers,
asio::buffer_sequence_begin(buffers), completion_condition,
init.completion_handler);
return init.result.get();
}
template <typename AsyncWriteStream, typename ConstBufferSequence,
typename WriteHandler>
inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (asio::error_code, std::size_t))
async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
ASIO_MOVE_ARG(WriteHandler) handler,
typename enable_if<
is_const_buffer_sequence<ConstBufferSequence>::value
>::type*)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
detail::start_write_buffer_sequence_op(s, buffers,
asio::buffer_sequence_begin(buffers), transfer_all(),
init.completion_handler);
return init.result.get();
}
namespace detail
{
template <typename AsyncWriteStream, typename DynamicBuffer,
typename CompletionCondition, typename WriteHandler>
class write_dynbuf_op
{
public:
template <typename BufferSequence>
write_dynbuf_op(AsyncWriteStream& stream,
ASIO_MOVE_ARG(BufferSequence) buffers,
CompletionCondition completion_condition, WriteHandler& handler)
: stream_(stream),
buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),
completion_condition_(
ASIO_MOVE_CAST(CompletionCondition)(completion_condition)),
handler_(ASIO_MOVE_CAST(WriteHandler)(handler))
{
}
#if defined(ASIO_HAS_MOVE)
write_dynbuf_op(const write_dynbuf_op& other)
: stream_(other.stream_),
buffers_(other.buffers_),
completion_condition_(other.completion_condition_),
handler_(other.handler_)
{
}
write_dynbuf_op(write_dynbuf_op&& other)
: stream_(other.stream_),
buffers_(ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
completion_condition_(
ASIO_MOVE_CAST(CompletionCondition)(
other.completion_condition_)),
handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))
{
}
#endif // defined(ASIO_HAS_MOVE)
void operator()(const asio::error_code& ec,
std::size_t bytes_transferred, int start = 0)
{
switch (start)
{
case 1:
async_write(stream_, buffers_.data(), completion_condition_,
ASIO_MOVE_CAST(write_dynbuf_op)(*this));
return; default:
buffers_.consume(bytes_transferred);
handler_(ec, static_cast<const std::size_t&>(bytes_transferred));
}
}
//private:
AsyncWriteStream& stream_;
DynamicBuffer buffers_;
CompletionCondition completion_condition_;
WriteHandler handler_;
};
template <typename AsyncWriteStream, typename DynamicBuffer,
typename CompletionCondition, typename WriteHandler>
inline void* asio_handler_allocate(std::size_t size,
write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
CompletionCondition, WriteHandler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename AsyncWriteStream, typename DynamicBuffer,
typename CompletionCondition, typename WriteHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
CompletionCondition, WriteHandler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename AsyncWriteStream, typename DynamicBuffer,
typename CompletionCondition, typename WriteHandler>
inline bool asio_handler_is_continuation(
write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
CompletionCondition, WriteHandler>* this_handler)
{
return asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename AsyncWriteStream,
typename DynamicBuffer, typename CompletionCondition,
typename WriteHandler>
inline void asio_handler_invoke(Function& function,
write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
CompletionCondition, WriteHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename AsyncWriteStream,
typename DynamicBuffer, typename CompletionCondition,
typename WriteHandler>
inline void asio_handler_invoke(const Function& function,
write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
CompletionCondition, WriteHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename AsyncWriteStream, typename DynamicBuffer,
typename CompletionCondition, typename WriteHandler, typename Allocator>
struct associated_allocator<
detail::write_dynbuf_op<AsyncWriteStream,
DynamicBuffer, CompletionCondition, WriteHandler>,
Allocator>
{
typedef typename associated_allocator<WriteHandler, Allocator>::type type;
static type get(
const detail::write_dynbuf_op<AsyncWriteStream,
DynamicBuffer, CompletionCondition, WriteHandler>& h,
const Allocator& a = Allocator()) ASIO_NOEXCEPT
{
return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
}
};
template <typename AsyncWriteStream, typename DynamicBuffer,
typename CompletionCondition, typename WriteHandler, typename Executor>
struct associated_executor<
detail::write_dynbuf_op<AsyncWriteStream,
DynamicBuffer, CompletionCondition, WriteHandler>,
Executor>
{
typedef typename associated_executor<WriteHandler, Executor>::type type;
static type get(
const detail::write_dynbuf_op<AsyncWriteStream,
DynamicBuffer, CompletionCondition, WriteHandler>& h,
const Executor& ex = Executor()) ASIO_NOEXCEPT
{
return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename AsyncWriteStream,
typename DynamicBuffer, typename WriteHandler>
inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (asio::error_code, std::size_t))
async_write(AsyncWriteStream& s,
ASIO_MOVE_ARG(DynamicBuffer) buffers,
ASIO_MOVE_ARG(WriteHandler) handler,
typename enable_if<
is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
>::type*)
{
return async_write(s,
ASIO_MOVE_CAST(DynamicBuffer)(buffers),
transfer_all(), ASIO_MOVE_CAST(WriteHandler)(handler));
}
template <typename AsyncWriteStream, typename DynamicBuffer,
typename CompletionCondition, typename WriteHandler>
inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (asio::error_code, std::size_t))
async_write(AsyncWriteStream& s,
ASIO_MOVE_ARG(DynamicBuffer) buffers,
CompletionCondition completion_condition,
ASIO_MOVE_ARG(WriteHandler) handler,
typename enable_if<
is_dynamic_buffer<typename decay<DynamicBuffer>::type>::value
>::type*)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
detail::write_dynbuf_op<AsyncWriteStream,
typename decay<DynamicBuffer>::type,
CompletionCondition, ASIO_HANDLER_TYPE(
WriteHandler, void (asio::error_code, std::size_t))>(
s, ASIO_MOVE_CAST(DynamicBuffer)(buffers),
completion_condition, init.completion_handler)(
asio::error_code(), 0, 1);
return init.result.get();
}
#if !defined(ASIO_NO_EXTENSIONS)
#if !defined(ASIO_NO_IOSTREAM)
template <typename AsyncWriteStream, typename Allocator, typename WriteHandler>
inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (asio::error_code, std::size_t))
async_write(AsyncWriteStream& s,
asio::basic_streambuf<Allocator>& b,
ASIO_MOVE_ARG(WriteHandler) handler)
{
return async_write(s, basic_streambuf_ref<Allocator>(b),
ASIO_MOVE_CAST(WriteHandler)(handler));
}
template <typename AsyncWriteStream, typename Allocator,
typename CompletionCondition, typename WriteHandler>
inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (asio::error_code, std::size_t))
async_write(AsyncWriteStream& s,
asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition,
ASIO_MOVE_ARG(WriteHandler) handler)
{
return async_write(s, basic_streambuf_ref<Allocator>(b),
completion_condition, ASIO_MOVE_CAST(WriteHandler)(handler));
}
#endif // !defined(ASIO_NO_IOSTREAM)
#endif // !defined(ASIO_NO_EXTENSIONS)
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_WRITE_HPP

View File

@ -0,0 +1,572 @@
//
// impl/write_at.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IMPL_WRITE_AT_HPP
#define ASIO_IMPL_WRITE_AT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/associated_allocator.hpp"
#include "asio/associated_executor.hpp"
#include "asio/buffer.hpp"
#include "asio/completion_condition.hpp"
#include "asio/detail/array_fwd.hpp"
#include "asio/detail/base_from_completion_cond.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/consuming_buffers.hpp"
#include "asio/detail/dependent_type.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_cont_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/handler_type_requirements.hpp"
#include "asio/detail/throw_error.hpp"
#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail
{
template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
typename ConstBufferIterator, typename CompletionCondition>
std::size_t write_at_buffer_sequence(SyncRandomAccessWriteDevice& d,
uint64_t offset, const ConstBufferSequence& buffers,
const ConstBufferIterator&, CompletionCondition completion_condition,
asio::error_code& ec)
{
ec = asio::error_code();
asio::detail::consuming_buffers<const_buffer,
ConstBufferSequence, ConstBufferIterator> tmp(buffers);
while (!tmp.empty())
{
if (std::size_t max_size = detail::adapt_completion_condition_result(
completion_condition(ec, tmp.total_consumed())))
{
tmp.consume(d.write_some_at(offset + tmp.total_consumed(),
tmp.prepare(max_size), ec));
}
else
break;
}
return tmp.total_consumed();;
}
} // namespace detail
template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
typename CompletionCondition>
std::size_t write_at(SyncRandomAccessWriteDevice& d,
uint64_t offset, const ConstBufferSequence& buffers,
CompletionCondition completion_condition, asio::error_code& ec)
{
return detail::write_at_buffer_sequence(d, offset, buffers,
asio::buffer_sequence_begin(buffers), completion_condition, ec);
}
template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>
inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
uint64_t offset, const ConstBufferSequence& buffers)
{
asio::error_code ec;
std::size_t bytes_transferred = write_at(
d, offset, buffers, transfer_all(), ec);
asio::detail::throw_error(ec, "write_at");
return bytes_transferred;
}
template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>
inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
uint64_t offset, const ConstBufferSequence& buffers,
asio::error_code& ec)
{
return write_at(d, offset, buffers, transfer_all(), ec);
}
template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
typename CompletionCondition>
inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
uint64_t offset, const ConstBufferSequence& buffers,
CompletionCondition completion_condition)
{
asio::error_code ec;
std::size_t bytes_transferred = write_at(
d, offset, buffers, completion_condition, ec);
asio::detail::throw_error(ec, "write_at");
return bytes_transferred;
}
#if !defined(ASIO_NO_EXTENSIONS)
#if !defined(ASIO_NO_IOSTREAM)
template <typename SyncRandomAccessWriteDevice, typename Allocator,
typename CompletionCondition>
std::size_t write_at(SyncRandomAccessWriteDevice& d,
uint64_t offset, asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition, asio::error_code& ec)
{
std::size_t bytes_transferred = write_at(
d, offset, b.data(), completion_condition, ec);
b.consume(bytes_transferred);
return bytes_transferred;
}
template <typename SyncRandomAccessWriteDevice, typename Allocator>
inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
uint64_t offset, asio::basic_streambuf<Allocator>& b)
{
asio::error_code ec;
std::size_t bytes_transferred = write_at(d, offset, b, transfer_all(), ec);
asio::detail::throw_error(ec, "write_at");
return bytes_transferred;
}
template <typename SyncRandomAccessWriteDevice, typename Allocator>
inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
uint64_t offset, asio::basic_streambuf<Allocator>& b,
asio::error_code& ec)
{
return write_at(d, offset, b, transfer_all(), ec);
}
template <typename SyncRandomAccessWriteDevice, typename Allocator,
typename CompletionCondition>
inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
uint64_t offset, asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition)
{
asio::error_code ec;
std::size_t bytes_transferred = write_at(
d, offset, b, completion_condition, ec);
asio::detail::throw_error(ec, "write_at");
return bytes_transferred;
}
#endif // !defined(ASIO_NO_IOSTREAM)
#endif // !defined(ASIO_NO_EXTENSIONS)
namespace detail
{
template <typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
class write_at_op
: detail::base_from_completion_cond<CompletionCondition>
{
public:
write_at_op(AsyncRandomAccessWriteDevice& device,
uint64_t offset, const ConstBufferSequence& buffers,
CompletionCondition completion_condition, WriteHandler& handler)
: detail::base_from_completion_cond<
CompletionCondition>(completion_condition),
device_(device),
offset_(offset),
buffers_(buffers),
start_(0),
handler_(ASIO_MOVE_CAST(WriteHandler)(handler))
{
}
#if defined(ASIO_HAS_MOVE)
write_at_op(const write_at_op& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
device_(other.device_),
offset_(other.offset_),
buffers_(other.buffers_),
start_(other.start_),
handler_(other.handler_)
{
}
write_at_op(write_at_op&& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
device_(other.device_),
offset_(other.offset_),
buffers_(other.buffers_),
start_(other.start_),
handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))
{
}
#endif // defined(ASIO_HAS_MOVE)
void operator()(const asio::error_code& ec,
std::size_t bytes_transferred, int start = 0)
{
std::size_t max_size;
switch (start_ = start)
{
case 1:
max_size = this->check_for_completion(ec, buffers_.total_consumed());
do
{
device_.async_write_some_at(
offset_ + buffers_.total_consumed(), buffers_.prepare(max_size),
ASIO_MOVE_CAST(write_at_op)(*this));
return; default:
buffers_.consume(bytes_transferred);
if ((!ec && bytes_transferred == 0) || buffers_.empty())
break;
max_size = this->check_for_completion(ec, buffers_.total_consumed());
} while (max_size > 0);
handler_(ec, buffers_.total_consumed());
}
}
//private:
AsyncRandomAccessWriteDevice& device_;
uint64_t offset_;
asio::detail::consuming_buffers<const_buffer,
ConstBufferSequence, ConstBufferIterator> buffers_;
int start_;
WriteHandler handler_;
};
template <typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
inline void* asio_handler_allocate(std::size_t size,
write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
inline bool asio_handler_is_continuation(
write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
: asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
inline void asio_handler_invoke(Function& function,
write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
inline void asio_handler_invoke(const Function& function,
write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
inline void start_write_at_buffer_sequence_op(AsyncRandomAccessWriteDevice& d,
uint64_t offset, const ConstBufferSequence& buffers,
const ConstBufferIterator&, CompletionCondition completion_condition,
WriteHandler& handler)
{
detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>(
d, offset, buffers, completion_condition, handler)(
asio::error_code(), 0, 1);
}
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler, typename Allocator>
struct associated_allocator<
detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>,
Allocator>
{
typedef typename associated_allocator<WriteHandler, Allocator>::type type;
static type get(
const detail::write_at_op<AsyncRandomAccessWriteDevice,
ConstBufferSequence, ConstBufferIterator,
CompletionCondition, WriteHandler>& h,
const Allocator& a = Allocator()) ASIO_NOEXCEPT
{
return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
}
};
template <typename AsyncRandomAccessWriteDevice,
typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler, typename Executor>
struct associated_executor<
detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
ConstBufferIterator, CompletionCondition, WriteHandler>,
Executor>
{
typedef typename associated_executor<WriteHandler, Executor>::type type;
static type get(
const detail::write_at_op<AsyncRandomAccessWriteDevice,
ConstBufferSequence, ConstBufferIterator,
CompletionCondition, WriteHandler>& h,
const Executor& ex = Executor()) ASIO_NOEXCEPT
{
return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
typename CompletionCondition, typename WriteHandler>
inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (asio::error_code, std::size_t))
async_write_at(AsyncRandomAccessWriteDevice& d,
uint64_t offset, const ConstBufferSequence& buffers,
CompletionCondition completion_condition,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
detail::start_write_at_buffer_sequence_op(d, offset, buffers,
asio::buffer_sequence_begin(buffers), completion_condition,
init.completion_handler);
return init.result.get();
}
template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
typename WriteHandler>
inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (asio::error_code, std::size_t))
async_write_at(AsyncRandomAccessWriteDevice& d,
uint64_t offset, const ConstBufferSequence& buffers,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
detail::start_write_at_buffer_sequence_op(d, offset, buffers,
asio::buffer_sequence_begin(buffers), transfer_all(),
init.completion_handler);
return init.result.get();
}
#if !defined(ASIO_NO_EXTENSIONS)
#if !defined(ASIO_NO_IOSTREAM)
namespace detail
{
template <typename Allocator, typename WriteHandler>
class write_at_streambuf_op
{
public:
write_at_streambuf_op(
asio::basic_streambuf<Allocator>& streambuf,
WriteHandler& handler)
: streambuf_(streambuf),
handler_(ASIO_MOVE_CAST(WriteHandler)(handler))
{
}
#if defined(ASIO_HAS_MOVE)
write_at_streambuf_op(const write_at_streambuf_op& other)
: streambuf_(other.streambuf_),
handler_(other.handler_)
{
}
write_at_streambuf_op(write_at_streambuf_op&& other)
: streambuf_(other.streambuf_),
handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))
{
}
#endif // defined(ASIO_HAS_MOVE)
void operator()(const asio::error_code& ec,
const std::size_t bytes_transferred)
{
streambuf_.consume(bytes_transferred);
handler_(ec, bytes_transferred);
}
//private:
asio::basic_streambuf<Allocator>& streambuf_;
WriteHandler handler_;
};
template <typename Allocator, typename WriteHandler>
inline void* asio_handler_allocate(std::size_t size,
write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename Allocator, typename WriteHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename Allocator, typename WriteHandler>
inline bool asio_handler_is_continuation(
write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
{
return asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
template <typename Function, typename Allocator, typename WriteHandler>
inline void asio_handler_invoke(Function& function,
write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename Allocator, typename WriteHandler>
inline void asio_handler_invoke(const Function& function,
write_at_streambuf_op<Allocator, WriteHandler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Allocator, typename WriteHandler>
inline write_at_streambuf_op<Allocator, WriteHandler>
make_write_at_streambuf_op(
asio::basic_streambuf<Allocator>& b, WriteHandler handler)
{
return write_at_streambuf_op<Allocator, WriteHandler>(b, handler);
}
} // namespace detail
#if !defined(GENERATING_DOCUMENTATION)
template <typename Allocator, typename WriteHandler, typename Allocator1>
struct associated_allocator<
detail::write_at_streambuf_op<Allocator, WriteHandler>,
Allocator1>
{
typedef typename associated_allocator<WriteHandler, Allocator1>::type type;
static type get(
const detail::write_at_streambuf_op<Allocator, WriteHandler>& h,
const Allocator1& a = Allocator1()) ASIO_NOEXCEPT
{
return associated_allocator<WriteHandler, Allocator1>::get(h.handler_, a);
}
};
template <typename Executor, typename WriteHandler, typename Executor1>
struct associated_executor<
detail::write_at_streambuf_op<Executor, WriteHandler>,
Executor1>
{
typedef typename associated_executor<WriteHandler, Executor1>::type type;
static type get(
const detail::write_at_streambuf_op<Executor, WriteHandler>& h,
const Executor1& ex = Executor1()) ASIO_NOEXCEPT
{
return associated_executor<WriteHandler, Executor1>::get(h.handler_, ex);
}
};
#endif // !defined(GENERATING_DOCUMENTATION)
template <typename AsyncRandomAccessWriteDevice, typename Allocator,
typename CompletionCondition, typename WriteHandler>
inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (asio::error_code, std::size_t))
async_write_at(AsyncRandomAccessWriteDevice& d,
uint64_t offset, asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
async_write_at(d, offset, b.data(), completion_condition,
detail::write_at_streambuf_op<Allocator, ASIO_HANDLER_TYPE(
WriteHandler, void (asio::error_code, std::size_t))>(
b, init.completion_handler));
return init.result.get();
}
template <typename AsyncRandomAccessWriteDevice, typename Allocator,
typename WriteHandler>
inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (asio::error_code, std::size_t))
async_write_at(AsyncRandomAccessWriteDevice& d,
uint64_t offset, asio::basic_streambuf<Allocator>& b,
ASIO_MOVE_ARG(WriteHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
async_completion<WriteHandler,
void (asio::error_code, std::size_t)> init(handler);
async_write_at(d, offset, b.data(), transfer_all(),
detail::write_at_streambuf_op<Allocator, ASIO_HANDLER_TYPE(
WriteHandler, void (asio::error_code, std::size_t))>(
b, init.completion_handler));
return init.result.get();
}
#endif // !defined(ASIO_NO_IOSTREAM)
#endif // !defined(ASIO_NO_EXTENSIONS)
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IMPL_WRITE_AT_HPP