diff options
author | Muxi Yan <mxyan@google.com> | 2018-10-18 10:39:48 -0700 |
---|---|---|
committer | Muxi Yan <mxyan@google.com> | 2018-10-18 10:39:48 -0700 |
commit | ac211b4214b9a5bbc00631b61af396557837b9fb (patch) | |
tree | 9885c89cef28b568f53cecdd5e1094c5f7bf3258 /src/objective-c/GRPCClient/private/GRPCChannel.m | |
parent | 67a4eb6623d0870992051d0280b78dd7a2b2c0ff (diff) |
Use dispatch_after for delayed destroy of channel
Diffstat (limited to 'src/objective-c/GRPCClient/private/GRPCChannel.m')
-rw-r--r-- | src/objective-c/GRPCClient/private/GRPCChannel.m | 87 |
1 files changed, 47 insertions, 40 deletions
diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index a17cc253fe..a91949684c 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -57,14 +57,13 @@ NSTimeInterval kChannelDestroyDelay = 30; @implementation GRPCChannelRef { NSTimeInterval _destroyDelay; - // We use dispatch queue for this purpose since timer invalidation must happen on the same - // thread which issued the timer. - dispatch_queue_t _dispatchQueue; void (^_destroyChannelCallback)(); NSUInteger _refCount; - NSTimer *_timer; BOOL _disconnected; + dispatch_queue_t _dispatchQueue; + dispatch_queue_t _timerQueue; + NSDate *_lastDispatch; } - (instancetype)initWithDestroyDelay:(NSTimeInterval)destroyDelay @@ -74,57 +73,65 @@ NSTimeInterval kChannelDestroyDelay = 30; _destroyChannelCallback = destroyChannelCallback; _refCount = 1; - _timer = nil; _disconnected = NO; + if (@available(iOS 8.0, *)) { + _dispatchQueue = dispatch_queue_create(NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); + _timerQueue = dispatch_queue_create(NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_DEFAULT, -1)); + } else { + _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + _timerQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT); + } + _lastDispatch = nil; } return self; } -// This function is protected by channel dispatch queue. - (void)refChannel { - if (!_disconnected) { - _refCount++; - [_timer invalidate]; - _timer = nil; - } + dispatch_async(_dispatchQueue, ^{ + if (!self->_disconnected) { + self->_refCount++; + self->_lastDispatch = nil; + } + }); } -// This function is protected by channel dispatch queue. - (void)unrefChannel { - if (!_disconnected) { - _refCount--; - if (_refCount == 0) { - [_timer invalidate]; - _timer = [NSTimer scheduledTimerWithTimeInterval:_destroyDelay - target:self - selector:@selector(timerFire:) - userInfo:nil - repeats:NO]; + dispatch_async(_dispatchQueue, ^{ + if (!self->_disconnected) { + self->_refCount--; + if (self->_refCount == 0) { + self->_lastDispatch = [NSDate date]; + dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)kChannelDestroyDelay * 1e9); + dispatch_after(delay, self->_timerQueue, ^{ + [self timerFire]; + }); + } } - } + }); } -// This function is protected by channel dispatch queue. - (void)disconnect { - if (!_disconnected) { - [_timer invalidate]; - _timer = nil; - _disconnected = YES; - // Break retain loop - _destroyChannelCallback = nil; - } + dispatch_async(_dispatchQueue, ^{ + if (!self->_disconnected) { + self->_lastDispatch = nil; + self->_disconnected = YES; + // Break retain loop + self->_destroyChannelCallback = nil; + } + }); } -// This function is protected by channel dispatch queue. -- (void)timerFire:(NSTimer *)timer { - if (_disconnected || _timer == nil || _timer != timer) { - return; - } - _timer = nil; - _destroyChannelCallback(); - // Break retain loop - _destroyChannelCallback = nil; - _disconnected = YES; +- (void)timerFire { + dispatch_async(_dispatchQueue, ^{ + if (self->_disconnected || self->_lastDispatch == nil || -[self->_lastDispatch timeIntervalSinceNow] < -kChannelDestroyDelay) { + return; + } + self->_lastDispatch = nil; + self->_disconnected = YES; + self->_destroyChannelCallback(); + // Break retain loop + self->_destroyChannelCallback = nil; + }); } @end |