sync asio

This commit is contained in:
Marcos Pinto 2007-10-29 03:10:12 +00:00
commit c059d5162b
29 changed files with 308 additions and 148 deletions

View file

@ -732,8 +732,8 @@ public:
* completes. Copies will be made of the handler as required. The function * completes. Copies will be made of the handler as required. The function
* signature of the handler must be: * signature of the handler must be:
* @code void handler( * @code void handler(
* const asio::system_error& error, // Result of operation. * const asio::error_code& error, // Result of operation.
* std::size_t bytes_transferred // Number of bytes received. * std::size_t bytes_transferred // Number of bytes received.
* ); @endcode * ); @endcode
* Regardless of whether the asynchronous operation completes immediately or * Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation * not, the handler will not be invoked from within this function. Invocation

View file

@ -34,7 +34,8 @@ public:
/// The underlying implementation type of I/O object. /// The underlying implementation type of I/O object.
typedef typename service_type::implementation_type implementation_type; typedef typename service_type::implementation_type implementation_type;
/// Get the io_service associated with the object. /// (Deprecated: use get_io_service().) Get the io_service associated with
/// the object.
/** /**
* This function may be used to obtain the io_service object that the I/O * This function may be used to obtain the io_service object that the I/O
* object uses to dispatch handlers for asynchronous operations. * object uses to dispatch handlers for asynchronous operations.
@ -44,7 +45,20 @@ public:
*/ */
asio::io_service& io_service() asio::io_service& io_service()
{ {
return service.io_service(); return service.get_io_service();
}
/// Get the io_service associated with the object.
/**
* This function may be used to obtain the io_service object that the I/O
* object uses to dispatch handlers for asynchronous operations.
*
* @return A reference to the io_service object that the I/O object will use
* to dispatch handlers. Ownership is not transferred to the caller.
*/
asio::io_service& get_io_service()
{
return service.get_io_service();
} }
protected: protected:

View file

@ -564,7 +564,8 @@ public:
if (this->service.open(this->implementation, if (this->service.open(this->implementation,
peer_endpoint.protocol(), ec)) peer_endpoint.protocol(), ec))
{ {
this->io_service().post(asio::detail::bind_handler(handler, ec)); this->get_io_service().post(
asio::detail::bind_handler(handler, ec));
return; return;
} }
} }

View file

@ -93,10 +93,17 @@ public:
return next_layer_.lowest_layer(); return next_layer_.lowest_layer();
} }
/// Get the io_service associated with the object. /// (Deprecated: use get_io_service().) Get the io_service associated with
/// the object.
asio::io_service& io_service() asio::io_service& io_service()
{ {
return next_layer_.io_service(); return next_layer_.get_io_service();
}
/// Get the io_service associated with the object.
asio::io_service& get_io_service()
{
return next_layer_.get_io_service();
} }
/// Close the stream. /// Close the stream.
@ -207,7 +214,7 @@ public:
buffer( buffer(
storage_.data() + previous_size, storage_.data() + previous_size,
storage_.size() - previous_size), storage_.size() - previous_size),
fill_handler<ReadHandler>(io_service(), fill_handler<ReadHandler>(get_io_service(),
storage_, previous_size, handler)); storage_, previous_size, handler));
} }
@ -295,12 +302,12 @@ public:
if (storage_.empty()) if (storage_.empty())
{ {
async_fill(read_some_handler<MutableBufferSequence, ReadHandler>( async_fill(read_some_handler<MutableBufferSequence, ReadHandler>(
io_service(), storage_, buffers, handler)); get_io_service(), storage_, buffers, handler));
} }
else else
{ {
std::size_t length = copy(buffers); std::size_t length = copy(buffers);
io_service().post(detail::bind_handler( get_io_service().post(detail::bind_handler(
handler, asio::error_code(), length)); handler, asio::error_code(), length));
} }
} }

View file

@ -83,10 +83,17 @@ public:
return stream_impl_.lowest_layer(); return stream_impl_.lowest_layer();
} }
/// Get the io_service associated with the object. /// (Deprecated: use get_io_service().) Get the io_service associated with
/// the object.
asio::io_service& io_service() asio::io_service& io_service()
{ {
return stream_impl_.io_service(); return stream_impl_.get_io_service();
}
/// Get the io_service associated with the object.
asio::io_service& get_io_service()
{
return stream_impl_.get_io_service();
} }
/// Close the stream. /// Close the stream.

View file

@ -94,10 +94,17 @@ public:
return next_layer_.lowest_layer(); return next_layer_.lowest_layer();
} }
/// Get the io_service associated with the object. /// (Deprecated: use get_io_service().) Get the io_service associated with
/// the object.
asio::io_service& io_service() asio::io_service& io_service()
{ {
return next_layer_.io_service(); return next_layer_.get_io_service();
}
/// Get the io_service associated with the object.
asio::io_service& get_io_service()
{
return next_layer_.get_io_service();
} }
/// Close the stream. /// Close the stream.
@ -165,7 +172,7 @@ public:
void async_flush(WriteHandler handler) void async_flush(WriteHandler handler)
{ {
async_write(next_layer_, buffer(storage_.data(), storage_.size()), async_write(next_layer_, buffer(storage_.data(), storage_.size()),
flush_handler<WriteHandler>(io_service(), storage_, handler)); flush_handler<WriteHandler>(get_io_service(), storage_, handler));
} }
/// Write the given data to the stream. Returns the number of bytes written. /// Write the given data to the stream. Returns the number of bytes written.
@ -253,12 +260,12 @@ public:
if (storage_.size() == storage_.capacity()) if (storage_.size() == storage_.capacity())
{ {
async_flush(write_some_handler<ConstBufferSequence, WriteHandler>( async_flush(write_some_handler<ConstBufferSequence, WriteHandler>(
io_service(), storage_, buffers, handler)); get_io_service(), storage_, buffers, handler));
} }
else else
{ {
std::size_t bytes_copied = copy(buffers); std::size_t bytes_copied = copy(buffers);
io_service().post(detail::bind_handler( get_io_service().post(detail::bind_handler(
handler, asio::error_code(), bytes_copied)); handler, asio::error_code(), bytes_copied));
} }
} }

View file

@ -180,7 +180,7 @@ public:
{ {
impl.might_have_pending_waits = true; impl.might_have_pending_waits = true;
scheduler_.schedule_timer(timer_queue_, impl.expiry, scheduler_.schedule_timer(timer_queue_, impl.expiry,
wait_handler<Handler>(this->io_service(), handler), &impl); wait_handler<Handler>(this->get_io_service(), handler), &impl);
} }
private: private:

View file

