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"
#if defined(BOOST_MSVC)
# if defined(_HAS_ITERATOR_DEBUGGING)
# if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0)
# if !defined(ASIO_DISABLE_BUFFER_DEBUGGING)
# define ASIO_ENABLE_BUFFER_DEBUGGING
# endif // !defined(ASIO_DISABLE_BUFFER_DEBUGGING)
@ -390,6 +390,11 @@ public:
{
}
~buffer_debug_check()
{
iter_ = Iterator();
}
void operator()()
{
*iter_;

View File

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

View File

@ -140,22 +140,13 @@ public:
if (read_op_queue_.enqueue_operation(descriptor, handler))
{
::pollfd ev = { 0 };
ev.fd = descriptor;
::pollfd& ev = add_pending_event_change(descriptor);
ev.events = POLLIN | POLLERR | POLLHUP;
if (write_op_queue_.has_operation(descriptor))
ev.events |= POLLOUT;
if (except_op_queue_.has_operation(descriptor))
ev.events |= POLLPRI;
ev.revents = 0;
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);
}
interrupter_.interrupt();
}
}
@ -175,22 +166,13 @@ public:
if (write_op_queue_.enqueue_operation(descriptor, handler))
{
::pollfd ev = { 0 };
ev.fd = descriptor;
::pollfd& ev = add_pending_event_change(descriptor);
ev.events = POLLOUT | POLLERR | POLLHUP;
if (read_op_queue_.has_operation(descriptor))
ev.events |= POLLIN;
if (except_op_queue_.has_operation(descriptor))
ev.events |= POLLPRI;
ev.revents = 0;
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);
}
interrupter_.interrupt();
}
}
@ -206,22 +188,13 @@ public:
if (except_op_queue_.enqueue_operation(descriptor, handler))
{
::pollfd ev = { 0 };
ev.fd = descriptor;
::pollfd& ev = add_pending_event_change(descriptor);
ev.events = POLLPRI | POLLERR | POLLHUP;
if (read_op_queue_.has_operation(descriptor))
ev.events |= POLLIN;
if (write_op_queue_.has_operation(descriptor))
ev.events |= POLLOUT;
ev.revents = 0;
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);
}
interrupter_.interrupt();
}
}
@ -241,21 +214,11 @@ public:
&& need_mod;
if (need_mod)
{
::pollfd ev = { 0 };
ev.fd = descriptor;
::pollfd& ev = add_pending_event_change(descriptor);
ev.events = POLLOUT | POLLPRI | POLLERR | POLLHUP;
if (read_op_queue_.has_operation(descriptor))
ev.events |= POLLIN;
ev.revents = 0;
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);
}
interrupter_.interrupt();
}
}
@ -285,11 +248,9 @@ public:
asio::detail::mutex::scoped_lock lock(mutex_);
// Remove the descriptor from /dev/poll.
::pollfd ev = { 0 };
ev.fd = descriptor;
::pollfd& ev = add_pending_event_change(descriptor);
ev.events = POLLREMOVE;
ev.revents = 0;
::write(dev_poll_fd_, &ev, sizeof(ev));
interrupter_.interrupt();
// Cancel any outstanding operations associated with the descriptor.
cancel_ops_unlocked(descriptor);
@ -374,6 +335,26 @@ private:
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;
wait_in_progress_ = true;
lock.unlock();
@ -454,7 +435,7 @@ private:
if (result != sizeof(ev))
{
ec = asio::error_code(errno,
asio::error::system_category);
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);
@ -513,7 +494,7 @@ private:
boost::throw_exception(
asio::system_error(
asio::error_code(errno,
asio::error::system_category),
asio::error::get_system_category()),
"/dev/poll"));
}
return fd;
@ -588,12 +569,39 @@ private:
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.
asio::detail::mutex mutex_;
// The /dev/poll file descriptor.
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
bool wait_in_progress_;

View File

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

View File

