socklistener.h

Go to the documentation of this file.
00001 /*
00002     socklibpp library
00003     Copyright (C) 2005  Daniel K. O. <danielosmari at users.sf.net>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Lesser General Public
00007     License as published by the Free Software Foundation; either
00008     version 2.1 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Lesser General Public License for more details.
00014 
00015     You should have received a copy of the GNU Lesser General Public
00016     License along with this library; if not, write to the Free Software
00017     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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                         // put all the sockets until FD_SETSIZE in the fd_set struct
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                         // put all the sockets until FD_SETSIZE in the fd_set struct
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                         // put all the sockets until FD_SETSIZE in the fd_set struct
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                         // put all the sockets until FD_SETSIZE in the fd_set struct
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

Generated on Thu Jan 18 19:26:35 2007 for socklib++ by  doxygen 1.5.1