diff options
author | Matthias Schiffer <matthias@gamezock.de> | 2009-05-15 17:30:40 +0200 |
---|---|---|
committer | Matthias Schiffer <matthias@gamezock.de> | 2009-05-15 17:30:40 +0200 |
commit | c8d469cc3de8ef2fb95f7b47355ebf5318a4c22f (patch) | |
tree | 2cb0bd20306f89f3da11ff22b19865ed99225b2f /src/Net/FdManager.cpp | |
parent | 8324b947487f72fd8cfc439ea5ae5bd1187fff1b (diff) | |
download | mad-c8d469cc3de8ef2fb95f7b47355ebf5318a4c22f.tar mad-c8d469cc3de8ef2fb95f7b47355ebf5318a4c22f.zip |
Einfache (ziemlich kaputte) Multithreaded IO
Diffstat (limited to 'src/Net/FdManager.cpp')
-rw-r--r-- | src/Net/FdManager.cpp | 105 |
1 files changed, 86 insertions, 19 deletions
diff --git a/src/Net/FdManager.cpp b/src/Net/FdManager.cpp index ffa4d8b..499ad62 100644 --- a/src/Net/FdManager.cpp +++ b/src/Net/FdManager.cpp @@ -18,11 +18,14 @@ */ #include "FdManager.h" +#include "ThreadManager.h" + #include <signal.h> #include <unistd.h> #include <sys/fcntl.h> #include <sigc++/adaptors/hide.h> +#include <sigc++/bind.h> namespace Mad { @@ -31,7 +34,11 @@ namespace Net { FdManager FdManager::fdManager; -FdManager::FdManager() { +FdManager::FdManager() : running(false) { + gl_rwlock_init(handlerLock); + gl_rwlock_init(eventLock); + gl_rwlock_init(runLock); + pipe(interruptPipe); int flags = fcntl(interruptPipe[0], F_GETFL, 0); @@ -48,43 +55,73 @@ FdManager::~FdManager() { close(interruptPipe[0]); close(interruptPipe[1]); + + gl_rwlock_destroy(runLock); + gl_rwlock_destroy(eventLock); + gl_rwlock_destroy(handlerLock); } bool FdManager::registerFd(int fd, const sigc::slot<void, short> &handler, short events) { struct pollfd pollfd = {fd, events, 0}; + gl_rwlock_wrlock(handlerLock); + gl_rwlock_wrlock(eventLock); pollfds.insert(std::make_pair(fd, pollfd)); - return handlers.insert(std::make_pair(fd, handler)).second; + bool ret = handlers.insert(std::make_pair(fd, handler)).second; + gl_rwlock_unlock(eventLock); + gl_rwlock_unlock(handlerLock); + + interrupt(); + + return ret; } bool FdManager::unregisterFd(int fd) { + gl_rwlock_wrlock(handlerLock); + gl_rwlock_wrlock(eventLock); pollfds.erase(fd); - return handlers.erase(fd); + bool ret = handlers.erase(fd); + gl_rwlock_unlock(eventLock); + gl_rwlock_unlock(handlerLock); + + interrupt(); + + return ret; } bool FdManager::setFdEvents(int fd, short events) { + gl_rwlock_wrlock(eventLock); std::map<int, struct pollfd>::iterator pollfd = pollfds.find(fd); - if(pollfd == pollfds.end()) + if(pollfd == pollfds.end()) { + gl_rwlock_unlock(eventLock); return false; + } if(pollfd->second.events != events) { pollfd->second.events = events; interrupt(); } + gl_rwlock_unlock(eventLock); + return true; } -short FdManager::getFdEvents(int fd) const { +short FdManager::getFdEvents(int fd) { + gl_rwlock_rdlock(eventLock); + std::map<int, struct pollfd>::const_iterator pollfd = pollfds.find(fd); if(pollfd == pollfds.end()) return -1; - return pollfd->second.events; + short ret = pollfd->second.events; + gl_rwlock_unlock(eventLock); + + return ret; } void FdManager::readInterrupt() { @@ -99,27 +136,57 @@ void FdManager::interrupt() { write(interruptPipe[1], &buf, sizeof(buf)); } -void FdManager::run() { - readInterrupt(); +void FdManager::ioThread() { + gl_rwlock_wrlock(runLock); + running = true; + gl_rwlock_unlock(runLock); - size_t count = pollfds.size(); - struct pollfd *fdarray = new struct pollfd[count]; + gl_rwlock_rdlock(runLock); + while(running) { + gl_rwlock_unlock(runLock); - std::map<int, struct pollfd>::iterator pollfd = pollfds.begin(); + gl_rwlock_rdlock(handlerLock); + gl_rwlock_rdlock(eventLock); + readInterrupt(); - for(size_t n = 0; n < count; ++n) { - fdarray[n] = pollfd->second; - ++pollfd; - } + size_t count = pollfds.size(); + struct pollfd *fdarray = new struct pollfd[count]; + + std::map<int, struct pollfd>::iterator pollfd = pollfds.begin(); - 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); + fdarray[n] = pollfd->second; + ++pollfd; + } + + gl_rwlock_unlock(eventLock); + gl_rwlock_unlock(handlerLock); + + if(poll(fdarray, count, -1) > 0) { + gl_rwlock_rdlock(handlerLock); + + std::queue<sigc::slot<void> > calls; + + for(size_t n = 0; n < count; ++n) { + if(fdarray[n].revents) + calls.push(sigc::bind(handlers[fdarray[n].fd], fdarray[n].revents)); + } + + gl_rwlock_unlock(handlerLock); + + while(!calls.empty()) { + calls.front()(); + calls.pop(); + } + } + + delete [] fdarray; + + gl_rwlock_rdlock(runLock); } - delete [] fdarray; + gl_rwlock_unlock(runLock); } } |