monotone

monotone Mtn Source Tree

Root/netxx/probe_select.cxx

1/*
2 * Copyright (C) 2001-2004 Peter J Jones (pjones@pmade.org)
3 * All Rights Reserved
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 * 3. Neither the name of the Author nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
23 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/** @file
34 * This file contains the implementation of the Netxx::Probe_impl class for
35 * the select(2) system call.
36**/
37
38// select sucks
39#define FD_SETSIZE 65536
40
41// common header
42#include "common.h"
43
44// Netxx includes
45#include "probe_impl.h"
46#include "netxx/types.h"
47#include "netxx/timeout.h"
48
49// standard includes
50#include <memory>
51#include <algorithm>
52#include <string>
53#include <list>
54#include <set>
55
56//####################################################################
57namespace
58{
59 struct pimpl
60 {
61std::list<Netxx::socket_type> rd_sockets_;
62std::list<Netxx::socket_type> wr_sockets_;
63std::list<Netxx::socket_type> er_sockets_;
64 };
65}
66//####################################################################
67Netxx::Probe_impl::Probe_impl (void)
68{
69 pimpl_ = new pimpl;
70}
71//####################################################################
72Netxx::Probe_impl::Probe_impl (const Probe_impl &other)
73{
74 std::auto_ptr<pimpl> ap(new pimpl); pimpl_ = ap.get();
75
76 static_cast<pimpl*>(pimpl_)->rd_sockets_ = static_cast<pimpl*>(other.pimpl_)->rd_sockets_;
77 static_cast<pimpl*>(pimpl_)->wr_sockets_ = static_cast<pimpl*>(other.pimpl_)->wr_sockets_;
78 static_cast<pimpl*>(pimpl_)->er_sockets_ = static_cast<pimpl*>(other.pimpl_)->er_sockets_;
79
80 ap.release();
81}
82//####################################################################
83Netxx::Probe_impl& Netxx::Probe_impl::operator= (const Probe_impl &other)
84{
85 Probe_impl tmp(other); swap(tmp);
86 return *this;
87}
88//####################################################################
89void Netxx::Probe_impl::swap (Probe_impl &other)
90{
91 static_cast<pimpl*>(pimpl_)->rd_sockets_.swap(static_cast<pimpl*>(other.pimpl_)->rd_sockets_);
92 static_cast<pimpl*>(pimpl_)->wr_sockets_.swap(static_cast<pimpl*>(other.pimpl_)->wr_sockets_);
93 static_cast<pimpl*>(pimpl_)->er_sockets_.swap(static_cast<pimpl*>(other.pimpl_)->er_sockets_);
94}
95//####################################################################
96Netxx::Probe_impl::~Probe_impl (void)
97{
98 delete static_cast<pimpl*>(pimpl_);
99}
100//####################################################################
101void Netxx::Probe_impl::add (socket_type socketfd, Probe::ready_type rt)
102{
103 if (rt == Probe::ready_none || rt & Probe::ready_read)
104static_cast<pimpl*>(pimpl_)->rd_sockets_.push_back(socketfd);
105
106 if (rt == Probe::ready_none || rt & Probe::ready_write)
107static_cast<pimpl*>(pimpl_)->wr_sockets_.push_back(socketfd);
108
109 if (rt == Probe::ready_none || rt & Probe::ready_oobd)
110static_cast<pimpl*>(pimpl_)->er_sockets_.push_back(socketfd);
111}
112//####################################################################
113void Netxx::Probe_impl::remove (socket_type socketfd)
114{
115 static_cast<pimpl*>(pimpl_)->rd_sockets_.remove(socketfd);
116 static_cast<pimpl*>(pimpl_)->wr_sockets_.remove(socketfd);
117 static_cast<pimpl*>(pimpl_)->er_sockets_.remove(socketfd);
118}
119//####################################################################
120void Netxx::Probe_impl::clear (void)
121{
122 static_cast<pimpl*>(pimpl_)->rd_sockets_.clear();
123 static_cast<pimpl*>(pimpl_)->wr_sockets_.clear();
124 static_cast<pimpl*>(pimpl_)->er_sockets_.clear();
125}
126
127struct fdsets
128{
129 fd_set *rd, *wr, *er;
130 fdsets() : rd(new fd_set), wr(new fd_set), er(new fd_set)
131 {
132 }
133 ~fdsets()
134 {
135 delete rd;
136 delete wr;
137 delete er;
138 }
139};
140
141//####################################################################
142Netxx::Probe_impl::probe_type Netxx::Probe_impl::probe (const Timeout &timeout, Probe::ready_type rt)
143{
144 pimpl *p=static_cast<pimpl*>(pimpl_);
145 probe_type return_value;
146
147 fdsets my_fd_sets;
148 fd_set &rd_fdset(*my_fd_sets.rd),
149 &wr_fdset(*my_fd_sets.wr),
150 &er_fdset(*my_fd_sets.er);
151 fd_set *rd_fdptr, *wr_fdptr, *er_fdptr;
152 timeval tmp_timeout;
153 timeval *timeout_ptr;
154 socket_type max_fd;
155 int rc;
156
157 for (;;) {
158if (timeout) {
159 tmp_timeout.tv_sec = timeout.get_sec();
160 tmp_timeout.tv_usec = timeout.get_usec();
161 timeout_ptr = &tmp_timeout;
162} else {
163 timeout_ptr = 0;
164}
165
166FD_ZERO(&rd_fdset);
167FD_ZERO(&wr_fdset);
168FD_ZERO(&er_fdset);
169
170std::set<socket_type> all_sockets;
171std::list<socket_type>::const_iterator it, end;
172
173if (rt == Probe::ready_none || rt & Probe::ready_read) {
174 for (it=p->rd_sockets_.begin(), end=p->rd_sockets_.end(); it!=end; ++it) {
175FD_SET(*it, &rd_fdset);
176all_sockets.insert(*it);
177 }
178
179 rd_fdptr = &rd_fdset;
180} else {
181 rd_fdptr = 0;
182}
183
184if (rt == Probe::ready_none || rt & Probe::ready_write) {
185 for (it=p->wr_sockets_.begin(), end=p->wr_sockets_.end(); it!=end; ++it) {
186FD_SET(*it, &wr_fdset);
187all_sockets.insert(*it);
188 }
189
190 wr_fdptr = &wr_fdset;
191} else {
192 wr_fdptr = 0;
193}
194
195if (rt == Probe::ready_none || rt & Probe::ready_oobd) {
196 for (it=p->er_sockets_.begin(), end=p->er_sockets_.end(); it!=end; ++it) {
197FD_SET(*it, &er_fdset);
198all_sockets.insert(*it);
199 }
200
201 er_fdptr = &er_fdset;
202} else {
203 er_fdptr = 0;
204}
205
206if (all_sockets.empty()) {
207 return return_value;
208}
209
210std::set<socket_type>::const_iterator maxfd_it = std::max_element(all_sockets.begin(), all_sockets.end());
211max_fd = maxfd_it == all_sockets.end() ? 0 : *maxfd_it;
212
213if (max_fd > FD_SETSIZE) {
214 throw Exception("Netxx::Probe: too many sockets for select");
215}
216
217if ( (rc = select(max_fd+1, rd_fdptr, wr_fdptr, er_fdptr, timeout_ptr)) > 0) {
218 std::set<socket_type>::const_iterator all_it=all_sockets.begin(), all_end=all_sockets.end();
219 Probe::ready_type ready_bits;
220
221 for (; all_it!=all_end; ++all_it) {
222ready_bits = Probe::ready_none;
223
224if (FD_ISSET(*all_it, &rd_fdset)) ready_bits |= Probe::ready_read;
225if (FD_ISSET(*all_it, &wr_fdset)) ready_bits |= Probe::ready_write;
226if (FD_ISSET(*all_it, &er_fdset)) ready_bits |= Probe::ready_oobd;
227if (ready_bits != Probe::ready_none) return_value.push_back(std::make_pair(*all_it, ready_bits));
228 }
229
230 return return_value;
231
232} else if (rc == 0) {
233 return return_value;
234} else {
235 error_type error_code = get_last_error();
236
237 switch (error_code) {
238case EINTR:
239 continue;
240
241default:
242{
243 std::string error("select(2): ");
244 error += str_error(error_code);
245 throw Exception(error);
246}
247 }
248}
249 }
250
251 /* not reached */
252 return return_value;
253}
254//####################################################################

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status