Artifact 6084d1377430bf38aa16cf9a614ab0bfa10368e10f74729dcefd2fd68e2f024c:
- File
src/OFKernelEventObserver_select.m
— part of check-in
[a2738e1a3d]
at
2015-05-02 21:46:28
on branch trunk
— FD_SETSIZE is not (maximum FD number + 1) on Win32
Instead, FD_SETSIZE is the number of file descriptors supported by
select(), independent of the actual file descriptor number.The default value is 64, even though it seems that Win32 supports much
more than that. Thus, this is defined to 1024 on Win32 now. (user: js, size: 4209) [annotate] [blame] [check-ins using]
/* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 * Jonathan Schleifer <js@webkeks.org> * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in * the packaging of this file. * * Alternatively, it may be distributed under the terms of the GNU General * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #define __NO_EXT_QNX #include "config.h" #ifdef _WIN32 /* Win32 has a ridiculous default of 64, even though it supports much more. */ # define FD_SETSIZE 1024 #endif #include <errno.h> #include <math.h> #include <string.h> #include <sys/time.h> #import "OFKernelEventObserver.h" #import "OFKernelEventObserver+Private.h" #import "OFKernelEventObserver_select.h" #import "OFArray.h" #import "OFObserveFailedException.h" #import "OFOutOfRangeException.h" #import "socket_helpers.h" @implementation OFKernelEventObserver_select - init { self = [super init]; FD_ZERO(&_readFDs); FD_ZERO(&_writeFDs); FD_SET(_cancelFD[0], &_readFDs); return self; } - (void)OF_addFileDescriptorForReading: (int)fd { #ifndef _WIN32 if (fd >= FD_SETSIZE) @throw [OFOutOfRangeException exception]; #endif FD_SET(fd, &_readFDs); } - (void)OF_addFileDescriptorForWriting: (int)fd { #ifndef _WIN32 if (fd >= FD_SETSIZE) @throw [OFOutOfRangeException exception]; #endif FD_SET(fd, &_writeFDs); } - (void)OF_removeFileDescriptorForReading: (int)fd { if (fd >= FD_SETSIZE) @throw [OFOutOfRangeException exception]; FD_CLR(fd, &_readFDs); } - (void)OF_removeFileDescriptorForWriting: (int)fd { if (fd >= FD_SETSIZE) @throw [OFOutOfRangeException exception]; FD_CLR(fd, &_writeFDs); } - (bool)observeForTimeInterval: (of_time_interval_t)timeInterval { void *pool = objc_autoreleasePoolPush(); id const *objects; fd_set readFDs; fd_set writeFDs; struct timeval timeout; int events; size_t i, count, realEvents = 0; [self OF_processQueueAndStoreRemovedIn: nil]; if ([self OF_processReadBuffers]) { objc_autoreleasePoolPop(pool); return true; } objc_autoreleasePoolPop(pool); #ifdef FD_COPY FD_COPY(&_readFDs, &readFDs); FD_COPY(&_writeFDs, &writeFDs); #else readFDs = _readFDs; writeFDs = _writeFDs; #endif /* * We cast to int before assigning to tv_usec in order to avoid a * warning with Apple GCC on PPC. POSIX defines this as suseconds_t, * however, this is not available on Win32. As an int should always * satisfy the required range, we just cast to int. */ #ifndef _WIN32 timeout.tv_sec = (time_t)timeInterval; #else timeout.tv_sec = (long)timeInterval; #endif timeout.tv_usec = (int)lrint((timeInterval - timeout.tv_sec) * 1000); events = select((int)_maxFD + 1, &readFDs, &writeFDs, NULL, (timeInterval != -1 ? &timeout : NULL)); if (events < 0) @throw [OFObserveFailedException exceptionWithObserver: self errNo: errno]; if (events == 0) return false; if (FD_ISSET(_cancelFD[0], &readFDs)) { char buffer; #ifndef _WIN32 OF_ENSURE(read(_cancelFD[0], &buffer, 1) == 1); #else OF_ENSURE(recvfrom(_cancelFD[0], &buffer, 1, 0, NULL, NULL) == 1); #endif } objects = [_readObjects objects]; count = [_readObjects count]; for (i = 0; i < count; i++) { int fd = [objects[i] fileDescriptorForReading]; pool = objc_autoreleasePoolPush(); if (FD_ISSET(fd, &readFDs)) { if ([_delegate respondsToSelector: @selector(objectIsReadyForReading:)]) [_delegate objectIsReadyForReading: objects[i]]; realEvents++; } objc_autoreleasePoolPop(pool); } objects = [_writeObjects objects]; count = [_writeObjects count]; for (i = 0; i < count; i++) { int fd = [objects[i] fileDescriptorForWriting]; pool = objc_autoreleasePoolPush(); if (FD_ISSET(fd, &writeFDs)) { if ([_delegate respondsToSelector: @selector(objectIsReadyForWriting:)]) [_delegate objectIsReadyForWriting: objects[i]]; realEvents++; } objc_autoreleasePoolPop(pool); } if (realEvents == 0) return false; return true; } @end