@ -19,6 +19,7 @@
#include "asio/detail/push_options.hpp" #include "asio/detail/push_options.hpp"
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/throw_exception.hpp>
#include "asio/detail/pop_options.hpp" #include "asio/detail/pop_options.hpp"
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) #if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
@ -27,6 +28,8 @@
#include <fcntl.h> #include <fcntl.h>
#include "asio/detail/pop_options.hpp" #include "asio/detail/pop_options.hpp"
#include "asio/error.hpp"
#include "asio/system_error.hpp"
#include "asio/detail/socket_types.hpp" #include "asio/detail/socket_types.hpp"
namespace asio { namespace asio {
@ -46,6 +49,12 @@ public:
write_descriptor_ = pipe_fds[1]; write_descriptor_ = pipe_fds[1];
::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK); ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
} }
else
{
asio::error_code ec(errno, asio::error::system_category);
asio::system_error e(ec, "pipe_select_interrupter");
boost::throw_exception(e);
}
} }
// Destructor. // Destructor.

View file

@ -58,7 +58,7 @@ public:
} }
private: private:
fd_set fd_set_; mutable fd_set fd_set_;
socket_type max_descriptor_; socket_type max_descriptor_;
}; };

View file

@ -624,7 +624,7 @@ public:
{ {
if (!is_open(impl)) if (!is_open(impl))
{ {
this->io_service().post(bind_handler(handler, this->get_io_service().post(bind_handler(handler,
asio::error::bad_descriptor, 0)); asio::error::bad_descriptor, 0));
} }
else else
@ -645,7 +645,7 @@ public:
// A request to receive 0 bytes on a stream socket is a no-op. // A request to receive 0 bytes on a stream socket is a no-op.
if (total_buffer_size == 0) if (total_buffer_size == 0)
{ {
this->io_service().post(bind_handler(handler, this->get_io_service().post(bind_handler(handler,
asio::error_code(), 0)); asio::error_code(), 0));
return; return;
} }
@ -658,7 +658,7 @@ public:
asio::error_code ec; asio::error_code ec;
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
{ {
this->io_service().post(bind_handler(handler, ec, 0)); this->get_io_service().post(bind_handler(handler, ec, 0));
return; return;
} }
impl.flags_ |= implementation_type::internal_non_blocking; impl.flags_ |= implementation_type::internal_non_blocking;
@ -666,7 +666,7 @@ public:
reactor_.start_write_op(impl.socket_, reactor_.start_write_op(impl.socket_,
send_handler<ConstBufferSequence, Handler>( send_handler<ConstBufferSequence, Handler>(
impl.socket_, this->io_service(), buffers, flags, handler)); impl.socket_, this->get_io_service(), buffers, flags, handler));
} }
} }
@ -804,7 +804,7 @@ public:
{ {
if (!is_open(impl)) if (!is_open(impl))
{ {
this->io_service().post(bind_handler(handler, this->get_io_service().post(bind_handler(handler,
asio::error::bad_descriptor, 0)); asio::error::bad_descriptor, 0));
} }
else else
@ -816,7 +816,7 @@ public:
asio::error_code ec; asio::error_code ec;
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
{ {
this->io_service().post(bind_handler(handler, ec, 0)); this->get_io_service().post(bind_handler(handler, ec, 0));
return; return;
} }
impl.flags_ |= implementation_type::internal_non_blocking; impl.flags_ |= implementation_type::internal_non_blocking;
@ -824,7 +824,7 @@ public:
reactor_.start_write_op(impl.socket_, reactor_.start_write_op(impl.socket_,
send_to_handler<ConstBufferSequence, Handler>( send_to_handler<ConstBufferSequence, Handler>(
impl.socket_, this->io_service(), buffers, impl.socket_, this->get_io_service(), buffers,
destination, flags, handler)); destination, flags, handler));
} }
} }
@ -975,7 +975,7 @@ public:
{ {
if (!is_open(impl)) if (!is_open(impl))
{ {
this->io_service().post(bind_handler(handler, this->get_io_service().post(bind_handler(handler,
asio::error::bad_descriptor, 0)); asio::error::bad_descriptor, 0));
} }
else else
@ -996,7 +996,7 @@ public:
// A request to receive 0 bytes on a stream socket is a no-op. // A request to receive 0 bytes on a stream socket is a no-op.
if (total_buffer_size == 0) if (total_buffer_size == 0)
{ {
this->io_service().post(bind_handler(handler, this->get_io_service().post(bind_handler(handler,
asio::error_code(), 0)); asio::error_code(), 0));
return; return;
} }
@ -1009,7 +1009,7 @@ public:
asio::error_code ec; asio::error_code ec;
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
{ {
this->io_service().post(bind_handler(handler, ec, 0)); this->get_io_service().post(bind_handler(handler, ec, 0));
return; return;
} }
impl.flags_ |= implementation_type::internal_non_blocking; impl.flags_ |= implementation_type::internal_non_blocking;
@ -1019,13 +1019,13 @@ public:
{ {
reactor_.start_except_op(impl.socket_, reactor_.start_except_op(impl.socket_,
receive_handler<MutableBufferSequence, Handler>( receive_handler<MutableBufferSequence, Handler>(
impl.socket_, this->io_service(), buffers, flags, handler)); impl.socket_, this->get_io_service(), buffers, flags, handler));
} }
else else
{ {
reactor_.start_read_op(impl.socket_, reactor_.start_read_op(impl.socket_,
receive_handler<MutableBufferSequence, Handler>( receive_handler<MutableBufferSequence, Handler>(
impl.socket_, this->io_service(), buffers, flags, handler)); impl.socket_, this->get_io_service(), buffers, flags, handler));
} }
} }
} }
@ -1181,7 +1181,7 @@ public:
{ {
if (!is_open(impl)) if (!is_open(impl))
{ {
this->io_service().post(bind_handler(handler, this->get_io_service().post(bind_handler(handler,
asio::error::bad_descriptor, 0)); asio::error::bad_descriptor, 0));
} }
else else
@ -1193,7 +1193,7 @@ public:
asio::error_code ec; asio::error_code ec;
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
{ {
this->io_service().post(bind_handler(handler, ec, 0)); this->get_io_service().post(bind_handler(handler, ec, 0));
return; return;
} }
impl.flags_ |= implementation_type::internal_non_blocking; impl.flags_ |= implementation_type::internal_non_blocking;
@ -1201,7 +1201,7 @@ public:
reactor_.start_read_op(impl.socket_, reactor_.start_read_op(impl.socket_,
receive_from_handler<MutableBufferSequence, Handler>( receive_from_handler<MutableBufferSequence, Handler>(
impl.socket_, this->io_service(), buffers, impl.socket_, this->get_io_service(), buffers,
sender_endpoint, flags, handler)); sender_endpoint, flags, handler));
} }
} }
@ -1384,12 +1384,12 @@ public:
{ {
if (!is_open(impl)) if (!is_open(impl))
{ {
this->io_service().post(bind_handler(handler, this->get_io_service().post(bind_handler(handler,
asio::error::bad_descriptor)); asio::error::bad_descriptor));
} }
else if (peer.is_open()) else if (peer.is_open())
{ {
this->io_service().post(bind_handler(handler, this->get_io_service().post(bind_handler(handler,
asio::error::already_open)); asio::error::already_open));
} }
else else
@ -1401,7 +1401,7 @@ public:
asio::error_code ec; asio::error_code ec;
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
{ {
this->io_service().post(bind_handler(handler, ec)); this->get_io_service().post(bind_handler(handler, ec));
return; return;
} }
impl.flags_ |= implementation_type::internal_non_blocking; impl.flags_ |= implementation_type::internal_non_blocking;
@ -1409,7 +1409,7 @@ public:
reactor_.start_read_op(impl.socket_, reactor_.start_read_op(impl.socket_,
accept_handler<Socket, Handler>( accept_handler<Socket, Handler>(
impl.socket_, this->io_service(), impl.socket_, this->get_io_service(),
peer, impl.protocol_, peer_endpoint, peer, impl.protocol_, peer_endpoint,
(impl.flags_ & implementation_type::enable_connection_aborted) != 0, (impl.flags_ & implementation_type::enable_connection_aborted) != 0,
handler)); handler));
@ -1515,7 +1515,7 @@ public:
{ {
if (!is_open(impl)) if (!is_open(impl))
{ {
this->io_service().post(bind_handler(handler, this->get_io_service().post(bind_handler(handler,
asio::error::bad_descriptor)); asio::error::bad_descriptor));
return; return;
} }
@ -1527,7 +1527,7 @@ public:
asio::error_code ec; asio::error_code ec;
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
{ {
this->io_service().post(bind_handler(handler, ec)); this->get_io_service().post(bind_handler(handler, ec));
return; return;
} }
impl.flags_ |= implementation_type::internal_non_blocking; impl.flags_ |= implementation_type::internal_non_blocking;
@ -1541,7 +1541,7 @@ public:
{ {
// The connect operation has finished successfully so we need to post the // The connect operation has finished successfully so we need to post the
// handler immediately. // handler immediately.
this->io_service().post(bind_handler(handler, this->get_io_service().post(bind_handler(handler,
asio::error_code())); asio::error_code()));
} }
else if (ec == asio::error::in_progress else if (ec == asio::error::in_progress
@ -1551,13 +1551,13 @@ public:
// until the socket becomes writeable. // until the socket becomes writeable.
boost::shared_ptr<bool> completed(new bool(false)); boost::shared_ptr<bool> completed(new bool(false));
reactor_.start_write_and_except_ops(impl.socket_, reactor_.start_write_and_except_ops(impl.socket_,
connect_handler<Handler>( connect_handler<Handler>(impl.socket_, completed,
impl.socket_, completed, this->io_service(), reactor_, handler)); this->get_io_service(), reactor_, handler));
} }
else else
{ {
// The connect operation has failed, so post the handler immediately. // The connect operation has failed, so post the handler immediately.
this->io_service().post(bind_handler(handler, ec)); this->get_io_service().post(bind_handler(handler, ec));
} }
} }

View file

@ -213,7 +213,7 @@ public:
start_work_thread(); start_work_thread();
work_io_service_->post( work_io_service_->post(
resolve_query_handler<Handler>( resolve_query_handler<Handler>(
impl, query, this->io_service(), handler)); impl, query, this->get_io_service(), handler));
} }
} }
@ -309,7 +309,7 @@ public:
start_work_thread(); start_work_thread();
work_io_service_->post( work_io_service_->post(
resolve_endpoint_handler<Handler>( resolve_endpoint_handler<Handler>(
impl, endpoint, this->io_service(), handler)); impl, endpoint, this->get_io_service(), handler));
} }
} }