@ -151,7 +151,7 @@ public:
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{
asio::error_code ec(errno,
asio::error::system_category);
asio::error::get_system_category());
read_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
@ -178,7 +178,7 @@ public:
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{
asio::error_code ec(errno,
asio::error::system_category);
asio::error::get_system_category());
write_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
@ -204,7 +204,7 @@ public:
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{
asio::error_code ec(errno,
asio::error::system_category);
asio::error::get_system_category());
except_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
@ -228,7 +228,7 @@ public:
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{
asio::error_code ec(errno,
asio::error::system_category);
asio::error::get_system_category());
write_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
@ -243,7 +243,7 @@ public:
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{
asio::error_code ec(errno,
asio::error::system_category);
asio::error::get_system_category());
except_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)
{
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);
read_op_queue_.dispatch_all_operations(descriptor, error);
}
@ -428,7 +428,7 @@ private:
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{
asio::error_code error(errno,
asio::error::system_category);
asio::error::get_system_category());
except_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)
{
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);
}
else
@ -458,7 +458,7 @@ private:
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{
asio::error_code error(errno,
asio::error::system_category);
asio::error::get_system_category());
write_op_queue_.dispatch_all_operations(descriptor, error);
}
}
@ -515,7 +515,7 @@ private:
boost::throw_exception(
asio::system_error(
asio::error_code(errno,
asio::error::system_category),
asio::error::get_system_category()),
"kqueue"));
}
return fd;

View File

@ -51,7 +51,8 @@ public:
}
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");
boost::throw_exception(e);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -157,7 +157,8 @@ public:
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;
}
@ -181,7 +182,8 @@ public:
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;
}
@ -1489,7 +1491,7 @@ public:
if (connect_error)
{
ec = asio::error_code(connect_error,
asio::error::system_category);
asio::error::get_system_category());
io_service_.post(bind_handler(handler_, ec));
return true;
}

View File

