asio sync

This commit is contained in:
Marcos Pinto 2007-11-17 12:22:22 +00:00
parent 732c3d8674
commit dc2f24344c
33 changed files with 712 additions and 193 deletions

View File

@ -27,7 +27,7 @@
#include "asio/detail/pop_options.hpp" #include "asio/detail/pop_options.hpp"
#if defined(BOOST_MSVC) #if defined(BOOST_MSVC)
# if defined(_HAS_ITERATOR_DEBUGGING) # if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0)
# if !defined(ASIO_DISABLE_BUFFER_DEBUGGING) # if !defined(ASIO_DISABLE_BUFFER_DEBUGGING)
# define ASIO_ENABLE_BUFFER_DEBUGGING # define ASIO_ENABLE_BUFFER_DEBUGGING
# endif // !defined(ASIO_DISABLE_BUFFER_DEBUGGING) # endif // !defined(ASIO_DISABLE_BUFFER_DEBUGGING)
@ -390,6 +390,11 @@ public:
{ {
} }
~buffer_debug_check()
{
iter_ = Iterator();
}
void operator()() void operator()()
{ {
*iter_; *iter_;

View File

@ -29,6 +29,7 @@
#include "asio/detail/kqueue_reactor.hpp" #include "asio/detail/kqueue_reactor.hpp"
#include "asio/detail/select_reactor.hpp" #include "asio/detail/select_reactor.hpp"
#include "asio/detail/service_base.hpp" #include "asio/detail/service_base.hpp"
#include "asio/detail/win_iocp_io_service.hpp"
namespace asio { namespace asio {
@ -62,7 +63,7 @@ private:
// The type of the platform-specific implementation. // The type of the platform-specific implementation.
#if defined(ASIO_HAS_IOCP) #if defined(ASIO_HAS_IOCP)
typedef detail::deadline_timer_service< typedef detail::deadline_timer_service<
traits_type, detail::select_reactor<true> > service_impl_type; traits_type, detail::win_iocp_io_service> service_impl_type;
#elif defined(ASIO_HAS_EPOLL) #elif defined(ASIO_HAS_EPOLL)
typedef detail::deadline_timer_service< typedef detail::deadline_timer_service<
traits_type, detail::epoll_reactor<false> > service_impl_type; traits_type, detail::epoll_reactor<false> > service_impl_type;

View File

@ -140,22 +140,13 @@ public:
if (read_op_queue_.enqueue_operation(descriptor, handler)) if (read_op_queue_.enqueue_operation(descriptor, handler))
{ {
::pollfd ev = { 0 }; ::pollfd& ev = add_pending_event_change(descriptor);
ev.fd = descriptor;
ev.events = POLLIN | POLLERR | POLLHUP; ev.events = POLLIN | POLLERR | POLLHUP;
if (write_op_queue_.has_operation(descriptor)) if (write_op_queue_.has_operation(descriptor))
ev.events |= POLLOUT; ev.events |= POLLOUT;
if (except_op_queue_.has_operation(descriptor)) if (except_op_queue_.has_operation(descriptor))
ev.events |= POLLPRI; ev.events |= POLLPRI;
ev.revents = 0; interrupter_.interrupt();
int result = ::write(dev_poll_fd_, &ev, sizeof(ev));
if (result != sizeof(ev))
{
asio::error_code ec(errno,
asio::error::system_category);
read_op_queue_.dispatch_all_operations(descriptor, ec);
}
} }
} }
@ -175,22 +166,13 @@ public:
if (write_op_queue_.enqueue_operation(descriptor, handler)) if (write_op_queue_.enqueue_operation(descriptor, handler))
{ {
::pollfd ev = { 0 }; ::pollfd& ev = add_pending_event_change(descriptor);
ev.fd = descriptor;
ev.events = POLLOUT | POLLERR | POLLHUP; ev.events = POLLOUT | POLLERR | POLLHUP;
if (read_op_queue_.has_operation(descriptor)) if (read_op_queue_.has_operation(descriptor))
ev.events |= POLLIN; ev.events |= POLLIN;
if (except_op_queue_.has_operation(descriptor)) if (except_op_queue_.has_operation(descriptor))
ev.events |= POLLPRI; ev.events |= POLLPRI;
ev.revents = 0; interrupter_.interrupt();
int result = ::write(dev_poll_fd_, &ev, sizeof(ev));
if (result != sizeof(ev))
{
asio::error_code ec(errno,
asio::error::system_category);
write_op_queue_.dispatch_all_operations(descriptor, ec);
}
} }
} }
@ -206,22 +188,13 @@ public:
if (except_op_queue_.enqueue_operation(descriptor, handler)) if (except_op_queue_.enqueue_operation(descriptor, handler))
{ {
::pollfd ev = { 0 }; ::pollfd& ev = add_pending_event_change(descriptor);
ev.fd = descriptor;
ev.events = POLLPRI | POLLERR | POLLHUP; ev.events = POLLPRI | POLLERR | POLLHUP;
if (read_op_queue_.has_operation(descriptor)) if (read_op_queue_.has_operation(descriptor))
ev.events |= POLLIN; ev.events |= POLLIN;
if (write_op_queue_.has_operation(descriptor)) if (write_op_queue_.has_operation(descriptor))
ev.events |= POLLOUT; ev.events |= POLLOUT;
ev.revents = 0; interrupter_.interrupt();
int result = ::write(dev_poll_fd_, &ev, sizeof(ev));
if (result != sizeof(ev))
{
asio::error_code ec(errno,
asio::error::system_category);
except_op_queue_.dispatch_all_operations(descriptor, ec);
}
} }
} }
@ -241,21 +214,11 @@ public:
&& need_mod; && need_mod;
if (need_mod) if (need_mod)
{ {
::pollfd ev = { 0 }; ::pollfd& ev = add_pending_event_change(descriptor);
ev.fd = descriptor;
ev.events = POLLOUT | POLLPRI | POLLERR | POLLHUP; ev.events = POLLOUT | POLLPRI | POLLERR | POLLHUP;
if (read_op_queue_.has_operation(descriptor)) if (read_op_queue_.has_operation(descriptor))
ev.events |= POLLIN; ev.events |= POLLIN;
ev.revents = 0; interrupter_.interrupt();
int result = ::write(dev_poll_fd_, &ev, sizeof(ev));
if (result != sizeof(ev))
{
asio::error_code ec(errno,
asio::error::system_category);
write_op_queue_.dispatch_all_operations(descriptor, ec);
except_op_queue_.dispatch_all_operations(descriptor, ec);
}
} }
} }
@ -285,11 +248,9 @@ public:
asio::detail::mutex::scoped_lock lock(mutex_); asio::detail::mutex::scoped_lock lock(mutex_);
// Remove the descriptor from /dev/poll. // Remove the descriptor from /dev/poll.
::pollfd ev = { 0 }; ::pollfd& ev = add_pending_event_change(descriptor);
ev.fd = descriptor;
ev.events = POLLREMOVE; ev.events = POLLREMOVE;
ev.revents = 0; interrupter_.interrupt();
::write(dev_poll_fd_, &ev, sizeof(ev));
// Cancel any outstanding operations associated with the descriptor. // Cancel any outstanding operations associated with the descriptor.
cancel_ops_unlocked(descriptor); cancel_ops_unlocked(descriptor);
@ -374,6 +335,26 @@ private:
return; return;
} }
// Write the pending event registration changes to the /dev/poll descriptor.
std::size_t events_size = sizeof(::pollfd) * pending_event_changes_.size();
errno = 0;
int result = ::write(dev_poll_fd_,
&pending_event_changes_[0], events_size);
if (result != static_cast<int>(events_size))
{
for (std::size_t i = 0; i < pending_event_changes_.size(); ++i)
{
int descriptor = pending_event_changes_[i].fd;
asio::error_code ec = asio::error_code(
errno, asio::error::get_system_category());
read_op_queue_.dispatch_all_operations(descriptor, ec);
write_op_queue_.dispatch_all_operations(descriptor, ec);
except_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
pending_event_changes_.clear();
pending_event_change_index_.clear();
int timeout = block ? get_timeout() : 0; int timeout = block ? get_timeout() : 0;
wait_in_progress_ = true; wait_in_progress_ = true;
lock.unlock(); lock.unlock();
@ -454,7 +435,7 @@ private:
if (result != sizeof(ev)) if (result != sizeof(ev))
{ {
ec = asio::error_code(errno, ec = asio::error_code(errno,
asio::error::system_category); asio::error::get_system_category());
read_op_queue_.dispatch_all_operations(descriptor, ec); read_op_queue_.dispatch_all_operations(descriptor, ec);
write_op_queue_.dispatch_all_operations(descriptor, ec); write_op_queue_.dispatch_all_operations(descriptor, ec);
except_op_queue_.dispatch_all_operations(descriptor, ec); except_op_queue_.dispatch_all_operations(descriptor, ec);
@ -513,7 +494,7 @@ private:
boost::throw_exception( boost::throw_exception(
asio::system_error( asio::system_error(
asio::error_code(errno, asio::error_code(errno,
asio::error::system_category), asio::error::get_system_category()),
"/dev/poll")); "/dev/poll"));
} }
return fd; return fd;
@ -588,12 +569,39 @@ private:
timer_queues_for_cleanup_[i]->cleanup_timers(); timer_queues_for_cleanup_[i]->cleanup_timers();
} }
// Add a pending event entry for the given descriptor.
::pollfd& add_pending_event_change(int descriptor)
{
hash_map<int, std::size_t>::iterator iter
= pending_event_change_index_.find(descriptor);
if (iter == pending_event_change_index_.end())
{
std::size_t index = pending_event_changes_.size();
pending_event_changes_.reserve(pending_event_changes_.size() + 1);
pending_event_change_index_.insert(std::make_pair(descriptor, index));
pending_event_changes_.push_back(::pollfd());
pending_event_changes_[index].fd = descriptor;
pending_event_changes_[index].revents = 0;
return pending_event_changes_[index];
}
else
{
return pending_event_changes_[iter->second];
}
}
// Mutex to protect access to internal data. // Mutex to protect access to internal data.
asio::detail::mutex mutex_; asio::detail::mutex mutex_;
// The /dev/poll file descriptor. // The /dev/poll file descriptor.
int dev_poll_fd_; int dev_poll_fd_;
// Vector of /dev/poll events waiting to be written to the descriptor.
std::vector< ::pollfd> pending_event_changes_;
// Hash map to associate a descriptor with a pending event change index.
hash_map<int, std::size_t> pending_event_change_index_;
// Whether the DP_POLL operation is currently in progress // Whether the DP_POLL operation is currently in progress
bool wait_in_progress_; bool wait_in_progress_;