View file

@ -39,6 +39,13 @@ namespace socket_ops {
struct msghdr { int msg_namelen; }; struct msghdr { int msg_namelen; };
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
#if defined(__hpux)
// HP-UX doesn't declare these functions extern "C", so they are declared again
// here to avoid linker errors about undefined symbols.
extern "C" char* if_indextoname(unsigned int, char*);
extern "C" unsigned int if_nametoindex(const char*);
#endif // defined(__hpux)
inline void clear_error(asio::error_code& ec) inline void clear_error(asio::error_code& ec)
{ {
errno = 0; errno = 0;
@ -542,10 +549,12 @@ inline int select(int nfds, fd_set* readfds, fd_set* writefds,
timeout->tv_usec = 1000; timeout->tv_usec = 1000;
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
#if defined(__hpux) && defined(__HP_aCC) && !defined(_XOPEN_SOURCE_EXTENDED) #if defined(__hpux) && defined(__HP_aCC)
return error_wrapper(::select(nfds, timespec ts;
reinterpret_cast<int*>(readfds), reinterpret_cast<int*>(writefds), ts.tv_sec = timeout ? timeout->tv_sec : 0;
reinterpret_cast<int*>(exceptfds), timeout), ec); ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0;
return error_wrapper(::pselect(nfds, readfds,
writefds, exceptfds, timeout ? &ts : 0, 0), ec);
#else #else
return error_wrapper(::select(nfds, readfds, return error_wrapper(::select(nfds, readfds,
writefds, exceptfds, timeout), ec); writefds, exceptfds, timeout), ec);

View file

@ -29,12 +29,12 @@
# if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS) # if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
# if defined(_MSC_VER) || defined(__BORLANDC__) # if defined(_MSC_VER) || defined(__BORLANDC__)
# pragma message("Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately") # pragma message("Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately")
# pragma message("Assuming _WIN32_WINNT=0x0500 (i.e. Windows 2000 target)") # pragma message("Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target)")
# else // defined(_MSC_VER) || defined(__BORLANDC__) # else // defined(_MSC_VER) || defined(__BORLANDC__)
# warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately # warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately
# warning Assuming _WIN32_WINNT=0x0500 (i.e. Windows 2000 target) # warning Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target)
# endif // defined(_MSC_VER) || defined(__BORLANDC__) # endif // defined(_MSC_VER) || defined(__BORLANDC__)
# define _WIN32_WINNT 0x0500 # define _WIN32_WINNT 0x0501
# endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS) # endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
# if defined(_MSC_VER) # if defined(_MSC_VER)
# if defined(_WIN32) && !defined(WIN32) # if defined(_WIN32) && !defined(WIN32)

View file

@ -276,7 +276,7 @@ public:
if (impl_->first_waiter_ == 0) if (impl_->first_waiter_ == 0)
impl_->last_waiter_ = 0; impl_->last_waiter_ = 0;
lock.unlock(); lock.unlock();
service_impl_.io_service().post( service_impl_.get_io_service().post(
invoke_current_handler(service_impl_, impl_)); invoke_current_handler(service_impl_, impl_));
} }
} }
@ -429,7 +429,7 @@ public:
// This handler now has the lock, so can be dispatched immediately. // This handler now has the lock, so can be dispatched immediately.
impl->current_handler_ = ptr.get(); impl->current_handler_ = ptr.get();
lock.unlock(); lock.unlock();
this->io_service().dispatch(invoke_current_handler(*this, impl)); this->get_io_service().dispatch(invoke_current_handler(*this, impl));
ptr.release(); ptr.release();
} }
else else
@ -469,7 +469,7 @@ public:
// This handler now has the lock, so can be dispatched immediately. // This handler now has the lock, so can be dispatched immediately.
impl->current_handler_ = ptr.get(); impl->current_handler_ = ptr.get();
lock.unlock(); lock.unlock();
this->io_service().post(invoke_current_handler(*this, impl)); this->get_io_service().post(invoke_current_handler(*this, impl));
ptr.release(); ptr.release();
} }
else else

