Add move support for windows handles.

This commit is contained in:
Christopher Kohlhoff 2011-03-07 12:24:52 +11:00
parent 1df0c5c6ad
commit b8eabb3e98
10 changed files with 271 additions and 33 deletions

View File

@ -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)
{

View File

@ -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);

View File

@ -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.

View File

@ -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:

View File

@ -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));
}
};

View File

@ -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));
}
};

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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;

View File

@ -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;