View File

@ -160,7 +160,7 @@ public:
if (result != 0) if (result != 0)
{ {
asio::error_code ec(errno, asio::error_code ec(errno,
asio::error::system_category); asio::error::get_system_category());
read_op_queue_.dispatch_all_operations(descriptor, ec); read_op_queue_.dispatch_all_operations(descriptor, ec);
} }
} }
@ -196,7 +196,7 @@ public:
if (result != 0) if (result != 0)
{ {
asio::error_code ec(errno, asio::error_code ec(errno,
asio::error::system_category); asio::error::get_system_category());
write_op_queue_.dispatch_all_operations(descriptor, ec); write_op_queue_.dispatch_all_operations(descriptor, ec);
} }
} }
@ -228,7 +228,7 @@ public:
if (result != 0) if (result != 0)
{ {
asio::error_code ec(errno, asio::error_code ec(errno,
asio::error::system_category); asio::error::get_system_category());
except_op_queue_.dispatch_all_operations(descriptor, ec); except_op_queue_.dispatch_all_operations(descriptor, ec);
} }
} }
@ -262,7 +262,7 @@ public:
if (result != 0) if (result != 0)
{ {
asio::error_code ec(errno, asio::error_code ec(errno,
asio::error::system_category); asio::error::get_system_category());
write_op_queue_.dispatch_all_operations(descriptor, ec); write_op_queue_.dispatch_all_operations(descriptor, ec);
except_op_queue_.dispatch_all_operations(descriptor, ec); except_op_queue_.dispatch_all_operations(descriptor, ec);
} }
@ -456,7 +456,7 @@ private:
if (result != 0) if (result != 0)
{ {
ec = asio::error_code(errno, ec = asio::error_code(errno,
asio::error::system_category); asio::error::get_system_category());
read_op_queue_.dispatch_all_operations(descriptor, ec); read_op_queue_.dispatch_all_operations(descriptor, ec);
write_op_queue_.dispatch_all_operations(descriptor, ec); write_op_queue_.dispatch_all_operations(descriptor, ec);
except_op_queue_.dispatch_all_operations(descriptor, ec); except_op_queue_.dispatch_all_operations(descriptor, ec);
@ -518,7 +518,7 @@ private:
boost::throw_exception( boost::throw_exception(
asio::system_error( asio::system_error(
asio::error_code(errno, asio::error_code(errno,
asio::error::system_category), asio::error::get_system_category()),
"epoll")); "epoll"));
} }
return fd; return fd;

View File

@ -151,7 +151,7 @@ public:
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{ {
asio::error_code ec(errno, asio::error_code ec(errno,
asio::error::system_category); asio::error::get_system_category());
read_op_queue_.dispatch_all_operations(descriptor, ec); read_op_queue_.dispatch_all_operations(descriptor, ec);
} }
} }
@ -178,7 +178,7 @@ public:
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{ {
asio::error_code ec(errno, asio::error_code ec(errno,
asio::error::system_category); asio::error::get_system_category());
write_op_queue_.dispatch_all_operations(descriptor, ec); write_op_queue_.dispatch_all_operations(descriptor, ec);
} }
} }
@ -204,7 +204,7 @@ public:
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{ {
asio::error_code ec(errno, asio::error_code ec(errno,
asio::error::system_category); asio::error::get_system_category());
except_op_queue_.dispatch_all_operations(descriptor, ec); except_op_queue_.dispatch_all_operations(descriptor, ec);
} }
} }
@ -228,7 +228,7 @@ public:
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{ {
asio::error_code ec(errno, asio::error_code ec(errno,
asio::error::system_category); asio::error::get_system_category());
write_op_queue_.dispatch_all_operations(descriptor, ec); write_op_queue_.dispatch_all_operations(descriptor, ec);
} }
} }
@ -243,7 +243,7 @@ public:
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{ {
asio::error_code ec(errno, asio::error_code ec(errno,
asio::error::system_category); asio::error::get_system_category());
except_op_queue_.dispatch_all_operations(descriptor, ec); except_op_queue_.dispatch_all_operations(descriptor, ec);
write_op_queue_.dispatch_all_operations(descriptor, ec); write_op_queue_.dispatch_all_operations(descriptor, ec);
} }
@ -397,7 +397,7 @@ private:
if (events[i].flags & EV_ERROR) if (events[i].flags & EV_ERROR)
{ {
asio::error_code error( asio::error_code error(
events[i].data, asio::error::system_category); events[i].data, asio::error::get_system_category());
except_op_queue_.dispatch_all_operations(descriptor, error); except_op_queue_.dispatch_all_operations(descriptor, error);
read_op_queue_.dispatch_all_operations(descriptor, error); read_op_queue_.dispatch_all_operations(descriptor, error);
} }
@ -428,7 +428,7 @@ private:
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{ {
asio::error_code error(errno, asio::error_code error(errno,
asio::error::system_category); asio::error::get_system_category());
except_op_queue_.dispatch_all_operations(descriptor, error); except_op_queue_.dispatch_all_operations(descriptor, error);
read_op_queue_.dispatch_all_operations(descriptor, error); read_op_queue_.dispatch_all_operations(descriptor, error);
} }
@ -440,7 +440,7 @@ private:
if (events[i].flags & EV_ERROR) if (events[i].flags & EV_ERROR)
{ {
asio::error_code error( asio::error_code error(
events[i].data, asio::error::system_category); events[i].data, asio::error::get_system_category());
write_op_queue_.dispatch_all_operations(descriptor, error); write_op_queue_.dispatch_all_operations(descriptor, error);
} }
else else
@ -458,7 +458,7 @@ private:
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{ {
asio::error_code error(errno, asio::error_code error(errno,
asio::error::system_category); asio::error::get_system_category());
write_op_queue_.dispatch_all_operations(descriptor, error); write_op_queue_.dispatch_all_operations(descriptor, error);
} }
} }
@ -515,7 +515,7 @@ private:
boost::throw_exception( boost::throw_exception(
asio::system_error( asio::system_error(
asio::error_code(errno, asio::error_code(errno,
asio::error::system_category), asio::error::get_system_category()),
"kqueue")); "kqueue"));
} }
return fd; return fd;

View File

@ -51,7 +51,8 @@ public:
} }
else else
{ {
asio::error_code ec(errno, asio::error::system_category); asio::error_code ec(errno,
asio::error::get_system_category());
asio::system_error e(ec, "pipe_select_interrupter"); asio::system_error e(ec, "pipe_select_interrupter");
boost::throw_exception(e); boost::throw_exception(e);
} }

View File

@ -48,7 +48,8 @@ public:
if (error != 0) if (error != 0)
{ {
asio::system_error e( asio::system_error e(
asio::error_code(error, asio::error::system_category), asio::error_code(error,
asio::error::get_system_category()),
"event"); "event");
boost::throw_exception(e); boost::throw_exception(e);
} }

View File

