summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2014-01-23 19:17:22 -0500
committerAttila Molnar <attilamolnar@hush.com>2014-02-04 22:39:12 +0100
commit3752b3f59d5216d7dc6221a361efc76b9ad2273d (patch)
tree540ec25c9c643f1739875aa0add1f8a87a334e3c
parentd7164e521b2bf961dab531dff3914a17dec88949 (diff)
New socketengine stuff:
Use vectors that grow as necessary instead of mass allocating everything at once Rework poll engine logic to make sense
-rw-r--r--include/socketengine.h21
-rw-r--r--src/socketengine.cpp25
-rw-r--r--src/socketengines/socketengine_epoll.cpp43
-rw-r--r--src/socketengines/socketengine_kqueue.cpp41
-rw-r--r--src/socketengines/socketengine_poll.cpp146
-rw-r--r--src/socketengines/socketengine_ports.cpp80
-rw-r--r--src/socketengines/socketengine_select.cpp22
7 files changed, 184 insertions, 194 deletions
diff --git a/include/socketengine.h b/include/socketengine.h
index 4a2285a98..072ed9bde 100644
--- a/include/socketengine.h
+++ b/include/socketengine.h
@@ -230,13 +230,14 @@ class CoreExport EventHandler : public classbase
*/
class CoreExport SocketEngine
{
+ /** Reference table, contains all current handlers
+ **/
+ std::vector<EventHandler*> ref;
+
protected:
/** Current number of descriptors in the engine
*/
size_t CurrentSetSize;
- /** Reference table, contains all current handlers
- */
- EventHandler** ref;
/** List of handlers that want a trial read/write
*/
std::set<int> trials;
@@ -251,6 +252,18 @@ class CoreExport SocketEngine
virtual void OnSetEvent(EventHandler* eh, int old_mask, int new_mask) = 0;
void SetEventMask(EventHandler* eh, int value);
+
+ /** Add an event handler to the base socket engine. AddFd(EventHandler*, int) should call this.
+ */
+ bool AddFd(EventHandler* eh);
+
+ template <typename T>
+ void ResizeDouble(std::vector<T>& vect)
+ {
+ if (CurrentSetSize > vect.size())
+ vect.resize(vect.size() * 2);
+ }
+
public:
unsigned long TotalEvents;
@@ -314,7 +327,7 @@ public:
* required you must do this yourself.
* @param eh The event handler object to remove
*/
- virtual void DelFd(EventHandler* eh) = 0;
+ virtual void DelFd(EventHandler* eh);
/** Returns true if a file descriptor exists in
* the socket engine's list.
diff --git a/src/socketengine.cpp b/src/socketengine.cpp
index 219d154f2..c2a357b38 100644
--- a/src/socketengine.cpp
+++ b/src/socketengine.cpp
@@ -94,16 +94,33 @@ void SocketEngine::DispatchTrialWrites()
}
}
-bool SocketEngine::HasFd(int fd)
+bool SocketEngine::AddFd(EventHandler* eh)
{
- if ((fd < 0) || (fd > GetMaxFds()))
+ int fd = eh->GetFd();
+ if (HasFd(fd))
return false;
- return (ref[fd] != NULL);
+
+ while (static_cast<unsigned int>(fd) >= ref.size())
+ ref.resize(ref.empty() ? 1 : (ref.size() * 2));
+ ref[fd] = eh;
+ return true;
+}
+
+void SocketEngine::DelFd(EventHandler *eh)
+{
+ int fd = eh->GetFd();
+ if (GetRef(fd) == eh)
+ ref[fd] = NULL;
+}
+
+bool SocketEngine::HasFd(int fd)
+{
+ return GetRef(fd) != NULL;
}
EventHandler* SocketEngine::GetRef(int fd)
{
- if ((fd < 0) || (fd > GetMaxFds()))
+ if (fd < 0 || static_cast<unsigned int>(fd) >= ref.size())
return 0;
return ref[fd];
}
diff --git a/src/socketengines/socketengine_epoll.cpp b/src/socketengines/socketengine_epoll.cpp
index 099f793a1..8f5066c22 100644
--- a/src/socketengines/socketengine_epoll.cpp
+++ b/src/socketengines/socketengine_epoll.cpp
@@ -36,7 +36,7 @@ class EPollEngine : public SocketEngine
private:
/** These are used by epoll() to hold socket events
*/
- struct epoll_event* events;
+ std::vector<struct epoll_event> events;
int EngineHandle;
public:
/** Create a new EPollEngine
@@ -52,7 +52,7 @@ public:
virtual std::string GetName();
};
-EPollEngine::EPollEngine()
+EPollEngine::EPollEngine() : events(1)
{
int max = ulimit(4, 0);
if (max > 0)
@@ -77,18 +77,11 @@ EPollEngine::EPollEngine()
std::cout << "ERROR: Your kernel probably does not have the proper features. This is a fatal error, exiting now." << std::endl;
ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE);
}
-
- ref = new EventHandler* [GetMaxFds()];
- events = new struct epoll_event[GetMaxFds()];
-
- memset(ref, 0, GetMaxFds() * sizeof(EventHandler*));
}
EPollEngine::~EPollEngine()
{
this->Close(EngineHandle);
- delete[] ref;
- delete[] events;
}
static unsigned mask_to_epoll(int event_mask)
@@ -123,7 +116,7 @@ bool EPollEngine::AddFd(EventHandler* eh, int event_mask)
return false;
}
- if (ref[fd])
+ if (!SocketEngine::AddFd(eh))
{
ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Attempt to add duplicate fd: %d", fd);
return false;
@@ -142,9 +135,10 @@ bool EPollEngine::AddFd(EventHandler* eh, int event_mask)
ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "New file descriptor: %d", fd);
- ref[fd] = eh;
SocketEngine::SetEventMask(eh, event_mask);
CurrentSetSize++;
+ ResizeDouble(events);
+
return true;
}
@@ -182,7 +176,7 @@ void EPollEngine::DelFd(EventHandler* eh)
ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "epoll_ctl can't remove socket: %s", strerror(errno));
}
- ref[fd] = NULL;
+ SocketEngine::DelFd(eh);
ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Remove file descriptor: %d", fd);
CurrentSetSize--;
@@ -192,39 +186,44 @@ int EPollEngine::DispatchEvents()
{
socklen_t codesize = sizeof(int);
int errcode;
- int i = epoll_wait(EngineHandle, events, GetMaxFds() - 1, 1000);
+ int i = epoll_wait(EngineHandle, &events[0], events.size(), 1000);
ServerInstance->UpdateTime();
TotalEvents += i;
for (int j = 0; j < i; j++)
{
- EventHandler* eh = ref[events[j].data.fd];
+ struct epoll_event& ev = events[j];
+
+ EventHandler* eh = GetRef(ev.data.fd);
if (!eh)
{
ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Got event on unknown fd: %d", events[j].data.fd);
epoll_ctl(EngineHandle, EPOLL_CTL_DEL, events[j].data.fd, &events[j]);
continue;
}
- if (events[j].events & EPOLLHUP)
+
+ if (ev.events & EPOLLHUP)
{
ErrorEvents++;
eh->HandleEvent(EVENT_ERROR, 0);
continue;
}
- if (events[j].events & EPOLLERR)
+
+ if (ev.events & EPOLLERR)
{
ErrorEvents++;
/* Get error number */
- if (getsockopt(events[j].data.fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0)
+ if (getsockopt(ev.data.fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0)
errcode = errno;
eh->HandleEvent(EVENT_ERROR, errcode);
continue;
}
+
int mask = eh->GetEventMask();
- if (events[j].events & EPOLLIN)
+ if (ev.events & EPOLLIN)
mask &= ~FD_READ_WILL_BLOCK;
- if (events[j].events & EPOLLOUT)
+ if (ev.events & EPOLLOUT)
{
mask &= ~FD_WRITE_WILL_BLOCK;
if (mask & FD_WANT_SINGLE_WRITE)
@@ -235,15 +234,15 @@ int EPollEngine::DispatchEvents()
}
}
SetEventMask(eh, mask);
- if (events[j].events & EPOLLIN)
+ if (ev.events & EPOLLIN)
{
ReadEvents++;
eh->HandleEvent(EVENT_READ);
- if (eh != ref[events[j].data.fd])
+ if (eh != GetRef(ev.data.fd))
// whoa! we got deleted, better not give out the write event
continue;
}
- if (events[j].events & EPOLLOUT)
+ if (ev.events & EPOLLOUT)
{
WriteEvents++;
eh->HandleEvent(EVENT_WRITE);
diff --git a/src/socketengines/socketengine_kqueue.cpp b/src/socketengines/socketengine_kqueue.cpp
index 99ac51499..8c27b29b2 100644
--- a/src/socketengines/socketengine_kqueue.cpp
+++ b/src/socketengines/socketengine_kqueue.cpp
@@ -26,6 +26,7 @@
#include <sys/time.h>
#include "socketengine.h"
#include <iostream>
+#include <sys/sysctl.h>
/** A specialisation of the SocketEngine class, designed to use BSD kqueue().
*/
@@ -35,7 +36,7 @@ private:
int EngineHandle;
/** These are used by kqueue() to hold socket events
*/
- struct kevent* ke_list;
+ std::vector<struct kevent> ke_list;
/** This is a specialised time value used by kqueue()
*/
struct timespec ts;
@@ -54,9 +55,7 @@ public:
virtual void RecoverFromFork();
};
-#include <sys/sysctl.h>
-
-KQueueEngine::KQueueEngine()
+KQueueEngine::KQueueEngine() : ke_list(1)
{
MAX_DESCRIPTORS = 0;
int mib[2];
@@ -78,9 +77,6 @@ KQueueEngine::KQueueEngine()
}
this->RecoverFromFork();
- ke_list = new struct kevent[GetMaxFds()];
- ref = new EventHandler* [GetMaxFds()];
- memset(ref, 0, GetMaxFds() * sizeof(EventHandler*));
}
void KQueueEngine::RecoverFromFork()
@@ -105,8 +101,6 @@ void KQueueEngine::RecoverFromFork()
KQueueEngine::~KQueueEngine()
{
this->Close(EngineHandle);
- delete[] ref;
- delete[] ke_list;
}
bool KQueueEngine::AddFd(EventHandler* eh, int event_mask)
@@ -116,7 +110,7 @@ bool KQueueEngine::AddFd(EventHandler* eh, int event_mask)
if ((fd < 0) || (fd > GetMaxFds() - 1))
return false;
- if (ref[fd])
+ if (!SocketEngine::AddFd(eh))
return false;
// We always want to read from the socket...
@@ -131,12 +125,13 @@ bool KQueueEngine::AddFd(EventHandler* eh, int event_mask)
return false;
}
- ref[fd] = eh;
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "New file descriptor: %d", fd);
+
SocketEngine::SetEventMask(eh, event_mask);
OnSetEvent(eh, 0, event_mask);
CurrentSetSize++;
+ ResizeDouble(ke_list);
- ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "New file descriptor: %d", fd);
return true;
}
@@ -167,8 +162,8 @@ void KQueueEngine::DelFd(EventHandler* eh)
fd, strerror(errno));
}
+ SocketEngine::DelFd(eh);
CurrentSetSize--;
- ref[fd] = NULL;
ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Remove file descriptor: %d", fd);
}
@@ -215,23 +210,29 @@ int KQueueEngine::DispatchEvents()
ts.tv_nsec = 0;
ts.tv_sec = 1;
- int i = kevent(EngineHandle, NULL, 0, &ke_list[0], GetMaxFds(), &ts);
+ int i = kevent(EngineHandle, NULL, 0, &ke_list[0], ke_list.size(), &ts);
ServerInstance->UpdateTime();
+ if (i < 0)
+ return i;
+
TotalEvents += i;
for (int j = 0; j < i; j++)
{
- EventHandler* eh = ref[ke_list[j].ident];
+ struct kevent& kev = ke_list[j];
+
+ EventHandler* eh = GetRef(kev.ident);
if (!eh)
continue;
- if (ke_list[j].flags & EV_EOF)
+
+ if (kev.flags & EV_EOF)
{
ErrorEvents++;
- eh->HandleEvent(EVENT_ERROR, ke_list[j].fflags);
+ eh->HandleEvent(EVENT_ERROR, kev.fflags);
continue;
}
- if (ke_list[j].filter == EVFILT_WRITE)
+ if (kev.filter == EVFILT_WRITE)
{
WriteEvents++;
/* When mask is FD_WANT_FAST_WRITE or FD_WANT_SINGLE_WRITE,
@@ -242,11 +243,11 @@ int KQueueEngine::DispatchEvents()
SetEventMask(eh, eh->GetEventMask() & ~bits_to_clr);
eh->HandleEvent(EVENT_WRITE);
- if (eh != ref[ke_list[j].ident])
+ if (eh != GetRef(kev.ident))
// whoops, deleted out from under us
continue;
}
- if (ke_list[j].filter == EVFILT_READ)
+ if (kev.filter == EVFILT_READ)
{
ReadEvents++;
SetEventMask(eh, eh->GetEventMask() & ~FD_READ_WILL_BLOCK);
diff --git a/src/socketengines/socketengine_poll.cpp b/src/socketengines/socketengine_poll.cpp
index 493b22630..0112b7d2f 100644
--- a/src/socketengines/socketengine_poll.cpp
+++ b/src/socketengines/socketengine_poll.cpp
@@ -1,6 +1,7 @@
/*
* InspIRCd -- Internet Relay Chat Daemon
*
+ * Copyright (C) 2014 Adam <Adam@anope.org>
* Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
* Copyright (C) 2009 Uli Schlachter <psychon@znc.in>
* Copyright (C) 2009 Craig Edwards <craigedwards@brainbox.cc>
@@ -52,20 +53,16 @@ class PollEngine : public SocketEngine
private:
/** These are used by poll() to hold socket events
*/
- struct pollfd *events;
- /** This map maps fds to an index in the events array.
+ std::vector<struct pollfd> events;
+ /** This vector maps fds to an index in the events array.
*/
- std::map<int, unsigned int> fd_mappings;
+ std::vector<int> fd_mappings;
public:
/** Create a new PollEngine
*/
PollEngine();
- /** Delete a PollEngine
- */
- virtual ~PollEngine();
virtual bool AddFd(EventHandler* eh, int event_mask);
virtual void OnSetEvent(EventHandler* eh, int old_mask, int new_mask);
- virtual EventHandler* GetRef(int fd);
virtual void DelFd(EventHandler* eh);
virtual int DispatchEvents();
virtual std::string GetName();
@@ -73,7 +70,7 @@ public:
#endif
-PollEngine::PollEngine()
+PollEngine::PollEngine() : events(1), fd_mappings(1)
{
CurrentSetSize = 0;
struct rlimit limits;
@@ -87,19 +84,6 @@ PollEngine::PollEngine()
std::cout << "ERROR: Can't determine maximum number of open sockets: " << strerror(errno) << std::endl;
ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE);
}
-
- ref = new EventHandler* [GetMaxFds()];
- events = new struct pollfd[GetMaxFds()];
-
- memset(events, 0, GetMaxFds() * sizeof(struct pollfd));
- memset(ref, 0, GetMaxFds() * sizeof(EventHandler*));
-}
-
-PollEngine::~PollEngine()
-{
- // No destruction required, either.
- delete[] ref;
- delete[] events;
}
static int mask_to_poll(int event_mask)
@@ -121,7 +105,13 @@ bool PollEngine::AddFd(EventHandler* eh, int event_mask)
return false;
}
- if (fd_mappings.find(fd) != fd_mappings.end())
+ if (static_cast<unsigned int>(fd) < fd_mappings.size() && fd_mappings[fd] != -1)
+ {
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Attempt to add duplicate fd: %d", fd);
+ return false;
+ }
+
+ if (!SocketEngine::AddFd(eh))
{
ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Attempt to add duplicate fd: %d", fd);
return false;
@@ -129,35 +119,30 @@ bool PollEngine::AddFd(EventHandler* eh, int event_mask)
unsigned int index = CurrentSetSize;
+ while (static_cast<unsigned int>(fd) >= fd_mappings.size())
+ fd_mappings.resize(fd_mappings.size() * 2, -1);
fd_mappings[fd] = index;
- ref[index] = eh;
+
+ ResizeDouble(events);
events[index].fd = fd;
events[index].events = mask_to_poll(event_mask);
- ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "New file descriptor: %d (%d; index %d)", fd, events[fd].events, index);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "New file descriptor: %d (%d; index %d)", fd, events[index].events, index);
SocketEngine::SetEventMask(eh, event_mask);
CurrentSetSize++;
return true;
}
-EventHandler* PollEngine::GetRef(int fd)
-{
- std::map<int, unsigned int>::iterator it = fd_mappings.find(fd);
- if (it == fd_mappings.end())
- return NULL;
- return ref[it->second];
-}
-
void PollEngine::OnSetEvent(EventHandler* eh, int old_mask, int new_mask)
{
- std::map<int, unsigned int>::iterator it = fd_mappings.find(eh->GetFd());
- if (it == fd_mappings.end())
+ int fd = eh->GetFd();
+ if (fd < 0 || static_cast<unsigned int>(fd) >= fd_mappings.size() || fd_mappings[fd] == -1)
{
ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "SetEvents() on unknown fd: %d", eh->GetFd());
return;
}
- events[it->second].events = mask_to_poll(new_mask);
+ events[fd_mappings[fd]].events = mask_to_poll(new_mask);
}
void PollEngine::DelFd(EventHandler* eh)
@@ -169,14 +154,13 @@ void PollEngine::DelFd(EventHandler* eh)
return;
}
- std::map<int, unsigned int>::iterator it = fd_mappings.find(fd);
- if (it == fd_mappings.end())
+ if (static_cast<unsigned int>(fd) >= fd_mappings.size() || fd_mappings[fd] == -1)
{
ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "DelFd() on unknown fd: %d", fd);
return;
}
- unsigned int index = it->second;
+ unsigned int index = fd_mappings[fd];
unsigned int last_index = CurrentSetSize - 1;
int last_fd = events[last_index].fd;
@@ -190,16 +174,15 @@ void PollEngine::DelFd(EventHandler* eh)
// move last_fd from last_index into index
events[index].fd = last_fd;
events[index].events = events[last_index].events;
-
- ref[index] = ref[last_index];
}
// Now remove all data for the last fd we got into out list.
// Above code made sure this always is right
- fd_mappings.erase(it);
+ fd_mappings[fd] = -1;
events[last_index].fd = 0;
events[last_index].events = 0;
- ref[last_index] = NULL;
+
+ SocketEngine::DelFd(eh);
CurrentSetSize--;
@@ -209,58 +192,55 @@ void PollEngine::DelFd(EventHandler* eh)
int PollEngine::DispatchEvents()
{
- int i = poll(events, CurrentSetSize, 1000);
+ int i = poll(&events[0], CurrentSetSize, 1000);
int index;
socklen_t codesize = sizeof(int);
int errcode;
int processed = 0;
ServerInstance->UpdateTime();
- if (i > 0)
+ for (index = 0; index < CurrentSetSize && processed < i; index++)
{
- for (index = 0; index < CurrentSetSize && processed != i; index++)
- {
- if (events[index].revents)
- processed++;
- EventHandler* eh = ref[index];
- if (!eh)
- continue;
+ struct pollfd& pfd = events[index];
- if (events[index].revents & POLLHUP)
- {
- eh->HandleEvent(EVENT_ERROR, 0);
- continue;
- }
+ if (pfd.revents)
+ processed++;
+
+ EventHandler* eh = GetRef(pfd.fd);
+ if (!eh)
+ continue;
- if (events[index].revents & POLLERR)
- {
- // Get fd
- int fd = events[index].fd;
+ if (pfd.revents & POLLHUP)
+ {
+ eh->HandleEvent(EVENT_ERROR, 0);
+ continue;
+ }
- // Get error number
- if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0)
- errcode = errno;
- eh->HandleEvent(EVENT_ERROR, errcode);
+ if (pfd.revents & POLLERR)
+ {
+ // Get error number
+ if (getsockopt(pfd.fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0)
+ errcode = errno;
+ eh->HandleEvent(EVENT_ERROR, errcode);
+ continue;
+ }
+
+ if (pfd.revents & POLLIN)
+ {
+ SetEventMask(eh, eh->GetEventMask() & ~FD_READ_WILL_BLOCK);
+ eh->HandleEvent(EVENT_READ);
+ if (eh != GetRef(pfd.fd))
+ // whoops, deleted out from under us
continue;
- }
-
- if (events[index].revents & POLLIN)
- {
- SetEventMask(eh, eh->GetEventMask() & ~FD_READ_WILL_BLOCK);
- eh->HandleEvent(EVENT_READ);
- if (eh != ref[index])
- // whoops, deleted out from under us
- continue;
- }
-
- if (events[index].revents & POLLOUT)
- {
- int mask = eh->GetEventMask();
- mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE);
- SetEventMask(eh, mask);
- events[index].events = mask_to_poll(mask);
- eh->HandleEvent(EVENT_WRITE);
- }
+ }
+
+ if (pfd.revents & POLLOUT)
+ {
+ int mask = eh->GetEventMask();
+ mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE);
+ SetEventMask(eh, mask);
+ pfd.events = mask_to_poll(mask);
+ eh->HandleEvent(EVENT_WRITE);
}
}
diff --git a/src/socketengines/socketengine_ports.cpp b/src/socketengines/socketengine_ports.cpp
index ba4e8f2d7..936a8f6b9 100644
--- a/src/socketengines/socketengine_ports.cpp
+++ b/src/socketengines/socketengine_ports.cpp
@@ -42,9 +42,9 @@
class PortsEngine : public SocketEngine
{
private:
- /** These are used by epoll() to hold socket events
+ /** These are used by ports to hold socket events
*/
- port_event_t* events;
+ std::vector<port_event_t> events;
int EngineHandle;
public:
/** Create a new PortsEngine
@@ -65,7 +65,7 @@ public:
#include <ulimit.h>
-PortsEngine::PortsEngine()
+PortsEngine::PortsEngine() : events(1)
{
int max = ulimit(4, 0);
if (max > 0)
@@ -89,17 +89,11 @@ PortsEngine::PortsEngine()
ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE);
}
CurrentSetSize = 0;
-
- ref = new EventHandler* [GetMaxFds()];
- events = new port_event_t[GetMaxFds()];
- memset(ref, 0, GetMaxFds() * sizeof(EventHandler*));
}
PortsEngine::~PortsEngine()
{
this->Close(EngineHandle);
- delete[] ref;
- delete[] events;
}
static int mask_to_events(int event_mask)
@@ -118,15 +112,16 @@ bool PortsEngine::AddFd(EventHandler* eh, int event_mask)
if ((fd < 0) || (fd > GetMaxFds() - 1))
return false;
- if (ref[fd])
+ if (!SocketEngine::AddFd(eh))
return false;
- ref[fd] = eh;
SocketEngine::SetEventMask(eh, event_mask);
port_associate(EngineHandle, PORT_SOURCE_FD, fd, mask_to_events(event_mask), eh);
ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "New file descriptor: %d", fd);
CurrentSetSize++;
+ ResizeDouble(events);
+
return true;
}
@@ -145,7 +140,7 @@ void PortsEngine::DelFd(EventHandler* eh)
port_dissociate(EngineHandle, PORT_SOURCE_FD, fd);
CurrentSetSize--;
- ref[fd] = NULL;
+ SocketEngine::DelFd(eh);
ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Remove file descriptor: %d", fd);
}
@@ -158,7 +153,7 @@ int PortsEngine::DispatchEvents()
poll_time.tv_nsec = 0;
unsigned int nget = 1; // used to denote a retrieve request.
- int ret = port_getn(EngineHandle, this->events, GetMaxFds() - 1, &nget, &poll_time);
+ int ret = port_getn(EngineHandle, &events[0], events.size(), &nget, &poll_time);
ServerInstance->UpdateTime();
// first handle an error condition
@@ -170,38 +165,35 @@ int PortsEngine::DispatchEvents()
unsigned int i;
for (i = 0; i < nget; i++)
{
- switch (this->events[i].portev_source)
+ port_event_t& ev = events[i];
+
+ if (ev.portev_source != PORT_SOURCE_FD)
+ continue;
+
+ int fd = ev.portev_object;
+ EventHandler* eh = GetRef(fd);
+ if (!eh)
+ continue;
+
+ int mask = eh->GetEventMask();
+ if (ev.portev_events & POLLWRNORM)
+ mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE);
+ if (ev.portev_events & POLLRDNORM)
+ mask &= ~FD_READ_WILL_BLOCK;
+ // reinsert port for next time around, pretending to be one-shot for writes
+ SetEventMask(eh, mask);
+ port_associate(EngineHandle, PORT_SOURCE_FD, fd, mask_to_events(mask), eh);
+ if (ev.portev_events & POLLRDNORM)
+ {
+ ReadEvents++;
+ eh->HandleEvent(EVENT_READ);
+ if (eh != GetRef(fd))
+ continue;
+ }
+ if (ev.portev_events & POLLWRNORM)
{
- case PORT_SOURCE_FD:
- {
- int fd = this->events[i].portev_object;
- EventHandler* eh = ref[fd];
- if (eh)
- {
- int mask = eh->GetEventMask();
- if (events[i].portev_events & POLLWRNORM)
- mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE);
- if (events[i].portev_events & POLLRDNORM)
- mask &= ~FD_READ_WILL_BLOCK;
- // reinsert port for next time around, pretending to be one-shot for writes
- SetEventMask(eh, mask);
- port_associate(EngineHandle, PORT_SOURCE_FD, fd, mask_to_events(mask), eh);
- if (events[i].portev_events & POLLRDNORM)
- {
- ReadEvents++;
- eh->HandleEvent(EVENT_READ);
- if (eh != ref[fd])
- continue;
- }
- if (events[i].portev_events & POLLWRNORM)
- {
- WriteEvents++;
- eh->HandleEvent(EVENT_WRITE);
- }
- }
- }
- default:
- break;
+ WriteEvents++;
+ eh->HandleEvent(EVENT_WRITE);
}
}
diff --git a/src/socketengines/socketengine_select.cpp b/src/socketengines/socketengine_select.cpp
index f995b5472..39cfb7789 100644
--- a/src/socketengines/socketengine_select.cpp
+++ b/src/socketengines/socketengine_select.cpp
@@ -1,6 +1,7 @@
/*
* InspIRCd -- Internet Relay Chat Daemon
*
+ * Copyright (C) 2014 Adam <Adam@anope.org>
* Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
* Copyright (C) 2007-2008 Craig Edwards <craigedwards@brainbox.cc>
*
@@ -36,9 +37,6 @@ public:
/** Create a new SelectEngine
*/
SelectEngine();
- /** Delete a SelectEngine
- */
- virtual ~SelectEngine();
virtual bool AddFd(EventHandler* eh, int event_mask);
virtual void DelFd(EventHandler* eh);
void OnSetEvent(EventHandler* eh, int, int);
@@ -51,31 +49,21 @@ SelectEngine::SelectEngine()
MAX_DESCRIPTORS = FD_SETSIZE;
CurrentSetSize = 0;
- ref = new EventHandler* [GetMaxFds()];
- memset(ref, 0, GetMaxFds() * sizeof(EventHandler*));
-
FD_ZERO(&ReadSet);
FD_ZERO(&WriteSet);
FD_ZERO(&ErrSet);
MaxFD = 0;
}
-SelectEngine::~SelectEngine()
-{
- delete[] ref;
-}
-
bool SelectEngine::AddFd(EventHandler* eh, int event_mask)
{
int fd = eh->GetFd();
if ((fd < 0) || (fd > GetMaxFds() - 1))
return false;
- if (ref[fd])
+ if (!SocketEngine::AddFd(eh))
return false;
- ref[fd] = eh;
-
SocketEngine::SetEventMask(eh, event_mask);
OnSetEvent(eh, 0, event_mask);
FD_SET(fd, &ErrSet);
@@ -96,7 +84,7 @@ void SelectEngine::DelFd(EventHandler* eh)
return;
CurrentSetSize--;
- ref[fd] = NULL;
+ SocketEngine::DelFd(eh);
FD_CLR(fd, &ReadSet);
FD_CLR(fd, &WriteSet);
@@ -149,7 +137,7 @@ int SelectEngine::DispatchEvents()
{
--j;
- EventHandler* ev = ref[i];
+ EventHandler* ev = GetRef(i);
if (!ev)
continue;
@@ -171,7 +159,7 @@ int SelectEngine::DispatchEvents()
ReadEvents++;
SetEventMask(ev, ev->GetEventMask() & ~FD_READ_WILL_BLOCK);
ev->HandleEvent(EVENT_READ);
- if (ev != ref[i])
+ if (ev != GetRef(i))
continue;
}
if (has_write)