View file

@ -225,16 +225,18 @@ private:
{ {
bool more_handlers = (!handler_queue_.empty()); bool more_handlers = (!handler_queue_.empty());
task_interrupted_ = more_handlers || polling; task_interrupted_ = more_handlers || polling;
lock.unlock();
// If the task has already run and we're polling then we're done. // If the task has already run and we're polling then we're done.
if (task_has_run && polling) if (task_has_run && polling)
{ {
task_interrupted_ = true;
handler_queue_.push(&task_handler_);
ec = asio::error_code(); ec = asio::error_code();
return 0; return 0;
} }
task_has_run = true; task_has_run = true;
lock.unlock();
task_cleanup c(lock, *this); task_cleanup c(lock, *this);
// Run the task. May throw an exception. Only block if the handler // Run the task. May throw an exception. Only block if the handler
@ -316,6 +318,8 @@ private:
} }
// Helper class to perform task-related operations on block exit. // Helper class to perform task-related operations on block exit.
class task_cleanup;
friend class task_cleanup;
class task_cleanup class task_cleanup
{ {
public: public:

View file

@ -327,7 +327,7 @@ public:
ec = asio::error::bad_descriptor; ec = asio::error::bad_descriptor;
} }
else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress( else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
::GetModuleHandle("KERNEL32"), "CancelIoEx")) ::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
{ {
// The version of Windows supports cancellation from any thread. // The version of Windows supports cancellation from any thread.
typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED); typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
@ -767,7 +767,7 @@ public:
{ {
if (!is_open(impl)) if (!is_open(impl))
{ {
this->io_service().post(bind_handler(handler, this->get_io_service().post(bind_handler(handler,
asio::error::bad_descriptor, 0)); asio::error::bad_descriptor, 0));
return; return;
} }
@ -783,7 +783,7 @@ public:
typedef handler_alloc_traits<Handler, value_type> alloc_traits; typedef handler_alloc_traits<Handler, value_type> alloc_traits;
raw_handler_ptr<alloc_traits> raw_ptr(handler); raw_handler_ptr<alloc_traits> raw_ptr(handler);
handler_ptr<alloc_traits> ptr(raw_ptr, handler_ptr<alloc_traits> ptr(raw_ptr,
this->io_service(), impl.cancel_token_, buffers, handler); this->get_io_service(), impl.cancel_token_, buffers, handler);
// Copy buffers into WSABUF array. // Copy buffers into WSABUF array.
::WSABUF bufs[max_buffers]; ::WSABUF bufs[max_buffers];
@ -803,7 +803,7 @@ public:
// A request to receive 0 bytes on a stream socket is a no-op. // A request to receive 0 bytes on a stream socket is a no-op.
if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
{ {
asio::io_service::work work(this->io_service()); asio::io_service::work work(this->get_io_service());
ptr.reset(); ptr.reset();
asio::error_code error; asio::error_code error;
iocp_service_.post(bind_handler(handler, error, 0)); iocp_service_.post(bind_handler(handler, error, 0));
@ -819,7 +819,7 @@ public:
// Check if the operation completed immediately. // Check if the operation completed immediately.
if (result != 0 && last_error != WSA_IO_PENDING) if (result != 0 && last_error != WSA_IO_PENDING)
{ {
asio::io_service::work work(this->io_service()); asio::io_service::work work(this->get_io_service());
ptr.reset(); ptr.reset();
asio::error_code ec(last_error, asio::error_code ec(last_error,
asio::error::system_category); asio::error::system_category);
@ -958,7 +958,7 @@ public:
{ {
if (!is_open(impl)) if (!is_open(impl))
{ {
this->io_service().post(bind_handler(handler, this->get_io_service().post(bind_handler(handler,
asio::error::bad_descriptor, 0)); asio::error::bad_descriptor, 0));
return; return;
} }
@ -974,7 +974,7 @@ public:
typedef handler_alloc_traits<Handler, value_type> alloc_traits; typedef handler_alloc_traits<Handler, value_type> alloc_traits;
raw_handler_ptr<alloc_traits> raw_ptr(handler); raw_handler_ptr<alloc_traits> raw_ptr(handler);
handler_ptr<alloc_traits> ptr(raw_ptr, handler_ptr<alloc_traits> ptr(raw_ptr,
this->io_service(), buffers, handler); this->get_io_service(), buffers, handler);
// Copy buffers into WSABUF array. // Copy buffers into WSABUF array.
::WSABUF bufs[max_buffers]; ::WSABUF bufs[max_buffers];
@ -998,7 +998,7 @@ public:
// Check if the operation completed immediately. // Check if the operation completed immediately.
if (result != 0 && last_error != WSA_IO_PENDING) if (result != 0 && last_error != WSA_IO_PENDING)
{ {
asio::io_service::work work(this->io_service()); asio::io_service::work work(this->get_io_service());
ptr.reset(); ptr.reset();
asio::error_code ec(last_error, asio::error_code ec(last_error,
asio::error::system_category); asio::error::system_category);
@ -1170,7 +1170,7 @@ public:
{ {
if (!is_open(impl)) if (!is_open(impl))
{ {
this->io_service().post(bind_handler(handler, this->get_io_service().post(bind_handler(handler,
asio::error::bad_descriptor, 0)); asio::error::bad_descriptor, 0));
return; return;
} }
@ -1186,7 +1186,7 @@ public:
typedef handler_alloc_traits<Handler, value_type> alloc_traits; typedef handler_alloc_traits<Handler, value_type> alloc_traits;
raw_handler_ptr<alloc_traits> raw_ptr(handler); raw_handler_ptr<alloc_traits> raw_ptr(handler);
handler_ptr<alloc_traits> ptr(raw_ptr, handler_ptr<alloc_traits> ptr(raw_ptr,
this->io_service(), impl.cancel_token_, buffers, handler); this->get_io_service(), impl.cancel_token_, buffers, handler);
// Copy buffers into WSABUF array. // Copy buffers into WSABUF array.
::WSABUF bufs[max_buffers]; ::WSABUF bufs[max_buffers];
@ -1205,7 +1205,7 @@ public:
// A request to receive 0 bytes on a stream socket is a no-op. // A request to receive 0 bytes on a stream socket is a no-op.
if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
{ {
asio::io_service::work work(this->io_service()); asio::io_service::work work(this->get_io_service());
ptr.reset(); ptr.reset();
asio::error_code error; asio::error_code error;
iocp_service_.post(bind_handler(handler, error, 0)); iocp_service_.post(bind_handler(handler, error, 0));
@ -1220,7 +1220,7 @@ public:
DWORD last_error = ::WSAGetLastError(); DWORD last_error = ::WSAGetLastError();
if (result != 0 && last_error != WSA_IO_PENDING) if (result != 0 && last_error != WSA_IO_PENDING)
{ {
asio::io_service::work work(this->io_service()); asio::io_service::work work(this->get_io_service());
ptr.reset(); ptr.reset();
asio::error_code ec(last_error, asio::error_code ec(last_error,
asio::error::system_category); asio::error::system_category);
@ -1390,7 +1390,7 @@ public:
{ {
if (!is_open(impl)) if (!is_open(impl))
{ {
this->io_service().post(bind_handler(handler, this->get_io_service().post(bind_handler(handler,
asio::error::bad_descriptor, 0)); asio::error::bad_descriptor, 0));
return; return;
} }
@ -1406,7 +1406,7 @@ public:
typedef handler_alloc_traits<Handler, value_type> alloc_traits; typedef handler_alloc_traits<Handler, value_type> alloc_traits;
raw_handler_ptr<alloc_traits> raw_ptr(handler); raw_handler_ptr<alloc_traits> raw_ptr(handler);
handler_ptr<alloc_traits> ptr(raw_ptr, handler_ptr<alloc_traits> ptr(raw_ptr,
this->io_service(), sender_endp, buffers, handler); this->get_io_service(), sender_endp, buffers, handler);
// Copy buffers into WSABUF array. // Copy buffers into WSABUF array.
::WSABUF bufs[max_buffers]; ::WSABUF bufs[max_buffers];
@ -1429,7 +1429,7 @@ public:
DWORD last_error = ::WSAGetLastError(); DWORD last_error = ::WSAGetLastError();
if (result != 0 && last_error != WSA_IO_PENDING) if (result != 0 && last_error != WSA_IO_PENDING)
{ {
asio::io_service::work work(this->io_service()); asio::io_service::work work(this->get_io_service());
ptr.reset(); ptr.reset();
asio::error_code ec(last_error, asio::error_code ec(last_error,
asio::error::system_category); asio::error::system_category);
@ -1517,7 +1517,7 @@ public:
peer_(peer), peer_(peer),
protocol_(protocol), protocol_(protocol),
peer_endpoint_(peer_endpoint), peer_endpoint_(peer_endpoint),
work_(io_service.io_service()), work_(io_service.get_io_service()),
enable_connection_aborted_(enable_connection_aborted), enable_connection_aborted_(enable_connection_aborted),
handler_(handler) handler_(handler)
{ {
@ -1706,7 +1706,7 @@ public:
// Check whether acceptor has been initialised. // Check whether acceptor has been initialised.
if (!is_open(impl)) if (!is_open(impl))
{ {
this->io_service().post(bind_handler(handler, this->get_io_service().post(bind_handler(handler,
asio::error::bad_descriptor)); asio::error::bad_descriptor));
return; return;
} }
@ -1714,7 +1714,7 @@ public:
// Check that peer socket has not already been opened. // Check that peer socket has not already been opened.
if (peer.is_open()) if (peer.is_open())
{ {
this->io_service().post(bind_handler(handler, this->get_io_service().post(bind_handler(handler,
asio::error::already_open)); asio::error::already_open));
return; return;
} }
@ -1731,7 +1731,7 @@ public:
impl.protocol_.type(), impl.protocol_.protocol(), ec)); impl.protocol_.type(), impl.protocol_.protocol(), ec));
if (sock.get() == invalid_socket) if (sock.get() == invalid_socket)
{ {
this->io_service().post(bind_handler(handler, ec)); this->get_io_service().post(bind_handler(handler, ec));
return; return;
} }
@ -1769,7 +1769,7 @@ public:
} }
else else
{ {
asio::io_service::work work(this->io_service()); asio::io_service::work work(this->get_io_service());
ptr.reset(); ptr.reset();
asio::error_code ec(last_error, asio::error_code ec(last_error,
asio::error::system_category); asio::error::system_category);
@ -1888,7 +1888,7 @@ public:
{ {
if (!is_open(impl)) if (!is_open(impl))
{ {
this->io_service().post(bind_handler(handler, this->get_io_service().post(bind_handler(handler,
asio::error::bad_descriptor)); asio::error::bad_descriptor));
return; return;
} }
@ -1905,7 +1905,8 @@ public:
reinterpret_cast<void**>(&reactor_), 0, 0)); reinterpret_cast<void**>(&reactor_), 0, 0));
if (!reactor) if (!reactor)
{ {
reactor = &(asio::use_service<reactor_type>(this->io_service())); reactor = &(asio::use_service<reactor_type>(
this->get_io_service()));
interlocked_exchange_pointer( interlocked_exchange_pointer(
reinterpret_cast<void**>(&reactor_), reactor); reinterpret_cast<void**>(&reactor_), reactor);
} }
@ -1916,7 +1917,7 @@ public:
asio::error_code ec; asio::error_code ec;
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
{ {
this->io_service().post(bind_handler(handler, ec)); this->get_io_service().post(bind_handler(handler, ec));
return; return;
} }
@ -1933,7 +1934,7 @@ public:
// The connect operation has finished successfully so we need to post the // The connect operation has finished successfully so we need to post the
// handler immediately. // handler immediately.
this->io_service().post(bind_handler(handler, ec)); this->get_io_service().post(bind_handler(handler, ec));
} }
else if (ec == asio::error::in_progress else if (ec == asio::error::in_progress
|| ec == asio::error::would_block) || ec == asio::error::would_block)
@ -1945,7 +1946,7 @@ public:
connect_handler<Handler>( connect_handler<Handler>(
impl.socket_, impl.socket_,
(impl.flags_ & implementation_type::user_set_non_blocking) != 0, (impl.flags_ & implementation_type::user_set_non_blocking) != 0,
completed, this->io_service(), *reactor, handler)); completed, this->get_io_service(), *reactor, handler));
} }
else else
{ {
@ -1958,7 +1959,7 @@ public:
} }
// The connect operation has failed, so post the handler immediately. // The connect operation has failed, so post the handler immediately.
this->io_service().post(bind_handler(handler, ec)); this->get_io_service().post(bind_handler(handler, ec));
} }
} }

View file

@ -61,7 +61,7 @@ enum basic_errors
/// Address family not supported by protocol. /// Address family not supported by protocol.
address_family_not_supported = ASIO_SOCKET_ERROR(EAFNOSUPPORT), address_family_not_supported = ASIO_SOCKET_ERROR(EAFNOSUPPORT),
/// Address already in use. /// Port already in use.
address_in_use = ASIO_SOCKET_ERROR(EADDRINUSE), address_in_use = ASIO_SOCKET_ERROR(EADDRINUSE),
/// Transport endpoint is already connected. /// Transport endpoint is already connected.
@ -82,7 +82,7 @@ enum basic_errors
/// Bad file descriptor. /// Bad file descriptor.
bad_descriptor = ASIO_SOCKET_ERROR(EBADF), bad_descriptor = ASIO_SOCKET_ERROR(EBADF),
/// Bad address. /// Bad port.
fault = ASIO_SOCKET_ERROR(EFAULT), fault = ASIO_SOCKET_ERROR(EFAULT),
/// No route to host. /// No route to host.
@ -197,6 +197,10 @@ enum misc_errors
not_found not_found
}; };
enum ssl_errors
{
};
// boostify: error category definitions go here. // boostify: error category definitions go here.
inline asio::error_code make_error_code(basic_errors e) inline asio::error_code make_error_code(basic_errors e)
@ -219,6 +223,11 @@ inline asio::error_code make_error_code(misc_errors e)
return asio::error_code(static_cast<int>(e), misc_category); return asio::error_code(static_cast<int>(e), misc_category);
} }
inline asio::error_code make_error_code(ssl_errors e)
{
return asio::error_code(static_cast<int>(e), ssl_category);
}
} // namespace error } // namespace error
} // namespace asio } // namespace asio

View file

@ -84,7 +84,7 @@ inline std::string error_code::message() const
return strerror(value_); return strerror(value_);
#elif defined(__MACH__) && defined(__APPLE__) \ #elif defined(__MACH__) && defined(__APPLE__) \
|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) \ || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) \
|| defined(_AIX) || defined(_AIX) || defined(__hpux) || defined(__osf__)
char buf[256] = ""; char buf[256] = "";
strerror_r(value_, buf, sizeof(buf)); strerror_r(value_, buf, sizeof(buf));
return buf; return buf;

