Index: src/OFRunLoop.h ================================================================== --- src/OFRunLoop.h +++ src/OFRunLoop.h @@ -15,10 +15,11 @@ */ #import "OFObject.h" #import "OFStream.h" #import "OFStreamObserver.h" +#import "OFTCPSocket.h" @class OFSortedList; @class OFTimer; @class OFMutableDictionary; @@ -56,10 +57,12 @@ length: (size_t)length block: (of_stream_async_read_block_t)block; + (void)_addAsyncReadLineForStream: (OFStream*)stream encoding: (of_string_encoding_t)encoding block: (of_stream_async_read_line_block_t)block; ++ (void)_addAsyncAcceptForTCPSocket: (OFTCPSocket*)socket + block: (of_tcpsocket_async_accept_block_t)block; #endif /** * \brief Adds an OFTimer to the run loop. * Index: src/OFRunLoop.m ================================================================== --- src/OFRunLoop.m +++ src/OFRunLoop.m @@ -50,10 +50,18 @@ } @property (copy) of_stream_async_read_line_block_t block; @property of_string_encoding_t encoding; @end + +@interface OFRunLoop_AcceptQueueItem: OFObject +{ + of_tcpsocket_async_accept_block_t block; +} + +@property (copy) of_tcpsocket_async_accept_block_t block; +@end @implementation OFRunLoop_ReadQueueItem @synthesize buffer, length, block; - (void)dealloc @@ -65,10 +73,21 @@ @end @implementation OFRunLoop_ReadLineQueueItem @synthesize block, encoding; +- (void)dealloc +{ + [block release]; + + [super dealloc]; +} +@end + +@implementation OFRunLoop_AcceptQueueItem +@synthesize block; + - (void)dealloc { [block release]; [super dealloc]; @@ -160,10 +179,34 @@ [queueItem setEncoding: encoding]; [queue appendObject: queueItem]; objc_autoreleasePoolPop(pool); } + ++ (void)_addAsyncAcceptForTCPSocket: (OFTCPSocket*)socket + block: (of_tcpsocket_async_accept_block_t)block +{ + void *pool = objc_autoreleasePoolPush(); + OFRunLoop *runLoop = [self currentRunLoop]; + OFList *queue = [runLoop->readQueues objectForKey: socket]; + OFRunLoop_AcceptQueueItem *queueItem; + + if (queue == nil) { + queue = [OFList list]; + [runLoop->readQueues setObject: queue + forKey: socket]; + } + + if ([queue count] == 0) + [runLoop->streamObserver addStreamForReading: socket]; + + queueItem = [[[OFRunLoop_AcceptQueueItem alloc] init] autorelease]; + [queueItem setBlock: block]; + [queue appendObject: queueItem]; + + objc_autoreleasePoolPop(pool); +} #endif - init { self = [super init]; @@ -244,10 +287,23 @@ [streamObserver removeStreamForReading: stream]; [readQueues removeObjectForKey: stream]; } } + } + } else if ([listObject->object isKindOfClass: + [OFRunLoop_AcceptQueueItem class]]) { + OFRunLoop_AcceptQueueItem *queueItem = listObject->object; + OFTCPSocket *newSocket = [(OFTCPSocket*)stream accept]; + + if (![queueItem block]((OFTCPSocket*)stream, newSocket)) { + [queue removeListObject: listObject]; + + if ([queue count] == 0) { + [streamObserver removeStreamForReading: stream]; + [readQueues removeObjectForKey: stream]; + } } } else OF_ENSURE(0); } #endif Index: src/OFTCPSocket.h ================================================================== --- src/OFTCPSocket.h +++ src/OFTCPSocket.h @@ -36,10 +36,11 @@ @class OFTCPSocket; @class OFString; #ifdef OF_HAVE_BLOCKS typedef void (^of_tcpsocket_async_connect_block_t)(OFTCPSocket*); +typedef BOOL (^of_tcpsocket_async_accept_block_t)(OFTCPSocket*, OFTCPSocket*); #endif /** * \brief A class which provides functions to create and use TCP sockets. * @@ -169,10 +170,21 @@ * \brief Accept an incoming connection. * * \return An autoreleased OFTCPSocket for the accepted connection. */ - (OFTCPSocket*)accept; + +#ifdef OF_HAVE_BLOCKS +/** + * \brief Asyncronously ccept an incoming connection. + * + * \param block The block to execute when a new connection has been accepted. + * Returns whether the next incoming connection should be accepted + * by the specified block as well. + */ +- (void)asyncAcceptWithBlock: (of_tcpsocket_async_accept_block_t)block; +#endif /** * \brief Enable or disable keep alives for the connection. * * \param enable Whether to enable or disable keep alives for the connection Index: src/OFTCPSocket.m ================================================================== --- src/OFTCPSocket.m +++ src/OFTCPSocket.m @@ -511,10 +511,18 @@ newSocket->sockAddr = addr; newSocket->sockAddrLen = addrLen; return newSocket; } + +#ifdef OF_HAVE_BLOCKS +- (void)asyncAcceptWithBlock: (of_tcpsocket_async_accept_block_t)block +{ + [OFRunLoop _addAsyncAcceptForTCPSocket: self + block: block]; +} +#endif - (void)setKeepAlivesEnabled: (BOOL)enable { int v = enable;