00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef SOCKLISTENER_H
00023 #define SOCKLISTENER_H
00024
00025 #include <list>
00026 #include <utility>
00027 #include <functional>
00028
00029 #include "sockbase.h"
00030
00031 namespace socklibpp {
00032
00053 template<class T=int>
00054 class listener {
00055 typedef std::list< std::pair<sock, T> > _sock_list;
00056 _sock_list _sockets;
00057
00058 struct Compare {
00059 bool operator()(const std::pair<sock, T>& a,
00060 const std::pair<sock, T>& b)
00061 { return a.fd == b.fd; }
00062 };
00063
00064 public:
00065
00072 void add(sock sb_, const T& data_ = T())
00073 {
00074 _sockets.push_back(std::make_pair(sb_, data_));
00075 }
00076
00080 bool remove(sock sb_)
00081 {
00082 return _sockets.remove_if(std::bind2nd(Compare(), sb_));
00083 }
00084
00085
00092 unsigned size() const throw() { return _sockets.size(); }
00093
00094
00102 bool empty() const throw() { return _sockets.empty(); }
00103
00104
00125 void readable(std::list<std::pair<sock, T> >& readlist, int usec=0, int sec=0)
00126 {
00127 int i;
00128 typename _sock_list::const_iterator it = _sockets.begin(), first;
00129 fd_set readset;
00130
00131 while (it!=_sockets.end()) {
00132 FD_ZERO(&readset);
00133 first = it;
00134
00135 for (i=0; i<FD_SETSIZE && it!=_sockets.end(); i++, ++it)
00136 FD_SET(it->first.fd, &readset);
00137
00138 struct timeval tv = { sec, usec };
00139
00140 int r = ::select(FD_SETSIZE, &readset, 0, 0, &tv);
00141
00142 if (r==sock::socket_error)
00143 return;
00144
00145 if (r>0)
00146 for (; first!=it; ++first)
00147 if (FD_ISSET(first->first.fd, &readset))
00148 readlist.push_back(*first);
00149 }
00150 }
00151
00152
00180 template<class Op>
00181 void for_each_read(Op op, int usec=0, int sec=0)
00182 {
00183 int _i;
00184 typename _sock_list::iterator
00185 _it = _sockets.begin(),
00186 _first;
00187 fd_set readset;
00188
00189 while (_it!=_sockets.end()) {
00190 FD_ZERO(&readset);
00191 _first = _it;
00192
00193 for (_i=0; _i<FD_SETSIZE && _it!=_sockets.end(); _i++, ++_it)
00194 FD_SET(_it->first.fd, &readset);
00195
00196 struct timeval tv = { sec, usec };
00197
00198 int _r = ::select(FD_SETSIZE, &readset, 0, 0, &tv);
00199
00200 if (_r==sock::socket_error)
00201 return;
00202
00203 if (_r>0)
00204 for (; _first!=_it; ++_first)
00205 if (FD_ISSET(_first->first.fd, &readset))
00206 if (op(_first->first, _first->second))
00207 _sockets.erase(_first--);
00208 }
00209 }
00210
00211
00232 void writeable(std::list<std::pair<sock, T> >& writelist, int usec=0, int sec=0)
00233 {
00234 int i;
00235 typename _sock_list::const_iterator it = _sockets.begin(), first;
00236 fd_set writeset;
00237
00238 while (it!=_sockets.end()) {
00239 FD_ZERO(&writeset);
00240 first = it;
00241
00242 for (i=0; i<FD_SETSIZE && it!=_sockets.end(); i++, ++it)
00243 FD_SET(it->first.fd, &writeset);
00244
00245 struct timeval tv = { sec, usec };
00246 int r = ::select(FD_SETSIZE, 0, &writeset, 0, &tv);
00247
00248 if (r==sock::socket_error)
00249 return;
00250
00251 if (r>0)
00252 for (; first!=it; ++first)
00253 if (FD_ISSET(first->first.fd, &writeset))
00254 writelist.push_back(*first);
00255 }
00256 }
00257
00258
00292 template<class Op>
00293 void for_each_write(Op op, int usec=0, int sec=0)
00294 {
00295 int _i;
00296 typename _sock_list::iterator
00297 _it = _sockets.begin(),
00298 _first;
00299 fd_set writeset;
00300
00301 while (_it!=_sockets.end()) {
00302 FD_ZERO(&writeset);
00303 _first = _it;
00304
00305 for (_i=0; _i<FD_SETSIZE && _it!=_sockets.end(); _i++, ++_it)
00306 FD_SET(_it->first.fd, &writeset);
00307
00308 struct timeval tv = { sec, usec };
00309
00310 int _r = ::select(FD_SETSIZE, 0, &writeset, 0, &tv);
00311
00312 if (_r==sock::socket_error)
00313 return;
00314
00315 if (_r>0)
00316 for (; _first!=_it; ++_first)
00317 if (FD_ISSET(_first->first.fd, &writeset))
00318 if (op(_first->first, _first->second))
00319 _sockets.erase(_first--);
00320 }
00321 }
00322
00323
00324 };
00325
00326
00327 }
00328
00329
00330 #endif