View file

@ -158,6 +158,11 @@ inline asio::io_service& io_service::work::io_service()
return io_service_; return io_service_;
} }
inline asio::io_service& io_service::work::get_io_service()
{
return io_service_;
}
inline io_service::service::service(asio::io_service& owner) inline io_service::service::service(asio::io_service& owner)
: owner_(owner), : owner_(owner),
type_info_(0), type_info_(0),
@ -174,6 +179,11 @@ inline asio::io_service& io_service::service::io_service()
return owner_; return owner_;
} }
inline asio::io_service& io_service::service::get_io_service()
{
return owner_;
}
template <typename Service> template <typename Service>
inline Service& use_service(io_service& ios) inline Service& use_service(io_service& ios)
{ {

View file

@ -19,6 +19,7 @@
#include "asio/detail/push_options.hpp" #include "asio/detail/push_options.hpp"
#include <algorithm> #include <algorithm>
#include <boost/optional.hpp>
#include "asio/detail/pop_options.hpp" #include "asio/detail/pop_options.hpp"
#include "asio/buffer.hpp" #include "asio/buffer.hpp"
@ -138,23 +139,25 @@ namespace detail
std::size_t bytes_transferred) std::size_t bytes_transferred)
{ {
total_transferred_ += bytes_transferred; total_transferred_ += bytes_transferred;
buffers_.consume(bytes_transferred); buffers_->consume(bytes_transferred);
if (completion_condition_(ec, total_transferred_) if ((*completion_condition_)(ec, total_transferred_)
|| buffers_.begin() == buffers_.end()) || buffers_->begin() == buffers_->end())
{ {
buffers_.reset();
completion_condition_.reset();
handler_(ec, total_transferred_); handler_(ec, total_transferred_);
} }
else else
{ {
stream_.async_read_some(buffers_, *this); stream_.async_read_some(*buffers_, *this);
} }
} }
//private: //private:
AsyncReadStream& stream_; AsyncReadStream& stream_;
buffers_type buffers_; boost::optional<buffers_type> buffers_;
std::size_t total_transferred_; std::size_t total_transferred_;
CompletionCondition completion_condition_; boost::optional<CompletionCondition> completion_condition_;
ReadHandler handler_; ReadHandler handler_;
}; };
@ -235,8 +238,9 @@ namespace detail
total_transferred_ += bytes_transferred; total_transferred_ += bytes_transferred;
streambuf_.commit(bytes_transferred); streambuf_.commit(bytes_transferred);
if (streambuf_.size() == streambuf_.max_size() if (streambuf_.size() == streambuf_.max_size()
|| completion_condition_(ec, total_transferred_)) || (*completion_condition_)(ec, total_transferred_))
{ {
completion_condition_.reset();
handler_(ec, total_transferred_); handler_(ec, total_transferred_);
} }
else else
@ -251,7 +255,7 @@ namespace detail
AsyncReadStream& stream_; AsyncReadStream& stream_;
asio::basic_streambuf<Allocator>& streambuf_; asio::basic_streambuf<Allocator>& streambuf_;
std::size_t total_transferred_; std::size_t total_transferred_;
CompletionCondition completion_condition_; boost::optional<CompletionCondition> completion_condition_;
ReadHandler handler_; ReadHandler handler_;
}; };

