|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r74820 - in trunk/boost/asio/detail: . impl
From: chris_at_[hidden]
Date: 2011-10-08 17:25:21
Author: chris_kohlhoff
Date: 2011-10-08 17:25:20 EDT (Sat, 08 Oct 2011)
New Revision: 74820
URL: http://svn.boost.org/trac/boost/changeset/74820
Log:
Set size of select fd_set at runtime when using Windows.
Text files modified:
trunk/boost/asio/detail/impl/select_reactor.ipp | 36 ++++++++++++----------
trunk/boost/asio/detail/posix_fd_set_adapter.hpp | 9 +++++
trunk/boost/asio/detail/select_reactor.hpp | 4 ++
trunk/boost/asio/detail/win_fd_set_adapter.hpp | 63 ++++++++++++++++++++++++++++++---------
4 files changed, 80 insertions(+), 32 deletions(-)
Modified: trunk/boost/asio/detail/impl/select_reactor.ipp
==============================================================================
--- trunk/boost/asio/detail/impl/select_reactor.ipp (original)
+++ trunk/boost/asio/detail/impl/select_reactor.ipp 2011-10-08 17:25:20 EDT (Sat, 08 Oct 2011)
@@ -172,27 +172,28 @@
#endif // defined(BOOST_ASIO_HAS_IOCP)
// Set up the descriptor sets.
- fd_set_adapter fds[max_select_ops];
- fds[read_op].set(interrupter_.read_descriptor());
+ for (int i = 0; i < max_select_ops; ++i)
+ fd_sets_[i].reset();
+ fd_sets_[read_op].set(interrupter_.read_descriptor());
socket_type max_fd = 0;
bool have_work_to_do = !timer_queues_.all_empty();
for (int i = 0; i < max_select_ops; ++i)
{
have_work_to_do = have_work_to_do || !op_queue_[i].empty();
- op_queue_[i].get_descriptors(fds[i], ops);
- if (fds[i].max_descriptor() > max_fd)
- max_fd = fds[i].max_descriptor();
+ op_queue_[i].get_descriptors(fd_sets_[i], ops);
+ if (fd_sets_[i].max_descriptor() > max_fd)
+ max_fd = fd_sets_[i].max_descriptor();
}
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
// Connection operations on Windows use both except and write fd_sets.
have_work_to_do = have_work_to_do || !op_queue_[connect_op].empty();
- op_queue_[connect_op].get_descriptors(fds[write_op], ops);
- if (fds[write_op].max_descriptor() > max_fd)
- max_fd = fds[write_op].max_descriptor();
- op_queue_[connect_op].get_descriptors(fds[except_op], ops);
- if (fds[except_op].max_descriptor() > max_fd)
- max_fd = fds[except_op].max_descriptor();
+ op_queue_[connect_op].get_descriptors(fd_sets_[write_op], ops);
+ if (fd_sets_[write_op].max_descriptor() > max_fd)
+ max_fd = fd_sets_[write_op].max_descriptor();
+ op_queue_[connect_op].get_descriptors(fd_sets_[except_op], ops);
+ if (fd_sets_[except_op].max_descriptor() > max_fd)
+ max_fd = fd_sets_[except_op].max_descriptor();
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
// We can return immediately if there's no work to do and the reactor is
@@ -209,11 +210,14 @@
// Block on the select call until descriptors become ready.
boost::system::error_code ec;
int retval = socket_ops::select(static_cast<int>(max_fd + 1),
- fds[read_op], fds[write_op], fds[except_op], tv, ec);
+ fd_sets_[read_op], fd_sets_[write_op], fd_sets_[except_op], tv, ec);
// Reset the interrupter.
- if (retval > 0 && fds[read_op].is_set(interrupter_.read_descriptor()))
+ if (retval > 0 && fd_sets_[read_op].is_set(interrupter_.read_descriptor()))
+ {
interrupter_.reset();
+ --retval;
+ }
lock.lock();
@@ -223,15 +227,15 @@
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
// Connection operations on Windows use both except and write fd_sets.
op_queue_[connect_op].perform_operations_for_descriptors(
- fds[except_op], ops);
+ fd_sets_[except_op], ops);
op_queue_[connect_op].perform_operations_for_descriptors(
- fds[write_op], ops);
+ fd_sets_[write_op], ops);
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
// Exception operations must be processed first to ensure that any
// out-of-band data is read before normal data.
for (int i = max_select_ops - 1; i >= 0; --i)
- op_queue_[i].perform_operations_for_descriptors(fds[i], ops);
+ op_queue_[i].perform_operations_for_descriptors(fd_sets_[i], ops);
}
timer_queues_.get_ready_timers(ops);
}
Modified: trunk/boost/asio/detail/posix_fd_set_adapter.hpp
==============================================================================
--- trunk/boost/asio/detail/posix_fd_set_adapter.hpp (original)
+++ trunk/boost/asio/detail/posix_fd_set_adapter.hpp 2011-10-08 17:25:20 EDT (Sat, 08 Oct 2011)
@@ -20,6 +20,7 @@
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
#include <cstring>
+#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/socket_types.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -29,7 +30,7 @@
namespace detail {
// Adapts the FD_SET type to meet the Descriptor_Set concept's requirements.
-class posix_fd_set_adapter
+class posix_fd_set_adapter : noncopyable
{
public:
posix_fd_set_adapter()
@@ -39,6 +40,12 @@
FD_ZERO(&fd_set_);
}
+ void reset()
+ {
+ using namespace std; // Needed for memset on Solaris.
+ FD_ZERO(&fd_set_);
+ }
+
bool set(socket_type descriptor)
{
if (descriptor < (socket_type)FD_SETSIZE)
Modified: trunk/boost/asio/detail/select_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/select_reactor.hpp (original)
+++ trunk/boost/asio/detail/select_reactor.hpp 2011-10-08 17:25:20 EDT (Sat, 08 Oct 2011)
@@ -24,6 +24,7 @@
#include <boost/limits.hpp>
#include <cstddef>
+#include <boost/asio/detail/fd_set_adapter.hpp>
#include <boost/asio/detail/mutex.hpp>
#include <boost/asio/detail/op_queue.hpp>
#include <boost/asio/detail/reactor_op.hpp>
@@ -183,6 +184,9 @@
// The queues of read, write and except operations.
reactor_op_queue<socket_type> op_queue_[max_ops];
+ // The file descriptor sets to be passed to the select system call.
+ fd_set_adapter fd_sets_[max_select_ops];
+
// The timer queues.
timer_queue_set timer_queues_;
Modified: trunk/boost/asio/detail/win_fd_set_adapter.hpp
==============================================================================
--- trunk/boost/asio/detail/win_fd_set_adapter.hpp (original)
+++ trunk/boost/asio/detail/win_fd_set_adapter.hpp 2011-10-08 17:25:20 EDT (Sat, 08 Oct 2011)
@@ -19,6 +19,7 @@
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/socket_types.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -28,39 +29,67 @@
namespace detail {
// Adapts the FD_SET type to meet the Descriptor_Set concept's requirements.
-class win_fd_set_adapter
+class win_fd_set_adapter : noncopyable
{
public:
- enum { win_fd_set_size = 1024 };
+ enum { default_fd_set_size = 1024 };
win_fd_set_adapter()
- : max_descriptor_(invalid_socket)
+ : capacity_(default_fd_set_size),
+ max_descriptor_(invalid_socket)
{
- fd_set_.fd_count = 0;
+ fd_set_ = static_cast<win_fd_set*>(::operator new(
+ sizeof(win_fd_set) - sizeof(SOCKET)
+ + sizeof(SOCKET) * (capacity_)));
+ fd_set_->fd_count = 0;
+ }
+
+ ~win_fd_set_adapter()
+ {
+ ::operator delete(fd_set_);
+ }
+
+ void reset()
+ {
+ fd_set_->fd_count = 0;
+ max_descriptor_ = invalid_socket;
}
bool set(socket_type descriptor)
{
- for (u_int i = 0; i < fd_set_.fd_count; ++i)
- if (fd_set_.fd_array[i] == descriptor)
+ for (u_int i = 0; i < fd_set_->fd_count; ++i)
+ if (fd_set_->fd_array[i] == descriptor)
return true;
- if (fd_set_.fd_count < win_fd_set_size)
+
+ if (fd_set_->fd_count == capacity_)
{
- fd_set_.fd_array[fd_set_.fd_count++] = descriptor;
- return true;
+ u_int new_capacity = capacity_ + capacity_ / 2;
+ win_fd_set* new_fd_set = static_cast<win_fd_set*>(::operator new(
+ sizeof(win_fd_set) - sizeof(SOCKET)
+ + sizeof(SOCKET) * (new_capacity)));
+
+ new_fd_set->fd_count = fd_set_->fd_count;
+ for (u_int i = 0; i < fd_set_->fd_count; ++i)
+ new_fd_set->fd_array[i] = fd_set_->fd_array[i];
+
+ ::operator delete(fd_set_);
+ fd_set_ = new_fd_set;
+ capacity_ = new_capacity;
}
- return false;
+
+ fd_set_->fd_array[fd_set_->fd_count++] = descriptor;
+ return true;
}
bool is_set(socket_type descriptor) const
{
return !!__WSAFDIsSet(descriptor,
- const_cast<fd_set*>(reinterpret_cast<const fd_set*>(&fd_set_)));
+ const_cast<fd_set*>(reinterpret_cast<const fd_set*>(fd_set_)));
}
operator fd_set*()
{
- return reinterpret_cast<fd_set*>(&fd_set_);
+ return reinterpret_cast<fd_set*>(fd_set_);
}
socket_type max_descriptor() const
@@ -69,15 +98,19 @@
}
private:
+
// This structure is defined to be compatible with the Windows API fd_set
- // structure, but without being dependent on the value of FD_SETSIZE.
+ // structure, but without being dependent on the value of FD_SETSIZE. We use
+ // the "struct hack" to allow the number of descriptors to be varied at
+ // runtime.
struct win_fd_set
{
u_int fd_count;
- SOCKET fd_array[win_fd_set_size];
+ SOCKET fd_array[1];
};
- win_fd_set fd_set_;
+ win_fd_set* fd_set_;
+ u_int capacity_;
socket_type max_descriptor_;
};
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk