/* * FdManager.cpp * * Copyright (C) 2008 Matthias Schiffer * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "FdManager.h" #include #include #include #include namespace Mad { namespace Net { FdManager FdManager::fdManager; FdManager::FdManager() { pipe(interruptPipe); int flags = fcntl(interruptPipe[0], F_GETFL, 0); fcntl(interruptPipe[0], F_SETFL, flags | O_NONBLOCK); flags = fcntl(interruptPipe[1], F_GETFL, 0); fcntl(interruptPipe[1], F_SETFL, flags | O_NONBLOCK); registerFd(interruptPipe[0], sigc::hide(sigc::mem_fun(this, &FdManager::readInterrupt)), POLLIN); } FdManager::~FdManager() { unregisterFd(interruptPipe[0]); close(interruptPipe[0]); close(interruptPipe[1]); } bool FdManager::registerFd(int fd, const sigc::slot &handler, short events) { struct pollfd pollfd = {fd, events, 0}; pollfds.insert(std::make_pair(fd, pollfd)); return handlers.insert(std::make_pair(fd, handler)).second; } bool FdManager::unregisterFd(int fd) { pollfds.erase(fd); return handlers.erase(fd); } bool FdManager::setFdEvents(int fd, short events) { std::map::iterator pollfd = pollfds.find(fd); if(pollfd == pollfds.end()) return false; if(pollfd->second.events != events) { pollfd->second.events = events; interrupt(); } return true; } short FdManager::getFdEvents(int fd) const { std::map::const_iterator pollfd = pollfds.find(fd); if(pollfd == pollfds.end()) return -1; return pollfd->second.events; } void FdManager::readInterrupt() { char buf[20]; while(read(interruptPipe[0], buf, sizeof(buf)) > 0) {} } void FdManager::interrupt() { char buf = 0; write(interruptPipe[1], &buf, sizeof(buf)); } void FdManager::run() { readInterrupt(); size_t count = pollfds.size(); struct pollfd *fdarray = new struct pollfd[count]; std::map::iterator pollfd = pollfds.begin(); for(size_t n = 0; n < count; ++n) { fdarray[n] = pollfd->second; ++pollfd; } if(poll(fdarray, count, -1) > 0) { for(size_t n = 0; n < count; ++n) { if(fdarray[n].revents) handlers[fdarray[n].fd](fdarray[n].revents); } } delete [] fdarray; } } }