@ -51,7 +51,8 @@ public:
if (error != 0) if (error != 0)
{ {
asio::system_error e( asio::system_error e(
asio::error_code(error, asio::error::system_category), asio::error_code(error,
asio::error::get_system_category()),
"mutex"); "mutex");
boost::throw_exception(e); boost::throw_exception(e);
} }
@ -70,7 +71,8 @@ public:
if (error != 0) if (error != 0)
{ {
asio::system_error e( asio::system_error e(
asio::error_code(error, asio::error::system_category), asio::error_code(error,
asio::error::get_system_category()),
"mutex"); "mutex");
boost::throw_exception(e); boost::throw_exception(e);
} }
@ -83,7 +85,8 @@ public:
if (error != 0) if (error != 0)
{ {
asio::system_error e( asio::system_error e(
asio::error_code(error, asio::error::system_category), asio::error_code(error,
asio::error::get_system_category()),
"mutex"); "mutex");
boost::throw_exception(e); boost::throw_exception(e);
} }

View File

@ -53,7 +53,8 @@ public:
if (error != 0) if (error != 0)
{ {
asio::system_error e( asio::system_error e(
asio::error_code(error, asio::error::system_category), asio::error_code(error,
asio::error::get_system_category()),
"thread"); "thread");
boost::throw_exception(e); boost::throw_exception(e);
} }

View File

@ -47,7 +47,8 @@ public:
if (error != 0) if (error != 0)
{ {
asio::system_error e( asio::system_error e(
asio::error_code(error, asio::error::system_category), asio::error_code(error,
asio::error::get_system_category()),
"tss"); "tss");
boost::throw_exception(e); boost::throw_exception(e);
} }

View File

@ -157,7 +157,8 @@ public:
if (int err = reactor_.register_descriptor(sock.get())) if (int err = reactor_.register_descriptor(sock.get()))
{ {
ec = asio::error_code(err, asio::error::system_category); ec = asio::error_code(err,
asio::error::get_system_category());
return ec; return ec;
} }
@ -181,7 +182,8 @@ public:
if (int err = reactor_.register_descriptor(native_socket)) if (int err = reactor_.register_descriptor(native_socket))
{ {
ec = asio::error_code(err, asio::error::system_category); ec = asio::error_code(err,
asio::error::get_system_category());
return ec; return ec;
} }
@ -1489,7 +1491,7 @@ public:
if (connect_error) if (connect_error)
{ {
ec = asio::error_code(connect_error, ec = asio::error_code(connect_error,
asio::error::system_category); asio::error::get_system_category());
io_service_.post(bind_handler(handler_, ec)); io_service_.post(bind_handler(handler_, ec));
return true; return true;
} }

View File