@ -48,10 +48,11 @@ extern "C" unsigned int if_nametoindex(const char*);
inline void clear_error(asio::error_code& ec)
{
errno = 0;
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
WSASetLastError(0);
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
#else
errno = 0;
#endif
ec = asio::error_code();
}
@ -61,9 +62,10 @@ inline ReturnType error_wrapper(ReturnType return_value,
{
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
ec = asio::error_code(WSAGetLastError(),
asio::error::system_category);
asio::error::get_system_category());
#else
ec = asio::error_code(errno, asio::error::system_category);
ec = asio::error_code(errno,
asio::error::get_system_category());
#endif
return return_value;
}
@ -100,6 +102,10 @@ inline socket_type accept(socket_type s, socket_addr_type* addr,
}
#endif
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
clear_error(ec);
#endif
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)
{
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)
{
clear_error(ec);
#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__)
return error_wrapper(::close(s), ec);
#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)
{
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>
@ -144,14 +166,24 @@ inline int connect(socket_type s, const socket_addr_type* addr,
std::size_t addrlen, asio::error_code& ec)
{
clear_error(ec);
return error_wrapper(call_connect(
int result = error_wrapper(call_connect(
&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)
{
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__)
@ -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);
if (result != 0)
return -1;
# if defined(UNDER_CE)
clear_error(ec);
# endif
return bytes_transferred;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
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;
if (result != 0)
return -1;
# if defined(UNDER_CE)
clear_error(ec);
# endif
return bytes_transferred;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
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);
if (result != 0)
return -1;
# if defined(UNDER_CE)
clear_error(ec);
# endif
return bytes_transferred;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
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 bytes_transferred = 0;
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)
return -1;
# if defined(UNDER_CE)
clear_error(ec);
# endif
return bytes_transferred;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
msghdr msg = msghdr();
@ -327,6 +372,10 @@ inline socket_type socket(int af, int type, int protocol,
reinterpret_cast<const char*>(&optval), sizeof(optval));
}
# if defined(UNDER_CE)
clear_error(ec);
# endif
return s;
#elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
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;
#else // defined(__BORLANDC__)
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);
# if defined(BOOST_WINDOWS) && defined(UNDER_CE)
if (result == 0)
clear_error(ec);
# endif
return result;
#endif // defined(__BORLANDC__)
}
@ -455,6 +509,10 @@ inline int getsockopt(socket_type s, int level, int optname, void* optval,
*static_cast<DWORD*>(optval) = 1;
clear_error(ec);
}
# if defined(UNDER_CE)
if (result == 0)
clear_error(ec);
# endif
return result;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
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)
{
clear_error(ec);
return error_wrapper(call_getpeername(
int result = error_wrapper(call_getpeername(
&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>
@ -508,8 +571,13 @@ inline int getsockname(socket_type s, socket_addr_type* addr,
std::size_t* addrlen, asio::error_code& ec)
{
clear_error(ec);
return error_wrapper(call_getsockname(
int result = error_wrapper(call_getsockname(
&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,
@ -517,7 +585,12 @@ inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg,
{
clear_error(ec);
#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__)
return error_wrapper(::ioctl(s, cmd, arg), ec);
#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,
writefds, exceptfds, timeout ? &ts : 0, 0), ec);
#else
return error_wrapper(::select(nfds, readfds,
int result = error_wrapper(::select(nfds, readfds,
writefds, exceptfds, timeout), ec);
# if defined(BOOST_WINDOWS) && defined(UNDER_CE)
if (result >= 0)
clear_error(ec);
# endif
return result;
#endif
}
@ -568,7 +646,12 @@ inline int poll_read(socket_type s, asio::error_code& ec)
FD_ZERO(&fds);
FD_SET(s, &fds);
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__)
pollfd fds;
fds.fd = s;
@ -586,7 +669,12 @@ inline int poll_write(socket_type s, asio::error_code& ec)
FD_ZERO(&fds);
FD_SET(s, &fds);
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__)
pollfd fds;
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);
#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(
reinterpret_cast<sockaddr*>(&address),
address_length, 0, dest, &string_length), ec);
#endif
// Windows may set error code on success.
if (result != socket_error_retval)
@ -680,10 +776,20 @@ inline int inet_pton(int af, const char* src, void* dest,
sockaddr_storage_type address;
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(
const_cast<char*>(src), af, 0,
reinterpret_cast<sockaddr*>(&address),
&address_length), ec);
#endif
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)
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;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
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)
{
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__) \
@ -782,6 +898,9 @@ inline hostent* gethostbyaddr(const char* addr, int length, int af,
hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec);
if (!retval)
return 0;
# if defined(UNDER_CE)
clear_error(ec);
# endif
*result = *retval;
return retval;
#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);
if (!retval)
return 0;
# if defined(UNDER_CE)
clear_error(ec);
# endif
*result = *retval;
return result;
#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.
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
return asio::error_code(
WSAGetLastError(), asio::error::system_category);
WSAGetLastError(), asio::error::get_system_category());
#else
return asio::error_code(
errno, asio::error::system_category);
errno, asio::error::get_system_category());
#endif
}
}
@ -1615,7 +1737,7 @@ inline asio::error_code getaddrinfo(const char* host,
{
clear_error(ec);
#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.
int error = ::getaddrinfo(host, service, hints, result);
return ec = translate_addrinfo_error(error);
@ -1646,7 +1768,7 @@ inline asio::error_code getaddrinfo(const char* host,
inline void freeaddrinfo(addrinfo_type* ai)
{
#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.
::freeaddrinfo(ai);
# 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)
{
#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.
clear_error(ec);
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 asio
#undef ASIO_SOCKET_CALL
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_SOCKET_OPS_HPP

View File

@ -80,7 +80,9 @@
# undef ASIO_WSPIAPI_H_DEFINED
# endif // defined(ASIO_WSPIAPI_H_DEFINED)
# 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, "mswsock.lib")
# endif // defined(_MSC_VER) || defined(__BORLANDC__)

View File

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

View File

@ -162,13 +162,7 @@ public:
// Destroy timers that are waiting to be cleaned up.
virtual void cleanup_timers()
{
while (cleanup_timers_)
{
timer_base* next_timer = cleanup_timers_->next_;
cleanup_timers_->next_ = 0;
cleanup_timers_->destroy();
cleanup_timers_ = next_timer;
}
destroy_timer_list(cleanup_timers_);
}
// Destroy all timers.
@ -181,11 +175,12 @@ public:
timer_base* t = i->second;
typename hash_map<void*, timer_base*>::iterator old_i = i++;
timers_.erase(old_i);
t->destroy();
destroy_timer_list(t);
}
heap_.clear();
timers_.clear();
cleanup_timers();
destroy_timer_list(cancelled_timers_);
destroy_timer_list(cleanup_timers_);
}
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.
hash_map<void*, timer_base*> timers_;

View File

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

View File

@ -33,7 +33,9 @@
#include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/service_base.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/timer_queue.hpp"
#include "asio/detail/win_iocp_operation.hpp"
#include "asio/detail/mutex.hpp"
namespace asio {
namespace detail {
@ -51,7 +53,9 @@ public:
iocp_(),
outstanding_work_(0),
stopped_(0),
shutdown_(0)
shutdown_(0),
timer_thread_(0),
timer_interrupt_issued_(false)
{
}
@ -64,7 +68,7 @@ public:
DWORD last_error = ::GetLastError();
asio::system_error e(
asio::error_code(last_error,
asio::error::system_category),
asio::error::get_system_category()),
"iocp");
boost::throw_exception(e);
}
@ -93,6 +97,10 @@ public:
if (overlapped)
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.
@ -175,7 +183,7 @@ public:
DWORD last_error = ::GetLastError();
asio::system_error e(
asio::error_code(last_error,
asio::error::system_category),
asio::error::get_system_category()),
"pqcs");
boost::throw_exception(e);
}
@ -231,7 +239,7 @@ public:
DWORD last_error = ::GetLastError();
asio::system_error e(
asio::error_code(last_error,
asio::error::system_category),
asio::error::get_system_category()),
"pqcs");
boost::throw_exception(e);
}
@ -251,20 +259,102 @@ public:
DWORD last_error = ::GetLastError();
asio::system_error e(
asio::error_code(last_error,
asio::error::system_category),
asio::error::get_system_category()),
"pqcs");
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:
// 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.
// either 0 or 1).
size_t do_one(bool block, asio::error_code& ec)
{
long this_thread_id = static_cast<long>(::GetCurrentThreadId());
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.
DWORD bytes_transferred = 0;
#if (WINVER < 0x0500)
@ -275,18 +365,47 @@ private:
LPOVERLAPPED overlapped = 0;
::SetLastError(0);
BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
&completion_key, &overlapped, block ? 1000 : 0);
&completion_key, &overlapped, block ? timeout : 0);
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 (block && last_error == WAIT_TIMEOUT)
{
// Relinquish responsibility for dispatching timers.
if (dispatching_timers)
{
::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id);
}
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();
return 0;
}
if (overlapped)
else if (overlapped)
{
// We may have been passed a last_error value in the completion_key.
if (last_error == 0)
@ -294,6 +413,14 @@ private:
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
// while we make the upcall.
auto_work work(*this);
@ -305,18 +432,34 @@ private:
ec = asio::error_code();
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
{
// The stopped_ flag is always checked to ensure that any leftover
// interrupts from a previous run invocation are ignored.
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.
if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
{
DWORD last_error = ::GetLastError();
ec = asio::error_code(last_error,
asio::error::system_category);
asio::error::get_system_category());
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
{
auto_work(win_iocp_io_service& io_service)
@ -416,6 +598,37 @@ private:
// Flag to indicate whether the service has been shut down.
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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -61,7 +61,7 @@ enum basic_errors
/// Address family not supported by protocol.
address_family_not_supported = ASIO_SOCKET_ERROR(EAFNOSUPPORT),
/// Port already in use.
/// Address already in use.
address_in_use = ASIO_SOCKET_ERROR(EADDRINUSE),
/// Transport endpoint is already connected.
@ -82,7 +82,7 @@ enum basic_errors
/// Bad file descriptor.
bad_descriptor = ASIO_SOCKET_ERROR(EBADF),
/// Bad port.
/// Bad address.
fault = ASIO_SOCKET_ERROR(EFAULT),
/// No route to host.
@ -205,27 +205,32 @@ enum ssl_errors
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)
{
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)
{
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)
{
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)
{
return asio::error_code(static_cast<int>(e), ssl_category);
return asio::error_code(
static_cast<int>(e), get_ssl_category());
}
} // namespace error

View File

@ -41,10 +41,10 @@ namespace error
system_category = ASIO_WIN_OR_POSIX(0, 0),
/// 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.
addrinfo_category = ASIO_WIN_OR_POSIX(system_category, 2),
addrinfo_category = ASIO_WIN_OR_POSIX(_system_category, 2),
/// Miscellaneous error codes.
misc_category = ASIO_WIN_OR_POSIX(3, 3),
@ -52,6 +52,14 @@ namespace error
/// SSL error codes.
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
/// Bring error category type into the asio namespace.

View File

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

View File

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

View File

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

View File

@ -252,6 +252,13 @@ template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
class multicast_hops
{
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.
multicast_hops()
: ipv4_value_(0),
@ -264,7 +271,7 @@ public:
{
if (v < 0 || v > 255)
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;
}
@ -273,7 +280,7 @@ public:
{
if (v < 0 || v > 255)
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;
return *this;
}
@ -342,7 +349,7 @@ public:
else if (ipv6_value_ > 255)
ipv4_value_ = 255;
else
ipv4_value_ = static_cast<unsigned char>(ipv6_value_);
ipv4_value_ = (ipv4_value_type)ipv6_value_;
}
else
{
@ -353,8 +360,8 @@ public:
}
private:
unsigned char ipv4_value_;
int ipv6_value_;
ipv4_value_type ipv4_value_;
ipv6_value_type ipv6_value_;
};
// Helper template for implementing ip_mreq-based options.

View File

@ -179,7 +179,7 @@ public:
else
{
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()
{
m_socket.close();
m_broadcast_timer.cancel();
m_socket.close();
}

View File

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