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

poller_devpoll.cc

00001 /************************************************************************
00002  *
00003  * $Id: poller_devpoll.cc,v 1.14 2001/08/21 19:57:52 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 <string.h>
00028 #include <sys/ioctl.h>
00029 #include <sys/stat.h>
00030 #include <sys/types.h>
00031 #include <fcntl.h>
00032 #include <sys/poll.h>
00033 #include <sys/devpoll.h>
00034 #include <errno.h>
00035 
00036 #include "poller_devpoll.h"
00037 #include "poller_util.h"
00038 
00039 namespace fpoller {
00040 
00041   poller_devpoll::poller_devpoll():pollfds_(MAX_FDS){
00042     if ((devpoll_fd_ = open("/dev/poll",O_RDWR)) <0) {
00043       throw new exception("Could not open /dev/poll",errno);
00044     }
00045     dvpoll_.dp_fds = &pollfds_[0];
00046     dvpoll_.dp_nfds= MAX_FDS;
00047     dvpoll_.dp_timeout = 0;
00048   }
00049 
00050   poller_devpoll::~poller_devpoll(){
00051     close(devpoll_fd_);
00052   }
00053 
00054   void poller_devpoll::add(int fd, short interest, callback *cb){
00055     if (cb->operator()(fd) == REMOVE) {
00056       //we can just avoid adding;
00057       delete cb;
00058       return;
00059     }
00060     pollfd pfd;
00061     pfd.fd = fd;
00062     pfd.events=interest;
00063     changefds_.push_back(pfd);      
00064     fd_maps_.get_map(interest).insert(make_pair(fd,callback_wrapper(cb)));
00065   }
00066   
00067   void poller_devpoll::remove(int fd, short interest){
00068     changefds_.push_back((struct pollfd){fd,POLLREMOVE,0});
00069     fd_maps_.get_map(interest).erase(fd);
00070     // if we are removing for READ, but we still want WRITE, we have to resubmit and vice versa
00071     short opposite_interest = interest & WRITE ? READ : WRITE;
00072     fd_map &map = fd_maps_.get_map(opposite_interest);
00073     if ( map.find(fd) != map.end()){
00074       pollfd pfd;
00075       pfd.fd = fd;
00076       pfd.events=opposite_interest;
00077       changefds_.push_back(pfd);      
00078     }
00079   }
00080 
00081   int poller_devpoll::poll(int timeout){
00082     //first take care of all the changes that have been made since the last time we polled
00083     if (changefds_.size() > 0){
00084       if (write(devpoll_fd_,&changefds_[0],(sizeof(pollfd) * changefds_.size())) != static_cast<int>(sizeof(pollfd) * changefds_.size())){
00085         throw exception("Could not write to /dev/poll",errno);
00086       }
00087     }
00088     changefds_.clear();
00089     int nready,retval;
00090     dvpoll_.dp_timeout = timeout;
00091     if ((retval = nready = ioctl(devpoll_fd_,DP_POLL,&dvpoll_)) < 0){
00092       throw exception("Could not read from /dev/poll",errno);
00093     }
00094     for (pollfd * pfd = &pollfds_[0]; nready ; pfd++){
00095       nready--;
00096       fd_map &map = fd_maps_.get_map(pfd->revents);
00097       fd_map::iterator it = map.find(pfd->fd);
00098       if (it == map.end()){
00099         //should never happen
00100         remove(pfd->fd,pfd->revents);
00101       }else{
00102         if ((*(it->second))(pfd->fd) == REMOVE){
00103           remove(pfd->fd,pfd->revents);
00104         }
00105       }
00106     }
00107     return retval;
00108   }
00109   
00110 }//namespace fpoller
00111 

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