Add move support for windows handles.
This commit is contained in:
parent
1df0c5c6ad
commit
b8eabb3e98
@ -99,6 +99,64 @@ void win_iocp_handle_service::construct(
|
||||
impl_list_ = &impl;
|
||||
}
|
||||
|
||||
void win_iocp_handle_service::move_construct(
|
||||
win_iocp_handle_service::implementation_type& impl,
|
||||
win_iocp_handle_service::implementation_type& other_impl)
|
||||
{
|
||||
impl.handle_ = other_impl.handle_;
|
||||
other_impl.handle_ = INVALID_HANDLE_VALUE;
|
||||
|
||||
impl.safe_cancellation_thread_id_ = other_impl.safe_cancellation_thread_id_;
|
||||
other_impl.safe_cancellation_thread_id_ = 0;
|
||||
|
||||
// Insert implementation into linked list of all implementations.
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
impl.next_ = impl_list_;
|
||||
impl.prev_ = 0;
|
||||
if (impl_list_)
|
||||
impl_list_->prev_ = &impl;
|
||||
impl_list_ = &impl;
|
||||
}
|
||||
|
||||
void win_iocp_handle_service::move_assign(
|
||||
win_iocp_handle_service::implementation_type& impl,
|
||||
win_iocp_handle_service& other_service,
|
||||
win_iocp_handle_service::implementation_type& other_impl)
|
||||
{
|
||||
close_for_destruction(impl);
|
||||
|
||||
if (this != &other_service)
|
||||
{
|
||||
// Remove implementation from linked list of all implementations.
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
if (impl_list_ == &impl)
|
||||
impl_list_ = impl.next_;
|
||||
if (impl.prev_)
|
||||
impl.prev_->next_ = impl.next_;
|
||||
if (impl.next_)
|
||||
impl.next_->prev_= impl.prev_;
|
||||
impl.next_ = 0;
|
||||
impl.prev_ = 0;
|
||||
}
|
||||
|
||||
impl.handle_ = other_impl.handle_;
|
||||
other_impl.handle_ = INVALID_HANDLE_VALUE;
|
||||
|
||||
impl.safe_cancellation_thread_id_ = other_impl.safe_cancellation_thread_id_;
|
||||
other_impl.safe_cancellation_thread_id_ = 0;
|
||||
|
||||
if (this != &other_service)
|
||||
{
|
||||
// Insert implementation into linked list of all implementations.
|
||||
asio::detail::mutex::scoped_lock lock(other_service.mutex_);
|
||||
impl.next_ = other_service.impl_list_;
|
||||
impl.prev_ = 0;
|
||||
if (other_service.impl_list_)
|
||||
other_service.impl_list_->prev_ = &impl;
|
||||
other_service.impl_list_ = &impl;
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_handle_service::destroy(
|
||||
win_iocp_handle_service::implementation_type& impl)
|
||||
{
|
||||
|
@ -81,6 +81,15 @@ public:
|
||||
// Construct a new handle implementation.
|
||||
ASIO_DECL void construct(implementation_type& impl);
|
||||
|
||||
// Move-construct a new handle implementation.
|
||||
ASIO_DECL void move_construct(implementation_type& impl,
|
||||
implementation_type& other_impl);
|
||||
|
||||
// Move-assign from another handle implementation.
|
||||
ASIO_DECL void move_assign(implementation_type& impl,
|
||||
win_iocp_handle_service& other_service,
|
||||
implementation_type& other_impl);
|
||||
|
||||
// Destroy a handle implementation.
|
||||
ASIO_DECL void destroy(implementation_type& impl);
|
||||
|
||||
|
@ -109,7 +109,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
/// Move-assign a basic_stream_descriptor from another.
|
||||
/// Move-assign a basic_stream_descriptor from another.
|
||||
/**
|
||||
* This assignment operator moves a stream descriptor from one object to
|
||||
* another.
|
||||
|
@ -82,10 +82,45 @@ public:
|
||||
: basic_io_object<HandleService>(io_service)
|
||||
{
|
||||
asio::error_code ec;
|
||||
this->service.assign(this->implementation, handle, ec);
|
||||
this->get_service().assign(this->get_implementation(), handle, ec);
|
||||
asio::detail::throw_error(ec, "assign");
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
/// Move-construct a basic_handle from another.
|
||||
/**
|
||||
* This constructor moves a handle from one object to another.
|
||||
*
|
||||
* @param other The other basic_handle object from which the move will occur.
|
||||
*
|
||||
* @note Following the move, the valid operations for the other object are:
|
||||
* @li Using it as the target of a move assignment.
|
||||
* @li Destruction.
|
||||
*/
|
||||
basic_handle(basic_handle&& other)
|
||||
: basic_io_object<HandleService>(
|
||||
ASIO_MOVE_CAST(basic_handle)(other))
|
||||
{
|
||||
}
|
||||
|
||||
/// Move-assign a basic_handle from another.
|
||||
/**
|
||||
* This assignment operator moves a handle from one object to another.
|
||||
*
|
||||
* @param other The other basic_handle object from which the move will occur.
|
||||
*
|
||||
* @note Following the move, the valid operations for the other object are:
|
||||
* @li Using it as the target of a move assignment.
|
||||
* @li Destruction.
|
||||
*/
|
||||
basic_handle& operator=(basic_handle&& other)
|
||||
{
|
||||
basic_io_object<HandleService>::operator=(
|
||||
ASIO_MOVE_CAST(basic_handle)(other));
|
||||
return *this;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Get a reference to the lowest layer.
|
||||
/**
|
||||
* This function returns a reference to the lowest layer in a stack of
|
||||
@ -125,7 +160,7 @@ public:
|
||||
void assign(const native_handle_type& handle)
|
||||
{
|
||||
asio::error_code ec;
|
||||
this->service.assign(this->implementation, handle, ec);
|
||||
this->get_service().assign(this->get_implementation(), handle, ec);
|
||||
asio::detail::throw_error(ec, "assign");
|
||||
}
|
||||
|
||||
@ -140,13 +175,13 @@ public:
|
||||
asio::error_code assign(const native_handle_type& handle,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
return this->service.assign(this->implementation, handle, ec);
|
||||
return this->get_service().assign(this->get_implementation(), handle, ec);
|
||||
}
|
||||
|
||||
/// Determine whether the handle is open.
|
||||
bool is_open() const
|
||||
{
|
||||
return this->service.is_open(this->implementation);
|
||||
return this->get_service().is_open(this->get_implementation());
|
||||
}
|
||||
|
||||
/// Close the handle.
|
||||
@ -160,7 +195,7 @@ public:
|
||||
void close()
|
||||
{
|
||||
asio::error_code ec;
|
||||
this->service.close(this->implementation, ec);
|
||||
this->get_service().close(this->get_implementation(), ec);
|
||||
asio::detail::throw_error(ec, "close");
|
||||
}
|
||||
|
||||
@ -174,7 +209,7 @@ public:
|
||||
*/
|
||||
asio::error_code close(asio::error_code& ec)
|
||||
{
|
||||
return this->service.close(this->implementation, ec);
|
||||
return this->get_service().close(this->get_implementation(), ec);
|
||||
}
|
||||
|
||||
/// (Deprecated: Use native_handle().) Get the native handle representation.
|
||||
@ -185,7 +220,7 @@ public:
|
||||
*/
|
||||
native_type native()
|
||||
{
|
||||
return this->service.native_handle(this->implementation);
|
||||
return this->get_service().native_handle(this->get_implementation());
|
||||
}
|
||||
|
||||
/// Get the native handle representation.
|
||||
@ -196,7 +231,7 @@ public:
|
||||
*/
|
||||
native_handle_type native_handle()
|
||||
{
|
||||
return this->service.native_handle(this->implementation);
|
||||
return this->get_service().native_handle(this->get_implementation());
|
||||
}
|
||||
|
||||
/// Cancel all asynchronous operations associated with the handle.
|
||||
@ -210,7 +245,7 @@ public:
|
||||
void cancel()
|
||||
{
|
||||
asio::error_code ec;
|
||||
this->service.cancel(this->implementation, ec);
|
||||
this->get_service().cancel(this->get_implementation(), ec);
|
||||
asio::detail::throw_error(ec, "cancel");
|
||||
}
|
||||
|
||||
@ -224,7 +259,7 @@ public:
|
||||
*/
|
||||
asio::error_code cancel(asio::error_code& ec)
|
||||
{
|
||||
return this->service.cancel(this->implementation, ec);
|
||||
return this->get_service().cancel(this->get_implementation(), ec);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -87,6 +87,44 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
/// Move-construct a basic_random_access_handle from another.
|
||||
/**
|
||||
* This constructor moves a random-access handle from one object to another.
|
||||
*
|
||||
* @param other The other basic_random_access_handle object from which the
|
||||
* move will occur.
|
||||
*
|
||||
* @note Following the move, the valid operations for the other object are:
|
||||
* @li Using it as the target of a move assignment.
|
||||
* @li Destruction.
|
||||
*/
|
||||
basic_random_access_handle(basic_random_access_handle&& other)
|
||||
: basic_handle<RandomAccessHandleService>(
|
||||
ASIO_MOVE_CAST(basic_random_access_handle)(other))
|
||||
{
|
||||
}
|
||||
|
||||
/// Move-assign a basic_random_access_handle from another.
|
||||
/**
|
||||
* This assignment operator moves a random-access handle from one object to
|
||||
* another.
|
||||
*
|
||||
* @param other The other basic_random_access_handle object from which the
|
||||
* move will occur.
|
||||
*
|
||||
* @note Following the move, the valid operations for the other object are:
|
||||
* @li Using it as the target of a move assignment.
|
||||
* @li Destruction.
|
||||
*/
|
||||
basic_random_access_handle& operator=(basic_random_access_handle&& other)
|
||||
{
|
||||
basic_handle<RandomAccessHandleService>::operator=(
|
||||
ASIO_MOVE_CAST(basic_random_access_handle)(other));
|
||||
return *this;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Write some data to the handle at the specified offset.
|
||||
/**
|
||||
* This function is used to write data to the random-access handle. The
|
||||
@ -121,8 +159,8 @@ public:
|
||||
const ConstBufferSequence& buffers)
|
||||
{
|
||||
asio::error_code ec;
|
||||
std::size_t s = this->service.write_some_at(
|
||||
this->implementation, offset, buffers, ec);
|
||||
std::size_t s = this->get_service().write_some_at(
|
||||
this->get_implementation(), offset, buffers, ec);
|
||||
asio::detail::throw_error(ec, "write_some_at");
|
||||
return s;
|
||||
}
|
||||
@ -149,8 +187,8 @@ public:
|
||||
std::size_t write_some_at(boost::uint64_t offset,
|
||||
const ConstBufferSequence& buffers, asio::error_code& ec)
|
||||
{
|
||||
return this->service.write_some_at(
|
||||
this->implementation, offset, buffers, ec);
|
||||
return this->get_service().write_some_at(
|
||||
this->get_implementation(), offset, buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous write at the specified offset.
|
||||
@ -198,7 +236,7 @@ public:
|
||||
// not meet the documented type requirements for a WriteHandler.
|
||||
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
|
||||
|
||||
this->service.async_write_some_at(this->implementation,
|
||||
this->get_service().async_write_some_at(this->get_implementation(),
|
||||
offset, buffers, ASIO_MOVE_CAST(WriteHandler)(handler));
|
||||
}
|
||||
|
||||
@ -237,8 +275,8 @@ public:
|
||||
const MutableBufferSequence& buffers)
|
||||
{
|
||||
asio::error_code ec;
|
||||
std::size_t s = this->service.read_some_at(
|
||||
this->implementation, offset, buffers, ec);
|
||||
std::size_t s = this->get_service().read_some_at(
|
||||
this->get_implementation(), offset, buffers, ec);
|
||||
asio::detail::throw_error(ec, "read_some_at");
|
||||
return s;
|
||||
}
|
||||
@ -266,8 +304,8 @@ public:
|
||||
std::size_t read_some_at(boost::uint64_t offset,
|
||||
const MutableBufferSequence& buffers, asio::error_code& ec)
|
||||
{
|
||||
return this->service.read_some_at(
|
||||
this->implementation, offset, buffers, ec);
|
||||
return this->get_service().read_some_at(
|
||||
this->get_implementation(), offset, buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous read at the specified offset.
|
||||
@ -316,7 +354,7 @@ public:
|
||||
// not meet the documented type requirements for a ReadHandler.
|
||||
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
|
||||
|
||||
this->service.async_read_some_at(this->implementation,
|
||||
this->get_service().async_read_some_at(this->get_implementation(),
|
||||
offset, buffers, ASIO_MOVE_CAST(ReadHandler)(handler));
|
||||
}
|
||||
};
|
||||
|
@ -88,6 +88,44 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
/// Move-construct a basic_stream_handle from another.
|
||||
/**
|
||||
* This constructor moves a stream handle from one object to another.
|
||||
*
|
||||
* @param other The other basic_stream_handle object from which the move
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the valid operations for the other object are:
|
||||
* @li Using it as the target of a move assignment.
|
||||
* @li Destruction.
|
||||
*/
|
||||
basic_stream_handle(basic_stream_handle&& other)
|
||||
: basic_handle<StreamHandleService>(
|
||||
ASIO_MOVE_CAST(basic_stream_handle)(other))
|
||||
{
|
||||
}
|
||||
|
||||
/// Move-assign a basic_stream_handle from another.
|
||||
/**
|
||||
* This assignment operator moves a stream handle from one object to
|
||||
* another.
|
||||
*
|
||||
* @param other The other basic_stream_handle object from which the move
|
||||
* will occur.
|
||||
*
|
||||
* @note Following the move, the valid operations for the other object are:
|
||||
* @li Using it as the target of a move assignment.
|
||||
* @li Destruction.
|
||||
*/
|
||||
basic_stream_handle& operator=(basic_stream_handle&& other)
|
||||
{
|
||||
basic_handle<StreamHandleService>::operator=(
|
||||
ASIO_MOVE_CAST(basic_stream_handle)(other));
|
||||
return *this;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Write some data to the handle.
|
||||
/**
|
||||
* This function is used to write data to the stream handle. The function call
|
||||
@ -119,7 +157,8 @@ public:
|
||||
std::size_t write_some(const ConstBufferSequence& buffers)
|
||||
{
|
||||
asio::error_code ec;
|
||||
std::size_t s = this->service.write_some(this->implementation, buffers, ec);
|
||||
std::size_t s = this->get_service().write_some(
|
||||
this->get_implementation(), buffers, ec);
|
||||
asio::detail::throw_error(ec, "write_some");
|
||||
return s;
|
||||
}
|
||||
@ -144,7 +183,8 @@ public:
|
||||
std::size_t write_some(const ConstBufferSequence& buffers,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
return this->service.write_some(this->implementation, buffers, ec);
|
||||
return this->get_service().write_some(
|
||||
this->get_implementation(), buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous write.
|
||||
@ -190,8 +230,8 @@ public:
|
||||
// not meet the documented type requirements for a WriteHandler.
|
||||
ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
|
||||
|
||||
this->service.async_write_some(this->implementation, buffers,
|
||||
ASIO_MOVE_CAST(WriteHandler)(handler));
|
||||
this->get_service().async_write_some(this->get_implementation(),
|
||||
buffers, ASIO_MOVE_CAST(WriteHandler)(handler));
|
||||
}
|
||||
|
||||
/// Read some data from the handle.
|
||||
@ -226,7 +266,8 @@ public:
|
||||
std::size_t read_some(const MutableBufferSequence& buffers)
|
||||
{
|
||||
asio::error_code ec;
|
||||
std::size_t s = this->service.read_some(this->implementation, buffers, ec);
|
||||
std::size_t s = this->get_service().read_some(
|
||||
this->get_implementation(), buffers, ec);
|
||||
asio::detail::throw_error(ec, "read_some");
|
||||
return s;
|
||||
}
|
||||
@ -252,7 +293,8 @@ public:
|
||||
std::size_t read_some(const MutableBufferSequence& buffers,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
return this->service.read_some(this->implementation, buffers, ec);
|
||||
return this->get_service().read_some(
|
||||
this->get_implementation(), buffers, ec);
|
||||
}
|
||||
|
||||
/// Start an asynchronous read.
|
||||
@ -299,8 +341,8 @@ public:
|
||||
// not meet the documented type requirements for a ReadHandler.
|
||||
ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
|
||||
|
||||
this->service.async_read_some(this->implementation, buffers,
|
||||
ASIO_MOVE_CAST(ReadHandler)(handler));
|
||||
this->get_service().async_read_some(this->get_implementation(),
|
||||
buffers, ASIO_MOVE_CAST(ReadHandler)(handler));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -86,6 +86,23 @@ public:
|
||||
service_impl_.construct(impl);
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
/// Move-construct a new random-access handle implementation.
|
||||
void move_construct(implementation_type& impl,
|
||||
implementation_type& other_impl)
|
||||
{
|
||||
service_impl_.move_construct(impl, other_impl);
|
||||
}
|
||||
|
||||
/// Move-assign from another random-access handle implementation.
|
||||
void move_assign(implementation_type& impl,
|
||||
random_access_handle_service& other_service,
|
||||
implementation_type& other_impl)
|
||||
{
|
||||
service_impl_.move_assign(impl, other_service.service_impl_, other_impl);
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Destroy a random-access handle implementation.
|
||||
void destroy(implementation_type& impl)
|
||||
{
|
||||
|
@ -83,6 +83,23 @@ public:
|
||||
service_impl_.construct(impl);
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
/// Move-construct a new stream handle implementation.
|
||||
void move_construct(implementation_type& impl,
|
||||
implementation_type& other_impl)
|
||||
{
|
||||
service_impl_.move_construct(impl, other_impl);
|
||||
}
|
||||
|
||||
/// Move-assign from another stream handle implementation.
|
||||
void move_assign(implementation_type& impl,
|
||||
stream_handle_service& other_service,
|
||||
implementation_type& other_impl)
|
||||
{
|
||||
service_impl_.move_assign(impl, other_service.service_impl_, other_impl);
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
|
||||
|
||||
/// Destroy a stream handle implementation.
|
||||
void destroy(implementation_type& impl)
|
||||
{
|
||||
|
@ -57,6 +57,17 @@ void test()
|
||||
HANDLE native_handle1 = INVALID_HANDLE_VALUE;
|
||||
win::random_access_handle handle2(ios, native_handle1);
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
win::random_access_handle handle3(std::move(handle2));
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
// basic_random_access_handle operators.
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
handle1 = win::random_access_handle(ios);
|
||||
handle1 = std::move(handle2);
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
// basic_io_object functions.
|
||||
|
||||
io_service& ios_ref = handle1.get_io_service();
|
||||
@ -68,9 +79,9 @@ void test()
|
||||
= handle1.lowest_layer();
|
||||
(void)lowest_layer;
|
||||
|
||||
const win::random_access_handle& handle3 = handle1;
|
||||
const win::random_access_handle& handle4 = handle1;
|
||||
const win::random_access_handle::lowest_layer_type& lowest_layer2
|
||||
= handle3.lowest_layer();
|
||||
= handle4.lowest_layer();
|
||||
(void)lowest_layer2;
|
||||
|
||||
HANDLE native_handle2 = INVALID_HANDLE_VALUE;
|
||||
|
@ -56,6 +56,17 @@ void test()
|
||||
HANDLE native_handle1 = INVALID_HANDLE_VALUE;
|
||||
win::stream_handle handle2(ios, native_handle1);
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
win::stream_handle handle3(std::move(handle2));
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
// basic_stream_handle operators.
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
handle1 = win::stream_handle(ios);
|
||||
handle1 = std::move(handle2);
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
// basic_io_object functions.
|
||||
|
||||
io_service& ios_ref = handle1.get_io_service();
|
||||
@ -67,9 +78,9 @@ void test()
|
||||
= handle1.lowest_layer();
|
||||
(void)lowest_layer;
|
||||
|
||||
const win::stream_handle& handle3 = handle1;
|
||||
const win::stream_handle& handle4 = handle1;
|
||||
const win::stream_handle::lowest_layer_type& lowest_layer2
|
||||
= handle3.lowest_layer();
|
||||
= handle4.lowest_layer();
|
||||
(void)lowest_layer2;
|
||||
|
||||
HANDLE native_handle2 = INVALID_HANDLE_VALUE;
|
||||
|
Loading…
Reference in New Issue
Block a user