@ -48,10 +48,11 @@ extern "C" unsigned int if_nametoindex(const char*);
inline void clear_error(asio::error_code& ec) inline void clear_error(asio::error_code& ec)
{ {
errno = 0;
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
WSASetLastError(0); WSASetLastError(0);
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #else
errno = 0;
#endif
ec = asio::error_code(); ec = asio::error_code();
} }
@ -61,9 +62,10 @@ inline ReturnType error_wrapper(ReturnType return_value,
{ {
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
ec = asio::error_code(WSAGetLastError(), ec = asio::error_code(WSAGetLastError(),
asio::error::system_category); asio::error::get_system_category());
#else #else
ec = asio::error_code(errno, asio::error::system_category); ec = asio::error_code(errno,
asio::error::get_system_category());
#endif #endif
return return_value; return return_value;
} }
@ -100,6 +102,10 @@ inline socket_type accept(socket_type s, socket_addr_type* addr,
} }
#endif #endif
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
clear_error(ec);
#endif
return new_s; return new_s;
} }
@ -114,14 +120,25 @@ inline int bind(socket_type s, const socket_addr_type* addr,
std::size_t addrlen, asio::error_code& ec) std::size_t addrlen, asio::error_code& ec)
{ {
clear_error(ec); clear_error(ec);
return error_wrapper(call_bind(&msghdr::msg_namelen, s, addr, addrlen), ec); int result = error_wrapper(call_bind(
&msghdr::msg_namelen, s, addr, addrlen), ec);
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
if (result == 0)
clear_error(ec);
#endif
return result;
} }
inline int close(socket_type s, asio::error_code& ec) inline int close(socket_type s, asio::error_code& ec)
{ {
clear_error(ec); clear_error(ec);
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
return error_wrapper(::closesocket(s), ec); int result = error_wrapper(::closesocket(s), ec);
# if defined(UNDER_CE)
if (result == 0)
clear_error(ec);
# endif
return result;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
return error_wrapper(::close(s), ec); return error_wrapper(::close(s), ec);
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@ -130,7 +147,12 @@ inline int close(socket_type s, asio::error_code& ec)
inline int shutdown(socket_type s, int what, asio::error_code& ec) inline int shutdown(socket_type s, int what, asio::error_code& ec)
{ {
clear_error(ec); clear_error(ec);
return error_wrapper(::shutdown(s, what), ec); int result = error_wrapper(::shutdown(s, what), ec);
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
if (result == 0)
clear_error(ec);
#endif
return result;
} }
template <typename SockLenType> template <typename SockLenType>
@ -144,14 +166,24 @@ inline int connect(socket_type s, const socket_addr_type* addr,
std::size_t addrlen, asio::error_code& ec) std::size_t addrlen, asio::error_code& ec)
{ {
clear_error(ec); clear_error(ec);
return error_wrapper(call_connect( int result = error_wrapper(call_connect(
&msghdr::msg_namelen, s, addr, addrlen), ec); &msghdr::msg_namelen, s, addr, addrlen), ec);
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
if (result == 0)
clear_error(ec);
#endif
return result;
} }
inline int listen(socket_type s, int backlog, asio::error_code& ec) inline int listen(socket_type s, int backlog, asio::error_code& ec)
{ {
clear_error(ec); clear_error(ec);
return error_wrapper(::listen(s, backlog), ec); int result = error_wrapper(::listen(s, backlog), ec);
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
if (result == 0)
clear_error(ec);
#endif
return result;
} }
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@ -217,6 +249,9 @@ inline int recv(socket_type s, buf* bufs, size_t count, int flags,
recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec); recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec);
if (result != 0) if (result != 0)
return -1; return -1;
# if defined(UNDER_CE)
clear_error(ec);
# endif
return bytes_transferred; return bytes_transferred;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
msghdr msg = msghdr(); msghdr msg = msghdr();
@ -242,6 +277,9 @@ inline int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
*addrlen = (std::size_t)tmp_addrlen; *addrlen = (std::size_t)tmp_addrlen;
if (result != 0) if (result != 0)
return -1; return -1;
# if defined(UNDER_CE)
clear_error(ec);
# endif
return bytes_transferred; return bytes_transferred;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
msghdr msg = msghdr(); msghdr msg = msghdr();
@ -268,6 +306,9 @@ inline int send(socket_type s, const buf* bufs, size_t count, int flags,
send_buf_count, &bytes_transferred, send_flags, 0, 0), ec); send_buf_count, &bytes_transferred, send_flags, 0, 0), ec);
if (result != 0) if (result != 0)
return -1; return -1;
# if defined(UNDER_CE)
clear_error(ec);
# endif
return bytes_transferred; return bytes_transferred;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
msghdr msg = msghdr(); msghdr msg = msghdr();
@ -290,9 +331,13 @@ inline int sendto(socket_type s, const buf* bufs, size_t count, int flags,
DWORD send_buf_count = static_cast<DWORD>(count); DWORD send_buf_count = static_cast<DWORD>(count);
DWORD bytes_transferred = 0; DWORD bytes_transferred = 0;
int result = error_wrapper(::WSASendTo(s, const_cast<buf*>(bufs), int result = error_wrapper(::WSASendTo(s, const_cast<buf*>(bufs),
send_buf_count, &bytes_transferred, flags, addr, addrlen, 0, 0), ec); send_buf_count, &bytes_transferred, flags, addr,
static_cast<int>(addrlen), 0, 0), ec);
if (result != 0) if (result != 0)
return -1; return -1;
# if defined(UNDER_CE)
clear_error(ec);
# endif
return bytes_transferred; return bytes_transferred;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
msghdr msg = msghdr(); msghdr msg = msghdr();
@ -327,6 +372,10 @@ inline socket_type socket(int af, int type, int protocol,
reinterpret_cast<const char*>(&optval), sizeof(optval)); reinterpret_cast<const char*>(&optval), sizeof(optval));
} }
# if defined(UNDER_CE)
clear_error(ec);
# endif
return s; return s;
#elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__) #elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
socket_type s = error_wrapper(::socket(af, type, protocol), ec); socket_type s = error_wrapper(::socket(af, type, protocol), ec);
@ -385,8 +434,13 @@ inline int setsockopt(socket_type s, int level, int optname,
return -1; return -1;
#else // defined(__BORLANDC__) #else // defined(__BORLANDC__)
clear_error(ec); clear_error(ec);
return error_wrapper(call_setsockopt(&msghdr::msg_namelen, int result = error_wrapper(call_setsockopt(&msghdr::msg_namelen,
s, level, optname, optval, optlen), ec); s, level, optname, optval, optlen), ec);
# if defined(BOOST_WINDOWS) && defined(UNDER_CE)
if (result == 0)
clear_error(ec);
# endif
return result;
#endif // defined(__BORLANDC__) #endif // defined(__BORLANDC__)
} }
@ -455,6 +509,10 @@ inline int getsockopt(socket_type s, int level, int optname, void* optval,
*static_cast<DWORD*>(optval) = 1; *static_cast<DWORD*>(optval) = 1;
clear_error(ec); clear_error(ec);
} }
# if defined(UNDER_CE)
if (result == 0)
clear_error(ec);
# endif
return result; return result;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
clear_error(ec); clear_error(ec);
@ -490,8 +548,13 @@ inline int getpeername(socket_type s, socket_addr_type* addr,
std::size_t* addrlen, asio::error_code& ec) std::size_t* addrlen, asio::error_code& ec)
{ {
clear_error(ec); clear_error(ec);
return error_wrapper(call_getpeername( int result = error_wrapper(call_getpeername(
&msghdr::msg_namelen, s, addr, addrlen), ec); &msghdr::msg_namelen, s, addr, addrlen), ec);
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
if (result == 0)
clear_error(ec);
#endif
return result;
} }
template <typename SockLenType> template <typename SockLenType>
@ -508,8 +571,13 @@ inline int getsockname(socket_type s, socket_addr_type* addr,
std::size_t* addrlen, asio::error_code& ec) std::size_t* addrlen, asio::error_code& ec)
{ {
clear_error(ec); clear_error(ec);
return error_wrapper(call_getsockname( int result = error_wrapper(call_getsockname(
&msghdr::msg_namelen, s, addr, addrlen), ec); &msghdr::msg_namelen, s, addr, addrlen), ec);
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
if (result == 0)
clear_error(ec);
#endif
return result;
} }
inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg, inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg,
@ -517,7 +585,12 @@ inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg,
{ {
clear_error(ec); clear_error(ec);
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
return error_wrapper(::ioctlsocket(s, cmd, arg), ec); int result = error_wrapper(::ioctlsocket(s, cmd, arg), ec);
# if defined(UNDER_CE)
if (result == 0)
clear_error(ec);
# endif
return result;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
return error_wrapper(::ioctl(s, cmd, arg), ec); return error_wrapper(::ioctl(s, cmd, arg), ec);
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@ -556,8 +629,13 @@ inline int select(int nfds, fd_set* readfds, fd_set* writefds,
return error_wrapper(::pselect(nfds, readfds, return error_wrapper(::pselect(nfds, readfds,
writefds, exceptfds, timeout ? &ts : 0, 0), ec); writefds, exceptfds, timeout ? &ts : 0, 0), ec);
#else #else
return error_wrapper(::select(nfds, readfds, int result = error_wrapper(::select(nfds, readfds,
writefds, exceptfds, timeout), ec); writefds, exceptfds, timeout), ec);
# if defined(BOOST_WINDOWS) && defined(UNDER_CE)
if (result >= 0)
clear_error(ec);
# endif
return result;
#endif #endif
} }
@ -568,7 +646,12 @@ inline int poll_read(socket_type s, asio::error_code& ec)
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(s, &fds); FD_SET(s, &fds);
clear_error(ec); clear_error(ec);
return error_wrapper(::select(s, &fds, 0, 0, 0), ec); int result = error_wrapper(::select(s, &fds, 0, 0, 0), ec);
# if defined(UNDER_CE)
if (result >= 0)
clear_error(ec);
# endif
return result;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
pollfd fds; pollfd fds;
fds.fd = s; fds.fd = s;
@ -586,7 +669,12 @@ inline int poll_write(socket_type s, asio::error_code& ec)
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(s, &fds); FD_SET(s, &fds);
clear_error(ec); clear_error(ec);
return error_wrapper(::select(s, 0, &fds, 0, 0), ec); int result = error_wrapper(::select(s, 0, &fds, 0, 0), ec);
# if defined(UNDER_CE)
if (result >= 0)
clear_error(ec);
# endif
return result;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
pollfd fds; pollfd fds;
fds.fd = s; fds.fd = s;
@ -634,9 +722,17 @@ inline const char* inet_ntop(int af, const void* src, char* dest, size_t length,
} }
DWORD string_length = static_cast<DWORD>(length); DWORD string_length = static_cast<DWORD>(length);
#if defined(BOOST_NO_ANSI_APIS)
LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR));
int result = error_wrapper(::WSAAddressToStringW(
reinterpret_cast<sockaddr*>(&address),
address_length, 0, string_buffer, &string_length), ec);
::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1, dest, length, 0, 0);
#else
int result = error_wrapper(::WSAAddressToStringA( int result = error_wrapper(::WSAAddressToStringA(
reinterpret_cast<sockaddr*>(&address), reinterpret_cast<sockaddr*>(&address),
address_length, 0, dest, &string_length), ec); address_length, 0, dest, &string_length), ec);
#endif
// Windows may set error code on success. // Windows may set error code on success.
if (result != socket_error_retval) if (result != socket_error_retval)
@ -680,10 +776,20 @@ inline int inet_pton(int af, const char* src, void* dest,
sockaddr_storage_type address; sockaddr_storage_type address;
int address_length = sizeof(sockaddr_storage_type); int address_length = sizeof(sockaddr_storage_type);
#if defined(BOOST_NO_ANSI_APIS)
int num_wide_chars = strlen(src) + 1;
LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR));
::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars);
int result = error_wrapper(::WSAStringToAddressW(
wide_buffer, af, 0,
reinterpret_cast<sockaddr*>(&address),
&address_length), ec);
#else
int result = error_wrapper(::WSAStringToAddressA( int result = error_wrapper(::WSAStringToAddressA(
const_cast<char*>(src), af, 0, const_cast<char*>(src), af, 0,
reinterpret_cast<sockaddr*>(&address), reinterpret_cast<sockaddr*>(&address),
&address_length), ec); &address_length), ec);
#endif
if (af == AF_INET) if (af == AF_INET)
{ {
@ -717,6 +823,11 @@ inline int inet_pton(int af, const char* src, void* dest,
if (result == socket_error_retval && !ec) if (result == socket_error_retval && !ec)
ec = asio::error::invalid_argument; ec = asio::error::invalid_argument;
#if defined(UNDER_CE)
if (result != socket_error_retval)
clear_error(ec);
#endif
return result == socket_error_retval ? -1 : 1; return result == socket_error_retval ? -1 : 1;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
int result = error_wrapper(::inet_pton(af, src, dest), ec); int result = error_wrapper(::inet_pton(af, src, dest), ec);
@ -743,7 +854,12 @@ inline int inet_pton(int af, const char* src, void* dest,
inline int gethostname(char* name, int namelen, asio::error_code& ec) inline int gethostname(char* name, int namelen, asio::error_code& ec)
{ {
clear_error(ec); clear_error(ec);
return error_wrapper(::gethostname(name, namelen), ec); int result = error_wrapper(::gethostname(name, namelen), ec);
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
if (result == 0)
clear_error(ec);
#endif
return result;
} }
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) \ #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) \
@ -782,6 +898,9 @@ inline hostent* gethostbyaddr(const char* addr, int length, int af,
hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec); hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec);
if (!retval) if (!retval)
return 0; return 0;
# if defined(UNDER_CE)
clear_error(ec);
# endif
*result = *retval; *result = *retval;
return retval; return retval;
#elif defined(__sun) || defined(__QNX__) #elif defined(__sun) || defined(__QNX__)
@ -830,6 +949,9 @@ inline hostent* gethostbyname(const char* name, int af, struct hostent* result,
hostent* retval = error_wrapper(::gethostbyname(name), ec); hostent* retval = error_wrapper(::gethostbyname(name), ec);
if (!retval) if (!retval)
return 0; return 0;
# if defined(UNDER_CE)
clear_error(ec);
# endif
*result = *retval; *result = *retval;
return result; return result;
#elif defined(__sun) || defined(__QNX__) #elif defined(__sun) || defined(__QNX__)
@ -1601,10 +1723,10 @@ inline asio::error_code translate_addrinfo_error(int error)
default: // Possibly the non-portable EAI_SYSTEM. default: // Possibly the non-portable EAI_SYSTEM.
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
return asio::error_code( return asio::error_code(
WSAGetLastError(), asio::error::system_category); WSAGetLastError(), asio::error::get_system_category());
#else #else
return asio::error_code( return asio::error_code(
errno, asio::error::system_category); errno, asio::error::get_system_category());
#endif #endif
} }
} }
@ -1615,7 +1737,7 @@ inline asio::error_code getaddrinfo(const char* host,
{ {
clear_error(ec); clear_error(ec);
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) # if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
// Building for Windows XP, Windows Server 2003, or later. // Building for Windows XP, Windows Server 2003, or later.
int error = ::getaddrinfo(host, service, hints, result); int error = ::getaddrinfo(host, service, hints, result);
return ec = translate_addrinfo_error(error); return ec = translate_addrinfo_error(error);
@ -1646,7 +1768,7 @@ inline asio::error_code getaddrinfo(const char* host,
inline void freeaddrinfo(addrinfo_type* ai) inline void freeaddrinfo(addrinfo_type* ai)
{ {
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) # if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
// Building for Windows XP, Windows Server 2003, or later. // Building for Windows XP, Windows Server 2003, or later.
::freeaddrinfo(ai); ::freeaddrinfo(ai);
# else # else
@ -1674,7 +1796,7 @@ inline asio::error_code getnameinfo(const socket_addr_type* addr,
char* serv, std::size_t servlen, int flags, asio::error_code& ec) char* serv, std::size_t servlen, int flags, asio::error_code& ec)
{ {
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) # if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
// Building for Windows XP, Windows Server 2003, or later. // Building for Windows XP, Windows Server 2003, or later.
clear_error(ec); clear_error(ec);
int error = ::getnameinfo(addr, addrlen, host, static_cast<DWORD>(hostlen), int error = ::getnameinfo(addr, addrlen, host, static_cast<DWORD>(hostlen),
@ -1737,8 +1859,6 @@ inline u_short_type host_to_network_short(u_short_type value)
} // namespace detail } // namespace detail
} // namespace asio } // namespace asio
#undef ASIO_SOCKET_CALL
#include "asio/detail/pop_options.hpp" #include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_SOCKET_OPS_HPP #endif // ASIO_DETAIL_SOCKET_OPS_HPP

View File

@ -80,7 +80,9 @@
# undef ASIO_WSPIAPI_H_DEFINED # undef ASIO_WSPIAPI_H_DEFINED
# endif // defined(ASIO_WSPIAPI_H_DEFINED) # endif // defined(ASIO_WSPIAPI_H_DEFINED)
# if !defined(ASIO_NO_DEFAULT_LINKED_LIBS) # if !defined(ASIO_NO_DEFAULT_LINKED_LIBS)
# if defined(_MSC_VER) || defined(__BORLANDC__) # if defined(UNDER_CE)
# pragma comment(lib, "ws2.lib")
# elif defined(_MSC_VER) || defined(__BORLANDC__)
# pragma comment(lib, "ws2_32.lib") # pragma comment(lib, "ws2_32.lib")
# pragma comment(lib, "mswsock.lib") # pragma comment(lib, "mswsock.lib")
# endif // defined(_MSC_VER) || defined(__BORLANDC__) # endif // defined(_MSC_VER) || defined(__BORLANDC__)

View File

@ -24,7 +24,11 @@
#if !defined(BOOST_HAS_THREADS) #if !defined(BOOST_HAS_THREADS)
# include "asio/detail/null_thread.hpp" # include "asio/detail/null_thread.hpp"
#elif defined(BOOST_WINDOWS) #elif defined(BOOST_WINDOWS)
# include "asio/detail/win_thread.hpp" # if defined(UNDER_CE)
# include "asio/detail/wince_thread.hpp"
# else
# include "asio/detail/win_thread.hpp"
# endif
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
# include "asio/detail/posix_thread.hpp" # include "asio/detail/posix_thread.hpp"
#else #else
@ -37,7 +41,11 @@ namespace detail {
#if !defined(BOOST_HAS_THREADS) #if !defined(BOOST_HAS_THREADS)
typedef null_thread thread; typedef null_thread thread;
#elif defined(BOOST_WINDOWS) #elif defined(BOOST_WINDOWS)
# if defined(UNDER_CE)
typedef wince_thread thread;
# else
typedef win_thread thread; typedef win_thread thread;
# endif
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
typedef posix_thread thread; typedef posix_thread thread;
#endif #endif

View File

@ -162,13 +162,7 @@ public:
// Destroy timers that are waiting to be cleaned up. // Destroy timers that are waiting to be cleaned up.
virtual void cleanup_timers() virtual void cleanup_timers()
{ {
while (cleanup_timers_) destroy_timer_list(cleanup_timers_);
{
timer_base* next_timer = cleanup_timers_->next_;
cleanup_timers_->next_ = 0;
cleanup_timers_->destroy();
cleanup_timers_ = next_timer;
}
} }
// Destroy all timers. // Destroy all timers.
@ -181,11 +175,12 @@ public:
timer_base* t = i->second; timer_base* t = i->second;
typename hash_map<void*, timer_base*>::iterator old_i = i++; typename hash_map<void*, timer_base*>::iterator old_i = i++;
timers_.erase(old_i); timers_.erase(old_i);
t->destroy(); destroy_timer_list(t);
} }
heap_.clear(); heap_.clear();
timers_.clear(); timers_.clear();
cleanup_timers(); destroy_timer_list(cancelled_timers_);
destroy_timer_list(cleanup_timers_);
} }
private: private:
@ -367,6 +362,18 @@ private:
} }
} }
// Destroy all timers in a linked list.
void destroy_timer_list(timer_base*& t)
{
while (t)
{
timer_base* next = t->next_;
t->next_ = 0;
t->destroy();
t = next;
}
}
// A hash of timer token to linked lists of timers. // A hash of timer token to linked lists of timers.
hash_map<void*, timer_base*> timers_; hash_map<void*, timer_base*> timers_;

