Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   Related Pages   Examples  

poller_generic.cc

00001 /************************************************************************
00002  *
00003  * $Id: poller_generic.cc,v 1.13 2002/10/16 19:36:38 crooney Exp $
00004  *
00005  ***********************************************************************/
00006 
00007 /**************************************************************************
00008 Copyright 2001, Christopher Rooney crooney@crooney.com
00009 
00010 This file is part of fpoller.
00011 
00012 fpoller is free software; you can redistribute it and/or modify
00013 it under the terms of the GNU General Public License as published by
00014 the Free Software Foundation; either version 2 of the License, or
00015 (at your option) any later version.
00016 
00017 fpoller is distributed in the hope that it will be useful,
00018 but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 GNU General Public License for more details.
00021 
00022 You should have received a copy of the GNU General Public License
00023 along with fpoller; if not, write to the Free Software
00024 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 *************************************************************************/
00026 
00027 #include "poller_generic.h"
00028 
00029 namespace fpoller {
00030   poller_generic::poller_generic():num_fds_(0),pollfds_(MAX_FDS){
00031     for (int i = 0; i<MAX_FDS; i++){
00032       available_.push(i);
00033       pollfds_[i].fd = -1;
00034     }
00035   }
00036 
00037   void poller_generic::add(int fd, short interest, callback* cb){
00038     if (cb->operator()(fd) == REMOVE) {
00039       //we can just avoid adding;
00040       delete cb;
00041       return;
00042     }
00043     if (available_.empty()){
00044       unsigned i = pollfds_.size();
00045       pollfds_.resize(static_cast<unsigned>(i*1.5));
00046       for (;i < pollfds_.size();i++){
00047         available_.push(i);
00048         pollfds_[i].fd = -1;
00049       }
00050     }else{
00051       fd_map::iterator iter = fd_map_.find(fd);
00052       if (iter != fd_map_.end()){
00053         fd_info &info = iter->second;
00054         pollfds_[info.pollfds_index].fd = fd;
00055         pollfds_[info.pollfds_index].events |= interest;
00056         if ((interest & READ)){
00057           info.reader = callback_wrapper(cb);
00058         }
00059         if ((interest & WRITE)){
00060           info.writer = callback_wrapper(cb);
00061         }
00062       }else{
00063         int index = available_.top();
00064         available_.pop();
00065         pollfds_[index].fd = fd;
00066         pollfds_[index].events = interest;
00067         fd_info info;
00068         info.pollfds_index = index;
00069         if (interest & READ){
00070           info.reader = callback_wrapper(cb);
00071         }
00072         if (interest & WRITE){
00073           info.writer = callback_wrapper(cb);
00074         }
00075         fd_map_.insert(std::make_pair(fd,info));
00076         if (index > num_fds_){
00077           num_fds_ = index;
00078         }
00079       }
00080     }
00081   }
00082 
00083   void poller_generic::remove(int fd, short interest){
00084     fd_map::iterator iter = fd_map_.find(fd);
00085     if (iter != fd_map_.end()){
00086       fd_info &info = iter->second;
00087       int &index = info.pollfds_index;
00088       pollfd &pfd = pollfds_[index];
00089       if (interest ^ pfd.events > 0){
00090         //the fd waits on other events just remove for interest
00091         pfd.events ^= interest;
00092         if (interest & READ){
00093           info.reader = callback_wrapper();
00094         }
00095         if (interest & WRITE){
00096           info.writer = callback_wrapper();
00097         }
00098       }else{
00099         //actually remove
00100         pfd.fd = -1;
00101         pfd.events = 0;
00102         pfd.revents = 0;
00103         available_.push(index);
00104         if (index >= num_fds_){
00105           for(;pollfds_[num_fds_].fd <0 && num_fds_;){
00106             num_fds_--;
00107           }
00108         }
00109         fd_map_.erase(iter);
00110       }
00111     }
00112   }
00113 
00114   int poller_generic::poll(int timeout){
00115     int nready,retval;
00116     if ((retval = nready = ::poll(&pollfds_[0],num_fds_+1,timeout)) < 0){
00117       return retval;
00118     }
00119 
00120     for (pollfd *pfd = &pollfds_[0];
00121          nready && (pfd < (&pollfds_[num_fds_ + 1])) ;
00122          pfd++){
00123       short relevant_events;
00124       if ((relevant_events = pfd->revents & (pfd->events | ERROR))){
00125         nready--;
00126         fd_info &info = fd_map_[pfd->fd];
00127         if (relevant_events & (READ | ERROR)) {
00128           try_callback(pfd->fd,info.reader,READ);
00129         }
00130         if (relevant_events & (WRITE | ERROR)) {
00131           try_callback(pfd->fd,info.writer,WRITE);
00132         }
00133       }
00134     }
00135     return retval;
00136   }
00137   
00138 }
00139 
00140 
00141   

Generated at Wed Oct 16 16:02:39 2002 for fpoller by doxygen1.2.9.1 written by Dimitri van Heesch, © 1997-2001