summaryrefslogtreecommitdiffstats
path: root/src/Net/FdManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Net/FdManager.cpp')
-rw-r--r--src/Net/FdManager.cpp105
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);
}
}