View File

@ -49,7 +49,7 @@ public:
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
asio::system_error e( asio::system_error e(
asio::error_code(last_error, asio::error_code(last_error,
asio::error::system_category), asio::error::get_system_category()),
"event"); "event");
boost::throw_exception(e); boost::throw_exception(e);
} }

View File

@ -33,7 +33,9 @@
#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/service_base.hpp" #include "asio/detail/service_base.hpp"
#include "asio/detail/socket_types.hpp" #include "asio/detail/socket_types.hpp"
#include "asio/detail/timer_queue.hpp"
#include "asio/detail/win_iocp_operation.hpp" #include "asio/detail/win_iocp_operation.hpp"
#include "asio/detail/mutex.hpp"
namespace asio { namespace asio {
namespace detail { namespace detail {
@ -51,7 +53,9 @@ public:
iocp_(), iocp_(),
outstanding_work_(0), outstanding_work_(0),
stopped_(0), stopped_(0),
shutdown_(0) shutdown_(0),
timer_thread_(0),
timer_interrupt_issued_(false)
{ {
} }
@ -64,7 +68,7 @@ public:
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
asio::system_error e( asio::system_error e(
asio::error_code(last_error, asio::error_code(last_error,
asio::error::system_category), asio::error::get_system_category()),
"iocp"); "iocp");
boost::throw_exception(e); boost::throw_exception(e);
} }
@ -93,6 +97,10 @@ public:
if (overlapped) if (overlapped)
static_cast<operation*>(overlapped)->destroy(); static_cast<operation*>(overlapped)->destroy();
} }
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
timer_queues_[i]->destroy_timers();
timer_queues_.clear();
} }
// Register a handle with the IO completion port. // Register a handle with the IO completion port.
@ -175,7 +183,7 @@ public:
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
asio::system_error e( asio::system_error e(
asio::error_code(last_error, asio::error_code(last_error,
asio::error::system_category), asio::error::get_system_category()),
"pqcs"); "pqcs");
boost::throw_exception(e); boost::throw_exception(e);
} }
@ -231,7 +239,7 @@ public:
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
asio::system_error e( asio::system_error e(
asio::error_code(last_error, asio::error_code(last_error,
asio::error::system_category), asio::error::get_system_category()),
"pqcs"); "pqcs");
boost::throw_exception(e); boost::throw_exception(e);
} }
@ -251,20 +259,102 @@ public:
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
asio::system_error e( asio::system_error e(
asio::error_code(last_error, asio::error_code(last_error,
asio::error::system_category), asio::error::get_system_category()),
"pqcs"); "pqcs");
boost::throw_exception(e); boost::throw_exception(e);
} }
} }
// Add a new timer queue to the service.
template <typename Time_Traits>
void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
{
asio::detail::mutex::scoped_lock lock(timer_mutex_);
timer_queues_.push_back(&timer_queue);
}
// Remove a timer queue from the service.
template <typename Time_Traits>
void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
{
asio::detail::mutex::scoped_lock lock(timer_mutex_);
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
{
if (timer_queues_[i] == &timer_queue)
{
timer_queues_.erase(timer_queues_.begin() + i);
return;
}
}
}
// Schedule a timer in the given timer queue to expire at the specified
// absolute time. The handler object will be invoked when the timer expires.
template <typename Time_Traits, typename Handler>
void schedule_timer(timer_queue<Time_Traits>& timer_queue,
const typename Time_Traits::time_type& time, Handler handler, void* token)
{
// If the service has been shut down we silently discard the timer.
if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
return;
asio::detail::mutex::scoped_lock lock(timer_mutex_);
if (timer_queue.enqueue_timer(time, handler, token))
{
if (!timer_interrupt_issued_)
{
timer_interrupt_issued_ = true;
lock.unlock();
::PostQueuedCompletionStatus(iocp_.handle,
0, steal_timer_dispatching, 0);
}
}
}
// Cancel the timer associated with the given token. Returns the number of
// handlers that have been posted or dispatched.
template <typename Time_Traits>
std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
{
// If the service has been shut down we silently ignore the cancellation.
if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
return 0;
asio::detail::mutex::scoped_lock lock(timer_mutex_);
std::size_t n = timer_queue.cancel_timer(token);
if (n > 0 && !timer_interrupt_issued_)
{
timer_interrupt_issued_ = true;
lock.unlock();
::PostQueuedCompletionStatus(iocp_.handle,
0, steal_timer_dispatching, 0);
}
return n;
}
private: private:
// Dequeues at most one operation from the I/O completion port, and then // Dequeues at most one operation from the I/O completion port, and then
// executes it. Returns the number of operations that were dequeued (i.e. // executes it. Returns the number of operations that were dequeued (i.e.
// either 0 or 1). // either 0 or 1).
size_t do_one(bool block, asio::error_code& ec) size_t do_one(bool block, asio::error_code& ec)
{ {
long this_thread_id = static_cast<long>(::GetCurrentThreadId());
for (;;) for (;;)
{ {
// Try to acquire responsibility for dispatching timers.
bool dispatching_timers = (::InterlockedCompareExchange(
&timer_thread_, this_thread_id, 0) == 0);
// Calculate timeout for GetQueuedCompletionStatus call.
DWORD timeout = max_timeout;
if (dispatching_timers)
{
asio::detail::mutex::scoped_lock lock(timer_mutex_);
timer_interrupt_issued_ = false;
timeout = get_timeout();
}
// Get the next operation from the queue. // Get the next operation from the queue.
DWORD bytes_transferred = 0; DWORD bytes_transferred = 0;
#if (WINVER < 0x0500) #if (WINVER < 0x0500)
@ -275,18 +365,47 @@ private:
LPOVERLAPPED overlapped = 0; LPOVERLAPPED overlapped = 0;
::SetLastError(0); ::SetLastError(0);
BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred, BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
&completion_key, &overlapped, block ? 1000 : 0); &completion_key, &overlapped, block ? timeout : 0);
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
// Dispatch any pending timers.
if (dispatching_timers)
{
asio::detail::mutex::scoped_lock lock(timer_mutex_);
timer_queues_copy_ = timer_queues_;
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
{
timer_queues_[i]->dispatch_timers();
timer_queues_[i]->dispatch_cancellations();
timer_queues_[i]->cleanup_timers();
}
}
if (!ok && overlapped == 0) if (!ok && overlapped == 0)
{ {
if (block && last_error == WAIT_TIMEOUT) if (block && last_error == WAIT_TIMEOUT)
{
// Relinquish responsibility for dispatching timers.
if (dispatching_timers)
{
::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id);
}
continue; continue;
}
// Transfer responsibility for dispatching timers to another thread.
if (dispatching_timers && ::InterlockedCompareExchange(
&timer_thread_, 0, this_thread_id) == this_thread_id)
{
::PostQueuedCompletionStatus(iocp_.handle,
0, transfer_timer_dispatching, 0);
}
ec = asio::error_code(); ec = asio::error_code();
return 0; return 0;
} }
else if (overlapped)
if (overlapped)
{ {
// We may have been passed a last_error value in the completion_key. // We may have been passed a last_error value in the completion_key.
if (last_error == 0) if (last_error == 0)
@ -294,6 +413,14 @@ private:
last_error = completion_key; last_error = completion_key;
} }
// Transfer responsibility for dispatching timers to another thread.
if (dispatching_timers && ::InterlockedCompareExchange(
&timer_thread_, 0, this_thread_id) == this_thread_id)
{
::PostQueuedCompletionStatus(iocp_.handle,
0, transfer_timer_dispatching, 0);
}
// Ensure that the io_service does not exit due to running out of work // Ensure that the io_service does not exit due to running out of work
// while we make the upcall. // while we make the upcall.
auto_work work(*this); auto_work work(*this);
@ -305,18 +432,34 @@ private:
ec = asio::error_code(); ec = asio::error_code();
return 1; return 1;
} }
else if (completion_key == transfer_timer_dispatching)
{
// Woken up to try to acquire responsibility for dispatching timers.
::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id);
}
else if (completion_key == steal_timer_dispatching)
{
// Woken up to steal responsibility for dispatching timers.
::InterlockedExchange(&timer_thread_, 0);
}
else else
{ {
// The stopped_ flag is always checked to ensure that any leftover // The stopped_ flag is always checked to ensure that any leftover
// interrupts from a previous run invocation are ignored. // interrupts from a previous run invocation are ignored.
if (::InterlockedExchangeAdd(&stopped_, 0) != 0) if (::InterlockedExchangeAdd(&stopped_, 0) != 0)
{ {
// Relinquish responsibility for dispatching timers.
if (dispatching_timers)
{
::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id);
}
// Wake up next thread that is blocked on GetQueuedCompletionStatus. // Wake up next thread that is blocked on GetQueuedCompletionStatus.
if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0)) if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
{ {
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
ec = asio::error_code(last_error, ec = asio::error_code(last_error,
asio::error::system_category); asio::error::get_system_category());
return 0; return 0;
} }
@ -327,6 +470,45 @@ private:
} }
} }
// Check if all timer queues are empty.
bool all_timer_queues_are_empty() const
{
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
if (!timer_queues_[i]->empty())
return false;
return true;
}
// Get the timeout value for the GetQueuedCompletionStatus call. The timeout
// value is returned as a number of milliseconds. We will wait no longer than
// 1000 milliseconds.
DWORD get_timeout()
{
if (all_timer_queues_are_empty())
return max_timeout;
boost::posix_time::time_duration minimum_wait_duration
= boost::posix_time::milliseconds(max_timeout);
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
{
boost::posix_time::time_duration wait_duration
= timer_queues_[i]->wait_duration();
if (wait_duration < minimum_wait_duration)
minimum_wait_duration = wait_duration;
}
if (minimum_wait_duration > boost::posix_time::time_duration())
{
int milliseconds = minimum_wait_duration.total_milliseconds();
return static_cast<DWORD>(milliseconds > 0 ? milliseconds : 1);
}
else
{
return 0;
}
}
struct auto_work struct auto_work
{ {
auto_work(win_iocp_io_service& io_service) auto_work(win_iocp_io_service& io_service)
@ -416,6 +598,37 @@ private:
// Flag to indicate whether the service has been shut down. // Flag to indicate whether the service has been shut down.
long shutdown_; long shutdown_;
enum
{
// Maximum GetQueuedCompletionStatus timeout, in milliseconds.
max_timeout = 1000,
// Completion key value to indicate that responsibility for dispatching
// timers is being cooperatively transferred from one thread to another.
transfer_timer_dispatching = 1,
// Completion key value to indicate that responsibility for dispatching
// timers should be stolen from another thread.
steal_timer_dispatching = 2
};
// The thread that's currently in charge of dispatching timers.
long timer_thread_;
// Mutex for protecting access to the timer queues.
mutex timer_mutex_;
// Whether a thread has been interrupted to process a new timeout.
bool timer_interrupt_issued_;
// The timer queues.
std::vector<timer_queue_base*> timer_queues_;
// A copy of the timer queues, used when dispatching, cancelling and cleaning
// up timers. The copy is stored as a class data member to avoid unnecessary
// memory allocation.
std::vector<timer_queue_base*> timer_queues_copy_;
}; };
} // namespace detail } // namespace detail

