diff options
Diffstat (limited to 'boost/asio/detail/win_fd_set_adapter.hpp')
-rw-r--r-- | boost/asio/detail/win_fd_set_adapter.hpp | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/boost/asio/detail/win_fd_set_adapter.hpp b/boost/asio/detail/win_fd_set_adapter.hpp new file mode 100644 index 0000000000..afb40d0115 --- /dev/null +++ b/boost/asio/detail/win_fd_set_adapter.hpp @@ -0,0 +1,125 @@ +// +// detail/win_fd_set_adapter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 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 BOOST_ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP +#define BOOST_ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#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> + +namespace boost { +namespace asio { +namespace detail { + +// Adapts the FD_SET type to meet the Descriptor_Set concept's requirements. +class win_fd_set_adapter : noncopyable +{ +public: + enum { default_fd_set_size = 1024 }; + + win_fd_set_adapter() + : capacity_(default_fd_set_size), + max_descriptor_(invalid_socket) + { + 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) + return true; + + if (fd_set_->fd_count == capacity_) + { + 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; + } + + 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_))); + } + + operator fd_set*() + { + return reinterpret_cast<fd_set*>(fd_set_); + } + + socket_type max_descriptor() const + { + return max_descriptor_; + } + +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. 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[1]; + }; + + win_fd_set* fd_set_; + u_int capacity_; + socket_type max_descriptor_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + +#endif // BOOST_ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP |