annotate DEPENDENCIES/generic/include/boost/asio/detail/win_fd_set_adapter.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 //
Chris@16 2 // detail/win_fd_set_adapter.hpp
Chris@16 3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Chris@16 4 //
Chris@101 5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
Chris@16 6 //
Chris@16 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
Chris@16 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 9 //
Chris@16 10
Chris@16 11 #ifndef BOOST_ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP
Chris@16 12 #define BOOST_ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP
Chris@16 13
Chris@16 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
Chris@16 15 # pragma once
Chris@16 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
Chris@16 17
Chris@16 18 #include <boost/asio/detail/config.hpp>
Chris@16 19
Chris@16 20 #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
Chris@16 21
Chris@16 22 #include <boost/asio/detail/noncopyable.hpp>
Chris@101 23 #include <boost/asio/detail/reactor_op_queue.hpp>
Chris@16 24 #include <boost/asio/detail/socket_types.hpp>
Chris@16 25
Chris@16 26 #include <boost/asio/detail/push_options.hpp>
Chris@16 27
Chris@16 28 namespace boost {
Chris@16 29 namespace asio {
Chris@16 30 namespace detail {
Chris@16 31
Chris@16 32 // Adapts the FD_SET type to meet the Descriptor_Set concept's requirements.
Chris@16 33 class win_fd_set_adapter : noncopyable
Chris@16 34 {
Chris@16 35 public:
Chris@16 36 enum { default_fd_set_size = 1024 };
Chris@16 37
Chris@16 38 win_fd_set_adapter()
Chris@16 39 : capacity_(default_fd_set_size),
Chris@16 40 max_descriptor_(invalid_socket)
Chris@16 41 {
Chris@16 42 fd_set_ = static_cast<win_fd_set*>(::operator new(
Chris@16 43 sizeof(win_fd_set) - sizeof(SOCKET)
Chris@16 44 + sizeof(SOCKET) * (capacity_)));
Chris@16 45 fd_set_->fd_count = 0;
Chris@16 46 }
Chris@16 47
Chris@16 48 ~win_fd_set_adapter()
Chris@16 49 {
Chris@16 50 ::operator delete(fd_set_);
Chris@16 51 }
Chris@16 52
Chris@16 53 void reset()
Chris@16 54 {
Chris@16 55 fd_set_->fd_count = 0;
Chris@16 56 max_descriptor_ = invalid_socket;
Chris@16 57 }
Chris@16 58
Chris@16 59 bool set(socket_type descriptor)
Chris@16 60 {
Chris@16 61 for (u_int i = 0; i < fd_set_->fd_count; ++i)
Chris@16 62 if (fd_set_->fd_array[i] == descriptor)
Chris@16 63 return true;
Chris@16 64
Chris@101 65 reserve(fd_set_->fd_count + 1);
Chris@16 66 fd_set_->fd_array[fd_set_->fd_count++] = descriptor;
Chris@16 67 return true;
Chris@16 68 }
Chris@16 69
Chris@101 70 void set(reactor_op_queue<socket_type>& operations, op_queue<operation>&)
Chris@101 71 {
Chris@101 72 reactor_op_queue<socket_type>::iterator i = operations.begin();
Chris@101 73 while (i != operations.end())
Chris@101 74 {
Chris@101 75 reactor_op_queue<socket_type>::iterator op_iter = i++;
Chris@101 76 reserve(fd_set_->fd_count + 1);
Chris@101 77 fd_set_->fd_array[fd_set_->fd_count++] = op_iter->first;
Chris@101 78 }
Chris@101 79 }
Chris@101 80
Chris@16 81 bool is_set(socket_type descriptor) const
Chris@16 82 {
Chris@16 83 return !!__WSAFDIsSet(descriptor,
Chris@16 84 const_cast<fd_set*>(reinterpret_cast<const fd_set*>(fd_set_)));
Chris@16 85 }
Chris@16 86
Chris@16 87 operator fd_set*()
Chris@16 88 {
Chris@16 89 return reinterpret_cast<fd_set*>(fd_set_);
Chris@16 90 }
Chris@16 91
Chris@16 92 socket_type max_descriptor() const
Chris@16 93 {
Chris@16 94 return max_descriptor_;
Chris@16 95 }
Chris@16 96
Chris@101 97 void perform(reactor_op_queue<socket_type>& operations,
Chris@101 98 op_queue<operation>& ops) const
Chris@101 99 {
Chris@101 100 for (u_int i = 0; i < fd_set_->fd_count; ++i)
Chris@101 101 operations.perform_operations(fd_set_->fd_array[i], ops);
Chris@101 102 }
Chris@101 103
Chris@16 104 private:
Chris@16 105 // This structure is defined to be compatible with the Windows API fd_set
Chris@16 106 // structure, but without being dependent on the value of FD_SETSIZE. We use
Chris@16 107 // the "struct hack" to allow the number of descriptors to be varied at
Chris@16 108 // runtime.
Chris@16 109 struct win_fd_set
Chris@16 110 {
Chris@16 111 u_int fd_count;
Chris@16 112 SOCKET fd_array[1];
Chris@16 113 };
Chris@16 114
Chris@101 115 // Increase the fd_set_ capacity to at least the specified number of elements.
Chris@101 116 void reserve(u_int n)
Chris@101 117 {
Chris@101 118 if (n <= capacity_)
Chris@101 119 return;
Chris@101 120
Chris@101 121 u_int new_capacity = capacity_ + capacity_ / 2;
Chris@101 122 if (new_capacity < n)
Chris@101 123 new_capacity = n;
Chris@101 124
Chris@101 125 win_fd_set* new_fd_set = static_cast<win_fd_set*>(::operator new(
Chris@101 126 sizeof(win_fd_set) - sizeof(SOCKET)
Chris@101 127 + sizeof(SOCKET) * (new_capacity)));
Chris@101 128
Chris@101 129 new_fd_set->fd_count = fd_set_->fd_count;
Chris@101 130 for (u_int i = 0; i < fd_set_->fd_count; ++i)
Chris@101 131 new_fd_set->fd_array[i] = fd_set_->fd_array[i];
Chris@101 132
Chris@101 133 ::operator delete(fd_set_);
Chris@101 134 fd_set_ = new_fd_set;
Chris@101 135 capacity_ = new_capacity;
Chris@101 136 }
Chris@101 137
Chris@16 138 win_fd_set* fd_set_;
Chris@16 139 u_int capacity_;
Chris@16 140 socket_type max_descriptor_;
Chris@16 141 };
Chris@16 142
Chris@16 143 } // namespace detail
Chris@16 144 } // namespace asio
Chris@16 145 } // namespace boost
Chris@16 146
Chris@16 147 #include <boost/asio/detail/pop_options.hpp>
Chris@16 148
Chris@16 149 #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
Chris@16 150
Chris@16 151 #endif // BOOST_ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP