Index: src/OFKernelEventObserver.h ================================================================== --- src/OFKernelEventObserver.h +++ src/OFKernelEventObserver.h @@ -18,10 +18,15 @@ #import "OFObject.h" #ifdef OF_HAVE_SOCKETS # import "socket.h" #endif + +#ifdef OF_AMIGAOS +# include +# include +#endif OF_ASSUME_NONNULL_BEGIN @class OFMutableArray OF_GENERIC(ObjectType); @class OFDate; @@ -117,12 +122,15 @@ OFMutableArray OF_GENERIC(id ) *_readObjects; OFMutableArray OF_GENERIC(id ) *_writeObjects; id _Nullable _delegate; -#ifdef OF_HAVE_PIPE +#if defined(OF_HAVE_PIPE) int _cancelFD[2]; +#elif defined(OF_AMIGAOS) + struct Task *_waitingTask; + ULONG _cancelSignal; #else of_socket_t _cancelFD[2]; struct sockaddr_in _cancelAddr; #endif #ifdef OF_HAVE_THREADS Index: src/OFKernelEventObserver.m ================================================================== --- src/OFKernelEventObserver.m +++ src/OFKernelEventObserver.m @@ -53,10 +53,14 @@ #import "OFOutOfRangeException.h" #import "socket.h" #import "socket_helpers.h" +#ifdef OF_AMIGAOS +# include +#endif + enum { QUEUE_ADD = 0, QUEUE_REMOVE = 1, QUEUE_READ = 0, QUEUE_WRITE = 2 @@ -105,22 +109,23 @@ - (instancetype)init { self = [super init]; @try { -#if !defined(OF_HAVE_PIPE) && !defined(OF_WII) && !defined(OF_NINTENDO_3DS) +#if !defined(OF_HAVE_PIPE) && !defined(OF_WII) && !defined(OF_AMIGAOS) && \ + !defined(OF_NINTENDO_3DS) socklen_t cancelAddrLen; #endif _readObjects = [[OFMutableArray alloc] init]; _writeObjects = [[OFMutableArray alloc] init]; -#ifdef OF_HAVE_PIPE +#if defined(OF_HAVE_PIPE) if (pipe(_cancelFD)) @throw [OFInitializationFailedException exceptionWithClass: self.class]; -#else +#elif !defined(OF_AMIGAOS) _cancelFD[0] = _cancelFD[1] = socket(AF_INET, SOCK_DGRAM, 0); if (_cancelFD[0] == INVALID_SOCKET) @throw [OFInitializationFailedException exceptionWithClass: self.class]; @@ -181,15 +186,15 @@ return self; } - (void)dealloc { -#ifdef OF_HAVE_PIPE +#if defined(OF_HAVE_PIPE) close(_cancelFD[0]); if (_cancelFD[1] != _cancelFD[0]) close(_cancelFD[1]); -#else +#elif !defined(OF_AMIGAOS) closesocket(_cancelFD[0]); if (_cancelFD[1] != _cancelFD[0]) closesocket(_cancelFD[1]); #endif @@ -417,16 +422,25 @@ [self observeForTimeInterval: date.timeIntervalSinceNow]; } - (void)cancel { -#ifdef OF_HAVE_PIPE +#if defined(OF_HAVE_PIPE) OF_ENSURE(write(_cancelFD[1], "", 1) > 0); +#elif defined(OF_AMIGAOS) + Forbid(); + + if (_waitingTask != NULL) { + Signal(_waitingTask, (1 << _cancelSignal)); + _waitingTask = NULL; + } + + Permit(); #elif defined(OF_WII) OF_ENSURE(sendto(_cancelFD[1], "", 1, 0, (struct sockaddr *)&_cancelAddr, 8) > 0); #else OF_ENSURE(sendto(_cancelFD[1], (void *)"", 1, 0, (struct sockaddr *)&_cancelAddr, sizeof(_cancelAddr)) > 0); #endif } @end Index: src/OFSelectKernelEventObserver.m ================================================================== --- src/OFSelectKernelEventObserver.m +++ src/OFSelectKernelEventObserver.m @@ -40,30 +40,38 @@ #import "OFInitializationFailedException.h" #import "OFObserveFailedException.h" #import "OFOutOfRangeException.h" #import "socket_helpers.h" + +#ifdef OF_AMIGAOS +# include +#endif @implementation OFSelectKernelEventObserver - (instancetype)init { self = [super init]; -#ifndef OF_WINDOWS +#ifdef OF_AMIGAOS + _maxFD = 0; +#else +# ifndef OF_WINDOWS if (_cancelFD[0] >= (int)FD_SETSIZE) @throw [OFInitializationFailedException exceptionWithClass: self.class]; -#endif +# endif FD_ZERO(&_readFDs); FD_ZERO(&_writeFDs); FD_SET(_cancelFD[0], &_readFDs); if (_cancelFD[0] > INT_MAX) @throw [OFOutOfRangeException exception]; _maxFD = (int)_cancelFD[0]; +#endif return self; } - (void)of_addObjectForReading: (id )object @@ -142,11 +150,11 @@ fd_set readFDs; fd_set writeFDs; struct timeval timeout; int events; #ifdef OF_AMIGAOS - ULONG execSignalMask; + ULONG execSignalMask, cancelSignal; #endif size_t count; [self of_processQueue]; @@ -173,13 +181,30 @@ timeout.tv_sec = (long)timeInterval; #endif timeout.tv_usec = (int)lrint((timeInterval - timeout.tv_sec) * 1000); #ifdef OF_AMIGAOS - execSignalMask = _execSignalMask; + if ((cancelSignal = AllocSignal(-1)) == (ULONG)-1) + @throw [OFObserveFailedException exceptionWithObserver: self + errNo: EAGAIN]; + + execSignalMask = _execSignalMask | (1 << cancelSignal); + + Forbid(); + + _waitingTask = FindTask(NULL); + _cancelSignal = cancelSignal; + events = WaitSelect(_maxFD + 1, &readFDs, &writeFDs, NULL, (void *)(timeInterval != -1 ? &timeout : NULL), &execSignalMask); + + execSignalMask &= ~(1 << cancelSignal); + + _waitingTask = NULL; + FreeSignal(_cancelSignal); + + Permit(); #else events = select(_maxFD + 1, &readFDs, &writeFDs, NULL, (timeInterval != -1 ? &timeout : NULL)); #endif @@ -189,22 +214,22 @@ #ifdef OF_AMIGAOS if (execSignalMask != 0 && [_delegate respondsToSelector: @selector(execSignalWasReceived:)]) [_delegate execSignalWasReceived: execSignalMask]; -#endif - +#else if (FD_ISSET(_cancelFD[0], &readFDs)) { char buffer; -#ifdef OF_HAVE_PIPE +# ifdef OF_HAVE_PIPE OF_ENSURE(read(_cancelFD[0], &buffer, 1) == 1); -#else +# else OF_ENSURE(recvfrom(_cancelFD[0], (void *)&buffer, 1, 0, NULL, NULL) == 1); -#endif +# endif } +#endif objects = _readObjects.objects; count = _readObjects.count; for (size_t i = 0; i < count; i++) {