- (void)run NS_SWIFT_UNAVAILABLE_FROM_ASYNC("run cannot be used from async contexts.");
- (void)runUntilDate:(NSDate *)limitDate NS_SWIFT_UNAVAILABLE_FROM_ASYNC("run(until:) cannot be used from async contexts.");
- (BOOL)runMode:(NSRunLoopMode)mode beforeDate:(NSDate *)limitDate NS_SWIFT_UNAVAILABLE_FROM_ASYNC("run(_:before:) cannot be used from async contexts.");
+ (void)cfstreamThread:(id)unused { @autoreleasepool { [[NSThread currentThread] setName:GCDAsyncSocketThreadName]; LogInfo(@"CFStreamThread: Started"); // We can't run the run loop unless it has an associated input source or a timer. // So we'll just create a timer that will never fire - unless the server runs for decades. [NSTimer scheduledTimerWithTimeInterval:[[NSDate distantFuture] timeIntervalSinceNow] target:self selector:@selector(ignore:) userInfo:nil repeats:YES]; NSThread *currentThread = [NSThread currentThread]; NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop]; BOOL isCancelled = [currentThread isCancelled]; while (!isCancelled && [currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) { isCancelled = [currentThread isCancelled]; } LogInfo(@"CFStreamThread: Stopped"); }}
+ (void)stopCFStreamThreadIfNeeded { LogTrace(); // The creation of the cfstreamThread is relatively expensive. // So we'd like to keep it available for recycling. // However, there's a tradeoff here, because it shouldn't remain alive forever. // So what we're going to do is use a little delay before taking it down. // This way it can be reused properly in situations where multiple sockets are continually in flux. int delayInSeconds = 30; dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); dispatch_after(when, cfstreamThreadSetupQueue, ^{ @autoreleasepool { #pragma clang diagnostic push #pragma clang diagnostic warning"-Wimplicit-retain-self" if (cfstreamThreadRetainCount == 0) { LogWarn(@"Logic error concerning cfstreamThread start / stop"); return_from_block; } if (--cfstreamThreadRetainCount == 0) { [cfstreamThread cancel]; // set isCancelled flag // wake up the thread [[selfclass] performSelector:@selector(ignore:) onThread:cfstreamThread withObject:[NSNull null] waitUntilDone:NO]; cfstreamThread = nil; } #pragma clang diagnostic pop }}); }