View File

@ -27,6 +27,7 @@
#if !defined(ASIO_DISABLE_IOCP) #if !defined(ASIO_DISABLE_IOCP)
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
#if !defined(UNDER_CE)
// Define this to indicate that IOCP is supported on the target platform. // Define this to indicate that IOCP is supported on the target platform.
#define ASIO_HAS_IOCP 1 #define ASIO_HAS_IOCP 1
@ -39,6 +40,7 @@ class win_iocp_io_service;
} // namespace detail } // namespace detail
} // namespace asio } // namespace asio
#endif // !defined(UNDER_CE)
#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) #endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
#endif // !defined(ASIO_DISABLE_IOCP) #endif // !defined(ASIO_DISABLE_IOCP)

View File

@ -338,7 +338,7 @@ public:
{ {
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
ec = asio::error_code(last_error, ec = asio::error_code(last_error,
asio::error::system_category); asio::error::get_system_category());
} }
else else
{ {
@ -360,7 +360,7 @@ public:
{ {
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
ec = asio::error_code(last_error, ec = asio::error_code(last_error,
asio::error::system_category); asio::error::get_system_category());
} }
else else
{ {
@ -667,7 +667,7 @@ public:
else if (last_error == ERROR_PORT_UNREACHABLE) else if (last_error == ERROR_PORT_UNREACHABLE)
last_error = WSAECONNREFUSED; last_error = WSAECONNREFUSED;
ec = asio::error_code(last_error, ec = asio::error_code(last_error,
asio::error::system_category); asio::error::get_system_category());
return 0; return 0;
} }
@ -719,7 +719,7 @@ public:
// Map non-portable errors to their portable counterparts. // Map non-portable errors to their portable counterparts.
asio::error_code ec(last_error, asio::error_code ec(last_error,
asio::error::system_category); asio::error::get_system_category());
if (ec.value() == ERROR_NETNAME_DELETED) if (ec.value() == ERROR_NETNAME_DELETED)
{ {
if (handler_op->cancel_token_.expired()) if (handler_op->cancel_token_.expired())
@ -822,7 +822,7 @@ public:
asio::io_service::work work(this->get_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::get_system_category());
iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
} }
else else
@ -867,7 +867,7 @@ public:
if (last_error == ERROR_PORT_UNREACHABLE) if (last_error == ERROR_PORT_UNREACHABLE)
last_error = WSAECONNREFUSED; last_error = WSAECONNREFUSED;
ec = asio::error_code(last_error, ec = asio::error_code(last_error,
asio::error::system_category); asio::error::get_system_category());
return 0; return 0;
} }
@ -917,7 +917,7 @@ public:
// Map non-portable errors to their portable counterparts. // Map non-portable errors to their portable counterparts.
asio::error_code ec(last_error, asio::error_code ec(last_error,
asio::error::system_category); asio::error::get_system_category());
if (ec.value() == ERROR_PORT_UNREACHABLE) if (ec.value() == ERROR_PORT_UNREACHABLE)
{ {
ec = asio::error::connection_refused; ec = asio::error::connection_refused;
@ -1001,7 +1001,7 @@ public:
asio::io_service::work work(this->get_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::get_system_category());
iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
} }
else else
@ -1056,7 +1056,7 @@ public:
else if (last_error == ERROR_PORT_UNREACHABLE) else if (last_error == ERROR_PORT_UNREACHABLE)
last_error = WSAECONNREFUSED; last_error = WSAECONNREFUSED;
ec = asio::error_code(last_error, ec = asio::error_code(last_error,
asio::error::system_category); asio::error::get_system_category());
return 0; return 0;
} }
if (bytes_transferred == 0) if (bytes_transferred == 0)
@ -1115,7 +1115,7 @@ public:
// Map non-portable errors to their portable counterparts. // Map non-portable errors to their portable counterparts.
asio::error_code ec(last_error, asio::error_code ec(last_error,
asio::error::system_category); asio::error::get_system_category());
if (ec.value() == ERROR_NETNAME_DELETED) if (ec.value() == ERROR_NETNAME_DELETED)
{ {
if (handler_op->cancel_token_.expired()) if (handler_op->cancel_token_.expired())
@ -1223,7 +1223,7 @@ public:
asio::io_service::work work(this->get_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::get_system_category());
iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
} }
else else
@ -1270,7 +1270,7 @@ public:
if (last_error == ERROR_PORT_UNREACHABLE) if (last_error == ERROR_PORT_UNREACHABLE)
last_error = WSAECONNREFUSED; last_error = WSAECONNREFUSED;
ec = asio::error_code(last_error, ec = asio::error_code(last_error,
asio::error::system_category); asio::error::get_system_category());
return 0; return 0;
} }
if (bytes_transferred == 0) if (bytes_transferred == 0)
@ -1337,7 +1337,7 @@ public:
// Map non-portable errors to their portable counterparts. // Map non-portable errors to their portable counterparts.
asio::error_code ec(last_error, asio::error_code ec(last_error,
asio::error::system_category); asio::error::get_system_category());
if (ec.value() == ERROR_PORT_UNREACHABLE) if (ec.value() == ERROR_PORT_UNREACHABLE)
{ {
ec = asio::error::connection_refused; ec = asio::error::connection_refused;
@ -1432,7 +1432,7 @@ public:
asio::io_service::work work(this->get_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::get_system_category());
iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
} }
else else
@ -1671,7 +1671,7 @@ public:
// Call the handler. // Call the handler.
asio::error_code ec(last_error, asio::error_code ec(last_error,
asio::error::system_category); asio::error::get_system_category());
asio_handler_invoke_helpers::invoke( asio_handler_invoke_helpers::invoke(
detail::bind_handler(handler, ec), &handler); detail::bind_handler(handler, ec), &handler);
} }
@ -1772,7 +1772,7 @@ public:
asio::io_service::work work(this->get_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::get_system_category());
iocp_service_.post(bind_handler(handler, ec)); iocp_service_.post(bind_handler(handler, ec));
} }
} }
@ -1849,7 +1849,7 @@ public:
if (connect_error) if (connect_error)
{ {
ec = asio::error_code(connect_error, ec = asio::error_code(connect_error,
asio::error::system_category); asio::error::get_system_category());
io_service_.post(bind_handler(handler_, ec)); io_service_.post(bind_handler(handler_, ec));
return true; return true;
} }

