// // Copyright 2012 Square Inc. // Portions Copyright (c) 2016-present, Facebook, Inc. // // All rights reserved. // // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. An additional grant // of patent rights can be found in the PATENTS file in the same directory. // #import "SRRunLoopThread.h" @interface SRRunLoopThread () { dispatch_group_t _waitGroup; } @property (nonatomic, strong, readwrite) NSRunLoop *runLoop; @end @implementation SRRunLoopThread + (instancetype)sharedThread { static SRRunLoopThread *thread; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ thread = [[SRRunLoopThread alloc] init]; thread.name = @"com.facebook.SocketRocket.NetworkThread"; [thread start]; }); return thread; } - (instancetype)init { self = [super init]; if (self) { _waitGroup = dispatch_group_create(); dispatch_group_enter(_waitGroup); } return self; } - (void)main { @autoreleasepool { _runLoop = [NSRunLoop currentRunLoop]; dispatch_group_leave(_waitGroup); // Add an empty run loop source to prevent runloop from spinning. CFRunLoopSourceContext sourceCtx = { .version = 0, .info = NULL, .retain = NULL, .release = NULL, .copyDescription = NULL, .equal = NULL, .hash = NULL, .schedule = NULL, .cancel = NULL, .perform = NULL }; CFRunLoopSourceRef source = CFRunLoopSourceCreate(NULL, 0, &sourceCtx); CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode); CFRelease(source); while ([_runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) { } assert(NO); } } - (NSRunLoop *)runLoop; { dispatch_group_wait(_waitGroup, DISPATCH_TIME_FOREVER); return _runLoop; } @end