diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 377900fd9e1..1d7fb421e5e 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -66,6 +66,12 @@ static GRPCChannelPool *gChannelPool; BOOL _disconnected; dispatch_queue_t _dispatchQueue; dispatch_queue_t _timerQueue; + + /** + * Date and time when last timer is scheduled. When a timer is fired, if + * _lastDispatch + _destroyDelay < now, it can be determined that another timer is scheduled after + * schedule of the current timer, hence the current one should be discarded. + */ NSDate *_lastDispatch; } @@ -107,11 +113,12 @@ static GRPCChannelPool *gChannelPool; if (!self->_disconnected) { self->_refCount--; if (self->_refCount == 0) { - self->_lastDispatch = [NSDate date]; + NSDate *now = [NSDate date]; + self->_lastDispatch = now; dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)self->_destroyDelay * NSEC_PER_SEC); dispatch_after(delay, self->_timerQueue, ^{ - [self timerFire]; + [self timerFireWithScheduleDate:now]; }); } } @@ -129,10 +136,9 @@ static GRPCChannelPool *gChannelPool; }); } -- (void)timerFire { +- (void)timerFireWithScheduleDate:(NSDate *)scheduleDate { dispatch_async(_dispatchQueue, ^{ - if (self->_disconnected || self->_lastDispatch == nil || - -[self->_lastDispatch timeIntervalSinceNow] < -self->_destroyDelay) { + if (self->_disconnected || self->_lastDispatch != scheduleDate) { return; } self->_lastDispatch = nil;