View File

@ -49,7 +49,8 @@ public:
if (error != 0) if (error != 0)
{ {
asio::system_error e( asio::system_error e(
asio::error_code(error, asio::error::system_category), asio::error_code(error,
asio::error::get_system_category()),
"mutex"); "mutex");
boost::throw_exception(e); boost::throw_exception(e);
} }
@ -68,7 +69,8 @@ public:
if (error != 0) if (error != 0)
{ {
asio::system_error e( asio::system_error e(
asio::error_code(error, asio::error::system_category), asio::error_code(error,
asio::error::get_system_category()),
"mutex"); "mutex");
boost::throw_exception(e); boost::throw_exception(e);
} }

View File

@ -21,7 +21,7 @@
#include <boost/config.hpp> #include <boost/config.hpp>
#include "asio/detail/pop_options.hpp" #include "asio/detail/pop_options.hpp"
#if defined(BOOST_WINDOWS) #if defined(BOOST_WINDOWS) && !defined(UNDER_CE)
#include "asio/error.hpp" #include "asio/error.hpp"
#include "asio/system_error.hpp" #include "asio/system_error.hpp"
@ -56,7 +56,7 @@ public:
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
asio::system_error e( asio::system_error e(
asio::error_code(last_error, asio::error_code(last_error,
asio::error::system_category), asio::error::get_system_category()),
"thread"); "thread");
boost::throw_exception(e); boost::throw_exception(e);
} }
@ -118,7 +118,7 @@ inline unsigned int __stdcall win_thread_function(void* arg)
} // namespace detail } // namespace detail
} // namespace asio } // namespace asio
#endif // defined(BOOST_WINDOWS) #endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
#include "asio/detail/pop_options.hpp" #include "asio/detail/pop_options.hpp"

View File