View file

@ -17,6 +17,10 @@
#include "asio/detail/push_options.hpp" #include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/optional.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/buffer.hpp" #include "asio/buffer.hpp"
#include "asio/completion_condition.hpp" #include "asio/completion_condition.hpp"
#include "asio/detail/bind_handler.hpp" #include "asio/detail/bind_handler.hpp"
@ -124,23 +128,25 @@ namespace detail
std::size_t bytes_transferred) std::size_t bytes_transferred)
{ {
total_transferred_ += bytes_transferred; total_transferred_ += bytes_transferred;
buffers_.consume(bytes_transferred); buffers_->consume(bytes_transferred);
if (completion_condition_(ec, total_transferred_) if ((*completion_condition_)(ec, total_transferred_)
|| buffers_.begin() == buffers_.end()) || buffers_->begin() == buffers_->end())
{ {
buffers_.reset();
completion_condition_.reset();
handler_(ec, total_transferred_); handler_(ec, total_transferred_);
} }
else else
{ {
stream_.async_write_some(buffers_, *this); stream_.async_write_some(*buffers_, *this);
} }
} }
//private: //private:
AsyncWriteStream& stream_; AsyncWriteStream& stream_;
buffers_type buffers_; boost::optional<buffers_type> buffers_;
std::size_t total_transferred_; std::size_t total_transferred_;
CompletionCondition completion_condition_; boost::optional<CompletionCondition> completion_condition_;
WriteHandler handler_; WriteHandler handler_;
}; };

View file

