00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
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
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
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
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 }
00111