浏览代码

Support both NSOperationQueue and dispatch_queue_t for delegates

Mike Lewis 13 年之前
父节点
当前提交
c679b34022
共有 2 个文件被更改,包括 46 次插入13 次删除
  1. 4 2
      SocketRocket/SRWebSocket.h
  2. 42 11
      SocketRocket/SRWebSocket.m

+ 4 - 2
SocketRocket/SRWebSocket.h

@@ -50,8 +50,10 @@ extern NSString *const SRWebSocketErrorDomain;
 - (id)initWithURL:(NSURL *)url protocols:(NSArray *)protocols;
 - (id)initWithURL:(NSURL *)url;
 
-// Delegage queue will be +[NSOperationQueue mainQueue] by default
-- (void)setDelegateQueue:(NSOperationQueue*) queue;
+// Delegage queue will be dispatch_main_queue by default
+// Only can set OperationQeuue or dispatch_queue
+- (void)setDelegateOperationQueue:(NSOperationQueue*) queue;
+- (void)setDelegateDispatchQueue:(dispatch_queue_t) queue;
 
 // By default, it will schedule itself on +[NSRunLoop SR_networkRunLoop] using defaultModes
 - (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;

+ 42 - 11
SocketRocket/SRWebSocket.m

@@ -206,15 +206,18 @@ typedef void (^data_callback)(SRWebSocket *webSocket,  NSData *data);
 
 @property (nonatomic) SRReadyState readyState;
 
-@property (nonatomic) NSOperationQueue *delegateQueue;
-
+@property (nonatomic) NSOperationQueue *delegateOperationQueue;
+@property (nonatomic) dispatch_queue_t delegateDispatchQueue;
 
 @end
 
 
 @implementation SRWebSocket {
     NSInteger _webSocketVersion;
-    NSOperationQueue *_delegateQueue;
+    
+    NSOperationQueue *_delegateOperationQueue;
+    dispatch_queue_t _delegateDispatchQueue;
+    
     dispatch_queue_t _workQueue;
     NSMutableArray *_consumers;
 
@@ -330,7 +333,8 @@ static __strong NSData *CRLFCRLF;
     
     _workQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
     
-    _delegateQueue = [NSOperationQueue mainQueue];
+    _delegateDispatchQueue = dispatch_get_main_queue();
+    dispatch_retain(_delegateDispatchQueue);
     
     _readBuffer = [[NSMutableData alloc] init];
     _outputBuffer = [[NSMutableData alloc] init];
@@ -359,6 +363,11 @@ static __strong NSData *CRLFCRLF;
         CFRelease(_receivedHTTPHeaders);
         _receivedHTTPHeaders = NULL;
     }
+    
+    if (_delegateDispatchQueue) {
+        dispatch_release(_delegateDispatchQueue);
+        _delegateDispatchQueue = NULL;
+    }
 }
 
 #ifndef NDEBUG
@@ -383,7 +392,29 @@ static __strong NSData *CRLFCRLF;
     [self _connect];
 }
 
+// Calls block on delegate queue
+- (void)_performDelegateBlock:(dispatch_block_t)block;
+{
+    if (_delegateOperationQueue) {
+        [_delegateOperationQueue addOperationWithBlock:block];
+    } else {
+        assert(_delegateDispatchQueue);
+        dispatch_async(_delegateDispatchQueue, block);
+    }
+}
 
+- (void)setDelegateDispatchQueue:(dispatch_queue_t)queue;
+{
+    if (queue) {
+        dispatch_retain(queue);
+    }
+    
+    if (_delegateDispatchQueue) {
+        dispatch_release(_delegateDispatchQueue);
+    }
+    
+    _delegateDispatchQueue = queue;
+}
 
 - (BOOL)_checkHandshake:(CFHTTPMessageRef)httpMessage;
 {
@@ -432,7 +463,7 @@ static __strong NSData *CRLFCRLF;
         [self _readFrameNew];
     }
 
-    [_delegateQueue addOperationWithBlock:^{
+    [self _performDelegateBlock:^{
         if ([self.delegate respondsToSelector:@selector(webSocketDidOpen:)]) {
             [self.delegate webSocketDidOpen:self];
         };
@@ -616,7 +647,7 @@ static __strong NSData *CRLFCRLF;
 - (void)_closeWithProtocolError:(NSString *)message;
 {
     // Need to shunt this on the _callbackQueue first to see if they received any messages 
-    [_delegateQueue addOperationWithBlock:^{
+    [self _performDelegateBlock:^{
         [self closeWithCode:SRStatusCodeProtocolError reason:message];
         dispatch_async(_workQueue, ^{
             [self _disconnect];
@@ -629,7 +660,7 @@ static __strong NSData *CRLFCRLF;
     dispatch_async(_workQueue, ^{
         if (self.readyState != SR_CLOSED) {
             _failed = YES;
-            [_delegateQueue addOperationWithBlock:^{
+            [self _performDelegateBlock:^{
                 if ([self.delegate respondsToSelector:@selector(webSocket:didFailWithError:)]) {
                     [self.delegate webSocket:self didFailWithError:error];
                 }
@@ -676,7 +707,7 @@ static __strong NSData *CRLFCRLF;
 - (void)handlePing:(NSData *)pingData;
 {
     // Need to pingpong this off _callbackQueue first to make sure messages happen in order
-    [_delegateQueue addOperationWithBlock:^{
+    [self _performDelegateBlock:^{
         dispatch_async(_workQueue, ^{
             [self _sendFrameWithOpcode:SROpCodePong data:pingData];
         });
@@ -691,7 +722,7 @@ static __strong NSData *CRLFCRLF;
 - (void)_handleMessage:(id)message
 {
     SRFastLog(@"Received message");
-    [_delegateQueue addOperationWithBlock:^{
+    [self _performDelegateBlock:^{
         [self.delegate webSocket:self didReceiveMessage:message];
     }];
 }
@@ -1036,7 +1067,7 @@ static const uint8_t SRPayloadLenMask   = 0x7F;
         [_inputStream close];
         
         if (!_failed) {
-            [_delegateQueue addOperationWithBlock:^{
+            [self _performDelegateBlock:^{
                 if ([self.delegate respondsToSelector:@selector(webSocket:didCloseWithCode:reason:wasClean:)]) {
                     [self.delegate webSocket:self didCloseWithCode:_closeCode reason:_closeReason wasClean:YES];
                 }
@@ -1381,7 +1412,7 @@ static const size_t SRFrameHeaderOverhead = 32;
                     if (!_sentClose && !_failed) {
                         _sentClose = YES;
                         // If we get closed in this state it's probably not clean because we should be sending this when we send messages
-                        [_delegateQueue addOperationWithBlock:^{
+                        [self _performDelegateBlock:^{
                             if ([self.delegate respondsToSelector:@selector(webSocket:didCloseWithCode:reason:wasClean:)]) {
                                 [self.delegate webSocket:self didCloseWithCode:0 reason:@"Stream end encountered" wasClean:NO];
                             }