@ -40,16 +40,22 @@ class win_tss_ptr
: private noncopyable : private noncopyable
{ {
public: public:
#if defined(UNDER_CE)
enum { out_of_indexes = 0xFFFFFFFF };
#else
enum { out_of_indexes = TLS_OUT_OF_INDEXES };
#endif
// Constructor. // Constructor.
win_tss_ptr() win_tss_ptr()
{ {
tss_key_ = ::TlsAlloc(); tss_key_ = ::TlsAlloc();
if (tss_key_ == TLS_OUT_OF_INDEXES) if (tss_key_ == out_of_indexes)
{ {
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
asio::system_error e( asio::system_error e(
asio::error_code(last_error, asio::error_code(last_error,
asio::error::system_category), asio::error::get_system_category()),
"tss"); "tss");
boost::throw_exception(e); boost::throw_exception(e);
} }

View File

@ -0,0 +1,124 @@
//
// wince_thread.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2007 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_DETAIL_WINCE_THREAD_HPP
#define ASIO_DETAIL_WINCE_THREAD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
#include "asio/error.hpp"
#include "asio/system_error.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/throw_exception.hpp>
#include <memory>
#include "asio/detail/pop_options.hpp"
namespace asio {
namespace detail {
DWORD WINAPI wince_thread_function(LPVOID arg);
class wince_thread
: private noncopyable
{
public:
// Constructor.
template <typename Function>
wince_thread(Function f)
{
std::auto_ptr<func_base> arg(new func<Function>(f));
DWORD thread_id = 0;
thread_ = ::CreateThread(0, 0, wince_thread_function,
arg.get(), 0, &thread_id);
if (!thread_)
{
DWORD last_error = ::GetLastError();
asio::system_error e(
asio::error_code(last_error,
asio::error::get_system_category()),
"thread");
boost::throw_exception(e);
}
arg.release();
}
// Destructor.
~wince_thread()
{
::CloseHandle(thread_);
}
// Wait for the thread to exit.
void join()
{
::WaitForSingleObject(thread_, INFINITE);
}
private:
friend DWORD WINAPI wince_thread_function(LPVOID arg);
class func_base
{
public:
virtual ~func_base() {}
virtual void run() = 0;
};
template <typename Function>
class func
: public func_base
{
public:
func(Function f)
: f_(f)
{
}
virtual void run()
{
f_();
}
private:
Function f_;
};
::HANDLE thread_;
};
inline DWORD WINAPI wince_thread_function(LPVOID arg)
{
std::auto_ptr<wince_thread::func_base> func(
static_cast<wince_thread::func_base*>(arg));
func->run();
return 0;
}
} // namespace detail
} // namespace asio
#endif // defined(BOOST_WINDOWS) && defined(UNDER_CE)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_WINCE_THREAD_HPP

View File

@ -87,7 +87,7 @@ public:
{ {
asio::system_error e( asio::system_error e(
asio::error_code(ref_->result(), asio::error_code(ref_->result(),
asio::error::system_category), asio::error::get_system_category()),
"winsock"); "winsock");
boost::throw_exception(e); boost::throw_exception(e);
} }

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),
/// Port already in use. /// Address 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 port. /// Bad address.
fault = ASIO_SOCKET_ERROR(EFAULT), fault = ASIO_SOCKET_ERROR(EFAULT),
/// No route to host. /// No route to host.
@ -205,27 +205,32 @@ enum ssl_errors
inline asio::error_code make_error_code(basic_errors e) inline asio::error_code make_error_code(basic_errors e)
{ {
return asio::error_code(static_cast<int>(e), system_category); return asio::error_code(
static_cast<int>(e), get_system_category());
} }
inline asio::error_code make_error_code(netdb_errors e) inline asio::error_code make_error_code(netdb_errors e)
{ {
return asio::error_code(static_cast<int>(e), netdb_category); return asio::error_code(
static_cast<int>(e), get_netdb_category());
} }
inline asio::error_code make_error_code(addrinfo_errors e) inline asio::error_code make_error_code(addrinfo_errors e)
{ {
return asio::error_code(static_cast<int>(e), addrinfo_category); return asio::error_code(
static_cast<int>(e), get_addrinfo_category());
} }
inline asio::error_code make_error_code(misc_errors e) 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), get_misc_category());
} }
inline asio::error_code make_error_code(ssl_errors e) inline asio::error_code make_error_code(ssl_errors e)
{ {
return asio::error_code(static_cast<int>(e), ssl_category); return asio::error_code(
static_cast<int>(e), get_ssl_category());
} }
} // namespace error } // namespace error

View File

@ -41,10 +41,10 @@ namespace error
system_category = ASIO_WIN_OR_POSIX(0, 0), system_category = ASIO_WIN_OR_POSIX(0, 0),
/// Error codes from NetDB functions. /// Error codes from NetDB functions.
netdb_category = ASIO_WIN_OR_POSIX(system_category, 1), netdb_category = ASIO_WIN_OR_POSIX(_system_category, 1),
/// Error codes from getaddrinfo. /// Error codes from getaddrinfo.
addrinfo_category = ASIO_WIN_OR_POSIX(system_category, 2), addrinfo_category = ASIO_WIN_OR_POSIX(_system_category, 2),
/// Miscellaneous error codes. /// Miscellaneous error codes.
misc_category = ASIO_WIN_OR_POSIX(3, 3), misc_category = ASIO_WIN_OR_POSIX(3, 3),
@ -52,6 +52,14 @@ namespace error
/// SSL error codes. /// SSL error codes.
ssl_category = ASIO_WIN_OR_POSIX(4, 4) ssl_category = ASIO_WIN_OR_POSIX(4, 4)
}; };
// Category getters.
inline error_category get_system_category() { return system_category; }
inline error_category get_netdb_category() { return netdb_category; }
inline error_category get_addrinfo_category() { return addrinfo_category; }
inline error_category get_misc_category() { return misc_category; }
inline error_category get_ssl_category() { return ssl_category; }
} // namespace error } // namespace error
/// Bring error category type into the asio namespace. /// Bring error category type into the asio namespace.

View File

@ -35,11 +35,11 @@ inline std::string error_code::message() const
return "Already open."; return "Already open.";
if (*this == error::not_found) if (*this == error::not_found)
return "Not found."; return "Not found.";
if (category_ == error::ssl_category) if (category_ == error::get_ssl_category())
return "SSL error."; return "SSL error.";
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
value_type value = value_; value_type value = value_;
if (category() != error::system_category && *this != error::eof) if (category() != error::get_system_category() && *this != error::eof)
return "asio error"; return "asio error";
if (*this == error::eof) if (*this == error::eof)
value = ERROR_HANDLE_EOF; value = ERROR_HANDLE_EOF;
@ -78,7 +78,7 @@ inline std::string error_code::message() const
return "Service not found."; return "Service not found.";
if (*this == error::socket_type_not_supported) if (*this == error::socket_type_not_supported)
return "Socket type not supported."; return "Socket type not supported.";
if (category() != error::system_category) if (category() != error::get_system_category())
return "asio error"; return "asio error";
#if defined(__sun) || defined(__QNX__) #if defined(__sun) || defined(__QNX__)
return strerror(value_); return strerror(value_);

View File

@ -19,7 +19,6 @@
#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"
@ -139,25 +138,23 @@ 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_;
boost::optional<buffers_type> buffers_; buffers_type buffers_;
std::size_t total_transferred_; std::size_t total_transferred_;
boost::optional<CompletionCondition> completion_condition_; CompletionCondition completion_condition_;
ReadHandler handler_; ReadHandler handler_;
}; };
@ -238,9 +235,8 @@ 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
@ -255,7 +251,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_;
boost::optional<CompletionCondition> completion_condition_; CompletionCondition completion_condition_;
ReadHandler handler_; ReadHandler handler_;
}; };

View File

@ -17,10 +17,6 @@
#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"
@ -128,25 +124,23 @@ 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_;
boost::optional<buffers_type> buffers_; buffers_type buffers_;
std::size_t total_transferred_; std::size_t total_transferred_;
boost::optional<CompletionCondition> completion_condition_; CompletionCondition completion_condition_;
WriteHandler handler_; WriteHandler handler_;
}; };

View File

@ -252,6 +252,13 @@ template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
class multicast_hops class multicast_hops
{ {
public: public:
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
typedef int ipv4_value_type;
#else
typedef unsigned char ipv4_value_type;
#endif
typedef int ipv6_value_type;
// Default constructor. // Default constructor.
multicast_hops() multicast_hops()
: ipv4_value_(0), : ipv4_value_(0),
@ -264,7 +271,7 @@ public:
{ {
if (v < 0 || v > 255) if (v < 0 || v > 255)
throw std::out_of_range("multicast hops value out of range"); throw std::out_of_range("multicast hops value out of range");
ipv4_value_ = static_cast<unsigned char>(v); ipv4_value_ = (ipv4_value_type)v;
ipv6_value_ = v; ipv6_value_ = v;
} }
@ -273,7 +280,7 @@ public:
{ {
if (v < 0 || v > 255) if (v < 0 || v > 255)
throw std::out_of_range("multicast hops value out of range"); throw std::out_of_range("multicast hops value out of range");
ipv4_value_ = static_cast<unsigned char>(v); ipv4_value_ = (ipv4_value_type)v;
ipv6_value_ = v; ipv6_value_ = v;
return *this; return *this;
} }
@ -342,7 +349,7 @@ public:
else if (ipv6_value_ > 255) else if (ipv6_value_ > 255)
ipv4_value_ = 255; ipv4_value_ = 255;
else else
ipv4_value_ = static_cast<unsigned char>(ipv6_value_); ipv4_value_ = (ipv4_value_type)ipv6_value_;
} }
else else
{ {
@ -353,8 +360,8 @@ public:
} }
private: private:
unsigned char ipv4_value_; ipv4_value_type ipv4_value_;
int ipv6_value_; ipv6_value_type ipv6_value_;
}; };
// Helper template for implementing ip_mreq-based options. // Helper template for implementing ip_mreq-based options.

View File

@ -179,7 +179,7 @@ public:
else else
{ {
return handler_(asio::error_code( return handler_(asio::error_code(
error_code, asio::error::ssl_category), rc); error_code, asio::error::get_ssl_category()), rc);
} }
} }

View File

@ -183,7 +183,7 @@ void lsd::on_announce(udp::endpoint const& from, char* buffer
void lsd::close() void lsd::close()
{ {
m_socket.close();
m_broadcast_timer.cancel(); m_broadcast_timer.cancel();
m_socket.close();
} }

View File

@ -2317,6 +2317,8 @@ namespace detail
void session_impl::stop_lsd() void session_impl::stop_lsd()
{ {
mutex_t::scoped_lock l(m_mutex); mutex_t::scoped_lock l(m_mutex);
if (m_lsd.get())
m_lsd->close();
m_lsd = 0; m_lsd = 0;
} }