@ -381,7 +381,8 @@ public:
private: private:
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
detail::winsock_init<> init_; detail::winsock_init<> init_;
#elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) #elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \
|| defined(__osf__)
detail::signal_init<> init_; detail::signal_init<> init_;
#endif #endif
@ -429,9 +430,13 @@ public:
*/ */
~work(); ~work();
/// Get the io_service associated with the work. /// (Deprecated: use get_io_service().) Get the io_service associated with the
/// work.
asio::io_service& io_service(); asio::io_service& io_service();
/// Get the io_service associated with the work.
asio::io_service& get_io_service();
private: private:
// Prevent assignment. // Prevent assignment.
void operator=(const work& other); void operator=(const work& other);
@ -454,9 +459,13 @@ class io_service::service
: private noncopyable : private noncopyable
{ {
public: public:
/// Get the io_service object that owns the service. /// (Deprecated: use get_io_service().) Get the io_service object that owns
/// the service.
asio::io_service& io_service(); asio::io_service& io_service();
/// Get the io_service object that owns the service.
asio::io_service& get_io_service();
protected: protected:
/// Constructor. /// Constructor.
/** /**

View file

@ -300,7 +300,7 @@ public:
{ {
using namespace std; // For memcmp. using namespace std; // For memcmp.
int memcmp_result = memcmp(&a1.addr_, &a2.addr_, int memcmp_result = memcmp(&a1.addr_, &a2.addr_,
sizeof(asio::detail::in6_addr_type)) < 0; sizeof(asio::detail::in6_addr_type));
if (memcmp_result < 0) if (memcmp_result < 0)
return true; return true;
if (memcmp_result > 0) if (memcmp_result > 0)

View file

@ -32,52 +32,60 @@ namespace ip {
namespace detail { namespace detail {
namespace socket_option { namespace socket_option {
// Helper template for implementing boolean-based options. // Helper template for implementing multicast enable loopback options.
template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name> template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
class boolean class multicast_enable_loopback
{ {
public: public:
#if defined(__sun) || defined(_AIX) || defined(__osf__) #if defined(__sun) || defined(__osf__)
typedef unsigned char value_type; typedef unsigned char ipv4_value_type;
typedef unsigned char ipv6_value_type;
#elif defined(_AIX) || defined(__hpux)
typedef unsigned char ipv4_value_type;
typedef unsigned int ipv6_value_type;
#else #else
typedef int value_type; typedef int ipv4_value_type;
typedef int ipv6_value_type;
#endif #endif
// Default constructor. // Default constructor.
boolean() multicast_enable_loopback()
: value_(0) : ipv4_value_(0),
ipv6_value_(0)
{ {
} }
// Construct with a specific option value. // Construct with a specific option value.
explicit boolean(bool v) explicit multicast_enable_loopback(bool v)
: value_(v ? 1 : 0) : ipv4_value_(v ? 1 : 0),
ipv6_value_(v ? 1 : 0)
{ {
} }
// Set the value of the boolean. // Set the value of the boolean.
boolean& operator=(bool v) multicast_enable_loopback& operator=(bool v)
{ {
value_ = v ? 1 : 0; ipv4_value_ = v ? 1 : 0;
ipv6_value_ = v ? 1 : 0;
return *this; return *this;
} }
// Get the current value of the boolean. // Get the current value of the boolean.
bool value() const bool value() const
{ {
return !!value_; return !!ipv4_value_;
} }
// Convert to bool. // Convert to bool.
operator bool() const operator bool() const
{ {
return !!value_; return !!ipv4_value_;
} }
// Test for false. // Test for false.
bool operator!() const bool operator!() const
{ {
return !value_; return !ipv4_value_;
} }
// Get the level of the socket option. // Get the level of the socket option.
@ -100,35 +108,58 @@ public:
// Get the address of the boolean data. // Get the address of the boolean data.
template <typename Protocol> template <typename Protocol>
value_type* data(const Protocol&) void* data(const Protocol& protocol)
{ {
return &value_; if (protocol.family() == PF_INET6)
return &ipv6_value_;
return &ipv4_value_;
} }
// Get the address of the boolean data. // Get the address of the boolean data.
template <typename Protocol> template <typename Protocol>
const value_type* data(const Protocol&) const const void* data(const Protocol& protocol) const
{ {
return &value_; if (protocol.family() == PF_INET6)
return &ipv6_value_;
return &ipv4_value_;
} }
// Get the size of the boolean data. // Get the size of the boolean data.
template <typename Protocol> template <typename Protocol>
std::size_t size(const Protocol&) const std::size_t size(const Protocol& protocol) const
{ {
return sizeof(value_); if (protocol.family() == PF_INET6)
return sizeof(ipv6_value_);
return sizeof(ipv4_value_);
} }
// Set the size of the boolean data. // Set the size of the boolean data.
template <typename Protocol> template <typename Protocol>
void resize(const Protocol&, std::size_t s) void resize(const Protocol& protocol, std::size_t s)
{ {
if (s != sizeof(value_)) if (protocol.family() == PF_INET6)
throw std::length_error("boolean socket option resize"); {
if (s != sizeof(ipv6_value_))
{
throw std::length_error(
"multicast_enable_loopback socket option resize");
}
ipv4_value_ = ipv6_value_ ? 1 : 0;
}
else
{
if (s != sizeof(ipv4_value_))
{
throw std::length_error(
"multicast_enable_loopback socket option resize");
}
ipv6_value_ = ipv4_value_ ? 1 : 0;
}
} }
private: private:
value_type value_; ipv4_value_type ipv4_value_;
ipv6_value_type ipv6_value_;
}; };
// Helper template for implementing unicast hops options. // Helper template for implementing unicast hops options.
@ -206,6 +237,10 @@ public:
{ {
if (s != sizeof(value_)) if (s != sizeof(value_))
throw std::length_error("unicast hops socket option resize"); throw std::length_error("unicast hops socket option resize");
#if defined(__hpux)
if (value_ < 0)
value_ = value_ & 0xFF;
#endif
} }
private: private:
@ -477,7 +512,7 @@ public:
} }
// Construct with IPv6 interface. // Construct with IPv6 interface.
explicit network_interface(unsigned long ipv6_interface) explicit network_interface(unsigned int ipv6_interface)
{ {
ipv4_value_.s_addr = ipv4_value_.s_addr =
asio::detail::socket_ops::host_to_network_long( asio::detail::socket_ops::host_to_network_long(
@ -523,7 +558,7 @@ public:
private: private:
asio::detail::in4_addr_type ipv4_value_; asio::detail::in4_addr_type ipv4_value_;
unsigned long ipv6_value_; unsigned int ipv6_value_;
}; };
} // namespace socket_option } // namespace socket_option

View file

@ -167,7 +167,7 @@ typedef asio::ip::detail::socket_option::multicast_hops<
#if defined(GENERATING_DOCUMENTATION) #if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined enable_loopback; typedef implementation_defined enable_loopback;
#else #else
typedef asio::ip::detail::socket_option::boolean< typedef asio::ip::detail::socket_option::multicast_enable_loopback<
IPPROTO_IP, IP_MULTICAST_LOOP, IPPROTO_IPV6, IPV6_MULTICAST_LOOP> IPPROTO_IP, IP_MULTICAST_LOOP, IPPROTO_IPV6, IPV6_MULTICAST_LOOP>
enable_loopback; enable_loopback;
#endif #endif

View file

@ -27,17 +27,17 @@ namespace placeholders {
#if defined(GENERATING_DOCUMENTATION) #if defined(GENERATING_DOCUMENTATION)
/// An argument placeholder, for use with @ref boost_bind, that corresponds to /// An argument placeholder, for use with boost::bind(), that corresponds to
/// the error argument of a handler for any of the asynchronous functions. /// the error argument of a handler for any of the asynchronous functions.
unspecified error; unspecified error;
/// An argument placeholder, for use with @ref boost_bind, that corresponds to /// An argument placeholder, for use with boost::bind(), that corresponds to
/// the bytes_transferred argument of a handler for asynchronous functions such /// the bytes_transferred argument of a handler for asynchronous functions such
/// as asio::basic_stream_socket::async_write_some or /// as asio::basic_stream_socket::async_write_some or
/// asio::async_write. /// asio::async_write.
unspecified bytes_transferred; unspecified bytes_transferred;
/// An argument placeholder, for use with @ref boost_bind, that corresponds to /// An argument placeholder, for use with boost::bind(), that corresponds to
/// the iterator argument of a handler for asynchronous functions such as /// the iterator argument of a handler for asynchronous functions such as
/// asio::basic_resolver::resolve. /// asio::basic_resolver::resolve.
unspecified iterator; unspecified iterator;

View file

@ -238,7 +238,7 @@ public:
typedef handshake_handler<Stream, Handler> connect_handler; typedef handshake_handler<Stream, Handler> connect_handler;
connect_handler* local_handler = connect_handler* local_handler =
new connect_handler(handler, io_service()); new connect_handler(handler, get_io_service());
openssl_operation<Stream>* op = new openssl_operation<Stream> openssl_operation<Stream>* op = new openssl_operation<Stream>
( (
@ -259,7 +259,7 @@ public:
); );
local_handler->set_operation(op); local_handler->set_operation(op);
io_service().post(boost::bind(&openssl_operation<Stream>::start, op)); get_io_service().post(boost::bind(&openssl_operation<Stream>::start, op));
} }
// Shut down SSL on the stream. // Shut down SSL on the stream.
@ -294,7 +294,7 @@ public:
typedef shutdown_handler<Stream, Handler> disconnect_handler; typedef shutdown_handler<Stream, Handler> disconnect_handler;
disconnect_handler* local_handler = disconnect_handler* local_handler =
new disconnect_handler(handler, io_service()); new disconnect_handler(handler, get_io_service());
openssl_operation<Stream>* op = new openssl_operation<Stream> openssl_operation<Stream>* op = new openssl_operation<Stream>
( (
@ -313,7 +313,7 @@ public:
); );
local_handler->set_operation(op); local_handler->set_operation(op);
io_service().post(boost::bind(&openssl_operation<Stream>::start, op)); get_io_service().post(boost::bind(&openssl_operation<Stream>::start, op));
} }
// Write some data to the stream. // Write some data to the stream.
@ -354,7 +354,7 @@ public:
{ {
typedef io_handler<Stream, Handler> send_handler; typedef io_handler<Stream, Handler> send_handler;
send_handler* local_handler = new send_handler(handler, io_service()); send_handler* local_handler = new send_handler(handler, get_io_service());
boost::function<int (SSL*)> send_func = boost::function<int (SSL*)> send_func =
boost::bind(&::SSL_write, boost::arg<1>(), boost::bind(&::SSL_write, boost::arg<1>(),
@ -378,7 +378,7 @@ public:
); );
local_handler->set_operation(op); local_handler->set_operation(op);
io_service().post(boost::bind(&openssl_operation<Stream>::start, op)); get_io_service().post(boost::bind(&openssl_operation<Stream>::start, op));
} }
// Read some data from the stream. // Read some data from the stream.
@ -419,7 +419,7 @@ public:
{ {
typedef io_handler<Stream, Handler> recv_handler; typedef io_handler<Stream, Handler> recv_handler;
recv_handler* local_handler = new recv_handler(handler, io_service()); recv_handler* local_handler = new recv_handler(handler, get_io_service());
boost::function<int (SSL*)> recv_func = boost::function<int (SSL*)> recv_func =
boost::bind(&::SSL_read, boost::arg<1>(), boost::bind(&::SSL_read, boost::arg<1>(),
@ -443,7 +443,7 @@ public:
); );
local_handler->set_operation(op); local_handler->set_operation(op);
io_service().post(boost::bind(&openssl_operation<Stream>::start, op)); get_io_service().post(boost::bind(&openssl_operation<Stream>::start, op));
} }
// Peek at the incoming data on the stream. // Peek at the incoming data on the stream.

View file

@ -85,7 +85,7 @@ public:
template <typename Arg, typename Context_Service> template <typename Arg, typename Context_Service>
explicit stream(Arg& arg, basic_context<Context_Service>& context) explicit stream(Arg& arg, basic_context<Context_Service>& context)
: next_layer_(arg), : next_layer_(arg),
service_(asio::use_service<Service>(next_layer_.io_service())), service_(asio::use_service<Service>(next_layer_.get_io_service())),
impl_(service_.null()) impl_(service_.null())
{ {
service_.create(impl_, next_layer_, context); service_.create(impl_, next_layer_, context);
@ -97,7 +97,8 @@ public:
service_.destroy(impl_, next_layer_); service_.destroy(impl_, next_layer_);
} }
/// Get the io_service associated with the object. /// (Deprecated: use get_io_service().) Get the io_service associated with
/// the object.
/** /**
* This function may be used to obtain the io_service object that the stream * This function may be used to obtain the io_service object that the stream
* uses to dispatch handlers for asynchronous operations. * uses to dispatch handlers for asynchronous operations.
@ -107,7 +108,20 @@ public:
*/ */
asio::io_service& io_service() asio::io_service& io_service()
{ {
return next_layer_.io_service(); return next_layer_.get_io_service();
}
/// Get the io_service associated with the object.
/**
* This function may be used to obtain the io_service object that the stream
* uses to dispatch handlers for asynchronous operations.
*
* @return A reference to the io_service object that stream will use to
* dispatch handlers. Ownership is not transferred to the caller.
*/
asio::io_service& get_io_service()
{
return next_layer_.get_io_service();
} }
/// Get a reference to the next layer. /// Get a reference to the next layer.

View file

@ -65,7 +65,8 @@ public:
service_.destroy(impl_); service_.destroy(impl_);
} }
/// Get the io_service associated with the strand. /// (Deprecated: use get_io_service().) Get the io_service associated with
/// the strand.
/** /**
* This function may be used to obtain the io_service object that the strand * This function may be used to obtain the io_service object that the strand
* uses to dispatch handlers for asynchronous operations. * uses to dispatch handlers for asynchronous operations.
@ -75,7 +76,20 @@ public:
*/ */
asio::io_service& io_service() asio::io_service& io_service()
{ {
return service_.io_service(); return service_.get_io_service();
}
/// Get the io_service associated with the strand.
/**
* This function may be used to obtain the io_service object that the strand
* uses to dispatch handlers for asynchronous operations.
*
* @return A reference to the io_service object that the strand will use to
* dispatch handlers. Ownership is not transferred to the caller.
*/
asio::io_service& get_io_service()
{
return service_.get_io_service();
} }
/// Request the strand to invoke the given handler. /// Request the strand to invoke the given handler.