Compare commits
	
		
			2 Commits
		
	
	
		
			v11.3.1
			...
			feature/kq
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 0834198e74 | ||
|  | 22dd32d4e9 | 
| @@ -35,19 +35,122 @@ namespace ix | ||||
|         : _sockfd(fd) | ||||
|         , _selectInterrupt(createSelectInterrupt()) | ||||
|     { | ||||
|         ; | ||||
| #if defined(__APPLE__) | ||||
|         _kqueuefd = kqueue(); | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     Socket::~Socket() | ||||
|     { | ||||
|         close(); | ||||
|  | ||||
| #if defined(__APPLE__) | ||||
|         ::close(_kqueuefd); | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     PollResultType Socket::poll(bool readyToRead, | ||||
|                                 int timeoutMs, | ||||
|                                 int sockfd, | ||||
|                                 const SelectInterruptPtr& selectInterrupt) | ||||
|                                 const SelectInterruptPtr& selectInterrupt, | ||||
|                                 int kqueuefd) | ||||
|     { | ||||
| #if defined(__APPLE__) | ||||
|         // FIXME int kqueuefd = kqueue(); | ||||
|  | ||||
|         struct kevent ke; | ||||
|         EV_SET(&ke, sockfd, (readyToRead) ? EVFILT_READ : EVFILT_WRITE, EV_ADD, 0, 0, NULL); | ||||
|         if (kevent(kqueuefd, &ke, 1, NULL, 0, NULL) == -1) return PollResultType::Error; | ||||
|  | ||||
|         int retval, numevents = 0; | ||||
|  | ||||
|         int nfds = 1; | ||||
| #if 0 | ||||
|         if (selectInterrupt)  | ||||
|         { | ||||
|             nfds = 2; | ||||
|             int interruptFd = selectInterrupt->getFd(); | ||||
|  | ||||
|             struct kevent ke; | ||||
|             EV_SET(&ke, interruptFd, EVFILT_READ, EV_ADD, 0, 0, NULL); | ||||
|             if (kevent(kqueuefd, &ke, 1, NULL, 0, NULL) == -1) return PollResultType::Error; | ||||
|         } | ||||
| #endif | ||||
|  | ||||
|         struct kevent *events; | ||||
|         events = (struct kevent*) malloc(sizeof(struct kevent) * nfds); | ||||
|  | ||||
|         if (timeoutMs != 0) | ||||
|         { | ||||
|             struct timespec timeout; | ||||
|             timeout.tv_sec = timeoutMs / 1000; | ||||
|             timeout.tv_nsec = (timeoutMs % 1000) * 1000 * 1000; | ||||
|             retval = kevent(kqueuefd, NULL, 0, events, nfds, &timeout); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             retval = kevent(kqueuefd, NULL, 0, events, nfds, NULL); | ||||
|         } | ||||
|  | ||||
| #if 0 | ||||
|         if (retval > 0) { | ||||
|             int j; | ||||
|  | ||||
|             numevents = retval; | ||||
|             for(j = 0; j < numevents; j++) { | ||||
|                 int mask = 0; | ||||
|                 struct kevent *e = events+j; | ||||
|  | ||||
|                 if (e->filter == EVFILT_READ) mask |= AE_READABLE; | ||||
|                 if (e->filter == EVFILT_WRITE) mask |= AE_WRITABLE; | ||||
|                 eventLoop->fired[j].fd = e->ident; | ||||
|                 eventLoop->fired[j].mask = mask; | ||||
|             } | ||||
|         } | ||||
| #else | ||||
|         PollResultType pollResult = PollResultType::ReadyForRead; | ||||
|         if (retval < 0) | ||||
|         { | ||||
|             pollResult = PollResultType::Error; | ||||
|         } | ||||
|  | ||||
|         if (retval > 0) { | ||||
|             struct kevent *e = events; | ||||
|             if (e->filter == EVFILT_READ) | ||||
|             { | ||||
|                 pollResult = PollResultType::ReadyForRead; | ||||
|             } | ||||
|             else if (e->filter == EVFILT_WRITE)  | ||||
|             { | ||||
|                 pollResult = PollResultType::ReadyForWrite; | ||||
|  | ||||
|                 int optval = -1; | ||||
|                 socklen_t optlen = sizeof(optval); | ||||
|  | ||||
|                 // getsockopt() puts the errno value for connect into optval so 0 | ||||
|                 // means no-error. | ||||
|                 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1 || optval != 0) | ||||
|                 { | ||||
|                     pollResult = PollResultType::Error; | ||||
|  | ||||
|                     // set errno to optval so that external callers can have an | ||||
|                     // appropriate error description when calling strerror | ||||
|                     errno = optval; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             pollResult = PollResultType::Timeout; | ||||
|         } | ||||
| #endif | ||||
|  | ||||
|         free(events); | ||||
|  | ||||
|         // ::close(kqueuefd); //FMXE | ||||
|  | ||||
|         return pollResult; | ||||
| #else | ||||
|         // | ||||
|         // We used to use ::select to poll but on Android 9 we get large fds out of | ||||
|         // ::connect which crash in FD_SET as they are larger than FD_SETSIZE. Switching | ||||
| @@ -142,6 +245,7 @@ namespace ix | ||||
|         } | ||||
|  | ||||
|         return pollResult; | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     PollResultType Socket::isReadyToRead(int timeoutMs) | ||||
| @@ -152,7 +256,7 @@ namespace ix | ||||
|         } | ||||
|  | ||||
|         bool readyToRead = true; | ||||
|         return poll(readyToRead, timeoutMs, _sockfd, _selectInterrupt); | ||||
|         return poll(readyToRead, timeoutMs, _sockfd, _selectInterrupt, _kqueuefd); | ||||
|     } | ||||
|  | ||||
|     PollResultType Socket::isReadyToWrite(int timeoutMs) | ||||
| @@ -163,7 +267,7 @@ namespace ix | ||||
|         } | ||||
|  | ||||
|         bool readyToRead = false; | ||||
|         return poll(readyToRead, timeoutMs, _sockfd, _selectInterrupt); | ||||
|         return poll(readyToRead, timeoutMs, _sockfd, _selectInterrupt, _kqueuefd); | ||||
|     } | ||||
|  | ||||
|     // Wake up from poll/select by writing to the pipe which is watched by select | ||||
|   | ||||
| @@ -13,6 +13,13 @@ | ||||
| #include <string> | ||||
| #include <vector> | ||||
|  | ||||
| // For kqueue | ||||
| #if defined(__APPLE__) | ||||
| #include <sys/types.h> | ||||
| #include <sys/event.h> | ||||
| #include <sys/time.h> | ||||
| #endif | ||||
|  | ||||
| #ifdef _WIN32 | ||||
| #include <BaseTsd.h> | ||||
| typedef SSIZE_T ssize_t; | ||||
| @@ -94,7 +101,8 @@ namespace ix | ||||
|         static PollResultType poll(bool readyToRead, | ||||
|                                    int timeoutMs, | ||||
|                                    int sockfd, | ||||
|                                    const SelectInterruptPtr& selectInterrupt); | ||||
|                                    const SelectInterruptPtr& selectInterrupt, | ||||
|                                    int kqueuefd); | ||||
|  | ||||
|  | ||||
|         // Used as special codes for pipe communication | ||||
| @@ -114,5 +122,9 @@ namespace ix | ||||
|         static constexpr size_t kChunkSize = 1 << 15; | ||||
|  | ||||
|         SelectInterruptPtr _selectInterrupt; | ||||
|  | ||||
| #if defined(__APPLE__) | ||||
|         int _kqueuefd; | ||||
| #endif | ||||
|     }; | ||||
| } // namespace ix | ||||
|   | ||||
| @@ -66,7 +66,10 @@ namespace ix | ||||
|             int timeoutMs = 10; | ||||
|             bool readyToRead = false; | ||||
|             auto selectInterrupt = std::make_unique<SelectInterrupt>(); | ||||
|             PollResultType pollResult = Socket::poll(readyToRead, timeoutMs, fd, selectInterrupt); | ||||
|  | ||||
|             int kqueuefd = kqueue(); | ||||
|             PollResultType pollResult = Socket::poll(readyToRead, timeoutMs, fd, selectInterrupt, kqueuefd); | ||||
|             ::close(kqueuefd); | ||||
|  | ||||
|             if (pollResult == PollResultType::Timeout) | ||||
|             { | ||||
|   | ||||
| @@ -259,8 +259,11 @@ namespace ix | ||||
|             int timeoutMs = 10; | ||||
|             bool readyToRead = true; | ||||
|             auto selectInterrupt = std::make_unique<SelectInterrupt>(); | ||||
|  | ||||
|             int kqueuefd = kqueue(); | ||||
|             PollResultType pollResult = | ||||
|                 Socket::poll(readyToRead, timeoutMs, _serverFd, selectInterrupt); | ||||
|                 Socket::poll(readyToRead, timeoutMs, _serverFd, selectInterrupt, kqueuefd); | ||||
|             ::close(kqueuefd); | ||||
|  | ||||
|             if (pollResult == PollResultType::Error) | ||||
|             { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user