]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/socketengines/socketengine_kqueue.cpp
m_services_account Remove now needless workaround added to 2.0 to display the correct...
[user/henk/code/inspircd.git] / src / socketengines / socketengine_kqueue.cpp
index 61f5cd92232b92ea41da728e4386c5c7be262ba5..b7797a82f5588590ae2d29c6ee634a8d03a38430 100644 (file)
 namespace
 {
        int EngineHandle;
+       unsigned int ChangePos = 0;
        /** These are used by kqueue() to hold socket events
         */
        std::vector<struct kevent> ke_list(16);
+
+       /** Pending changes
+        */
+       std::vector<struct kevent> changelist(8);
 }
 
 /** Initialize the kqueue engine
@@ -89,6 +94,13 @@ void SocketEngine::Deinit()
        Close(EngineHandle);
 }
 
+static struct kevent* GetChangeKE()
+{
+       if (ChangePos >= changelist.size())
+               changelist.resize(changelist.size() * 2);
+       return &changelist[ChangePos++];
+}
+
 bool SocketEngine::AddFd(EventHandler* eh, int event_mask)
 {
        int fd = eh->GetFd();
@@ -100,16 +112,8 @@ bool SocketEngine::AddFd(EventHandler* eh, int event_mask)
                return false;
 
        // We always want to read from the socket...
-       struct kevent ke;
-       EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
-
-       int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
-       if (i == -1)
-       {
-               ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "Failed to add fd: %d %s",
-                                         fd, strerror(errno));
-               return false;
-       }
+       struct kevent* ke = GetChangeKE();
+       EV_SET(ke, fd, EVFILT_READ, EV_ADD, 0, 0, static_cast<void*>(eh));
 
        ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "New file descriptor: %d", fd);
 
@@ -130,22 +134,14 @@ void SocketEngine::DelFd(EventHandler* eh)
                return;
        }
 
-       struct kevent ke;
-
        // First remove the write filter ignoring errors, since we can't be
        // sure if there are actually any write filters registered.
-       EV_SET(&ke, eh->GetFd(), EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
-       kevent(EngineHandle, &ke, 1, 0, 0, NULL);
+       struct kevent* ke = GetChangeKE();
+       EV_SET(ke, eh->GetFd(), EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
 
        // Then remove the read filter.
-       EV_SET(&ke, eh->GetFd(), EVFILT_READ, EV_DELETE, 0, 0, NULL);
-       int j = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
-
-       if (j < 0)
-       {
-               ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "Failed to remove fd: %d %s",
-                                         fd, strerror(errno));
-       }
+       ke = GetChangeKE();
+       EV_SET(ke, eh->GetFd(), EVFILT_READ, EV_DELETE, 0, 0, NULL);
 
        SocketEngine::DelFdRef(eh);
 
@@ -157,32 +153,19 @@ void SocketEngine::OnSetEvent(EventHandler* eh, int old_mask, int new_mask)
        if ((new_mask & FD_WANT_POLL_WRITE) && !(old_mask & FD_WANT_POLL_WRITE))
        {
                // new poll-style write
-               struct kevent ke;
-               EV_SET(&ke, eh->GetFd(), EVFILT_WRITE, EV_ADD, 0, 0, NULL);
-               int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
-               if (i < 0)
-                       ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "Failed to mark for writing: %d %s",
-                                                 eh->GetFd(), strerror(errno));
+               struct kevent* ke = GetChangeKE();
+               EV_SET(ke, eh->GetFd(), EVFILT_WRITE, EV_ADD, 0, 0, static_cast<void*>(eh));
        }
        else if ((old_mask & FD_WANT_POLL_WRITE) && !(new_mask & FD_WANT_POLL_WRITE))
        {
                // removing poll-style write
-               struct kevent ke;
-               EV_SET(&ke, eh->GetFd(), EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
-               int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
-               if (i < 0)
-                       ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "Failed to mark for writing: %d %s",
-                                                 eh->GetFd(), strerror(errno));
+               struct kevent* ke = GetChangeKE();
+               EV_SET(ke, eh->GetFd(), EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
        }
        if ((new_mask & (FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE)) && !(old_mask & (FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE)))
        {
-               // new one-shot write
-               struct kevent ke;
-               EV_SET(&ke, eh->GetFd(), EVFILT_WRITE, EV_ADD | EV_ONESHOT, 0, 0, NULL);
-               int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
-               if (i < 0)
-                       ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "Failed to mark for writing: %d %s",
-                                                 eh->GetFd(), strerror(errno));
+               struct kevent* ke = GetChangeKE();
+               EV_SET(ke, eh->GetFd(), EVFILT_WRITE, EV_ADD | EV_ONESHOT, 0, 0, static_cast<void*>(eh));
        }
 }
 
@@ -192,7 +175,8 @@ int SocketEngine::DispatchEvents()
        ts.tv_nsec = 0;
        ts.tv_sec = 1;
 
-       int i = kevent(EngineHandle, NULL, 0, &ke_list[0], ke_list.size(), &ts);
+       int i = kevent(EngineHandle, &changelist.front(), ChangePos, &ke_list.front(), ke_list.size(), &ts);
+       ChangePos = 0;
        ServerInstance->UpdateTime();
 
        if (i < 0)
@@ -203,13 +187,14 @@ int SocketEngine::DispatchEvents()
        for (int j = 0; j < i; j++)
        {
                struct kevent& kev = ke_list[j];
+               EventHandler* eh = static_cast<EventHandler*>(kev.udata);
+               if (!eh)
+                       continue;
 
                // Copy these in case the vector gets resized and kev invalidated
-               const int fd = kev.ident;
+               const int fd = eh->GetFd();
                const short filter = kev.filter;
-
-               EventHandler* eh = GetRef(fd);
-               if (!eh)
+               if (fd < 0)
                        continue;
 
                if (kev.flags & EV_EOF)