diff options
author | Muxi Yan <mxyan@google.com> | 2018-12-06 18:26:51 -0800 |
---|---|---|
committer | Muxi Yan <mxyan@google.com> | 2018-12-06 18:26:51 -0800 |
commit | da759f1fc63ceb0c893bb6027bacfadfda5ab111 (patch) | |
tree | e529cda89aaf09bbc91b95505bc0d5fdc615851a /src/objective-c/GRPCClient/private/GRPCChannelPool.m | |
parent | f9e50322bf1d6be736b415831eea44130b9dedfe (diff) |
batch fixes
Diffstat (limited to 'src/objective-c/GRPCClient/private/GRPCChannelPool.m')
-rw-r--r-- | src/objective-c/GRPCClient/private/GRPCChannelPool.m | 82 |
1 files changed, 43 insertions, 39 deletions
diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 349bdd44a6..17c74e558b 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -27,7 +27,6 @@ #import "GRPCCronetChannelFactory.h" #import "GRPCInsecureChannelFactory.h" #import "GRPCSecureChannelFactory.h" -#import "utilities.h" #import "version.h" #import "GRPCWrappedCall.h" #import "GRPCCompletionQueue.h" @@ -57,6 +56,34 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; return [self initWithChannelConfiguration:channelConfiguration destroyDelay:kDefaultChannelDestroyDelay]; } +- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration + destroyDelay:(NSTimeInterval)destroyDelay { + NSAssert(channelConfiguration != nil, @"channelConfiguration cannot be empty."); + if (channelConfiguration == nil) { + return nil; + } + + if ((self = [super init])) { + _channelConfiguration = [channelConfiguration copy]; + _destroyDelay = destroyDelay; + _wrappedCalls = [NSHashTable weakObjectsHashTable]; + _wrappedChannel = nil; + _lastTimedDestroy = nil; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 + if (@available(iOS 8.0, macOS 10.10, *)) { + _timerQueue = dispatch_queue_create(NULL, + dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); + } else { +#else + { +#endif + _timerQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + } + } + + return self; +} + - (void)dealloc { // Disconnect GRPCWrappedCall objects created but not yet removed if (_wrappedCalls.allObjects.count != 0) { @@ -67,12 +94,14 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; } - (GRPCWrappedCall *)wrappedCallWithPath:(NSString *)path -completionQueue:(GRPCCompletionQueue *)queue -callOptions:(GRPCCallOptions *)callOptions { + completionQueue:(GRPCCompletionQueue *)queue + callOptions:(GRPCCallOptions *)callOptions { NSAssert(path.length > 0, @"path must not be empty."); NSAssert(queue != nil, @"completionQueue must not be empty."); NSAssert(callOptions, @"callOptions must not be empty."); - if (path.length == 0 || queue == nil || callOptions == nil) return nil; + if (path.length == 0 || queue == nil || callOptions == nil) { + return nil; + } GRPCWrappedCall *call = nil; @@ -97,6 +126,7 @@ callOptions:(GRPCCallOptions *)callOptions { call = [[GRPCWrappedCall alloc] initWithUnmanagedCall:unmanagedCall pooledChannel:self]; if (call == nil) { NSAssert(call != nil, @"Unable to create GRPCWrappedCall object"); + grpc_call_unref(unmanagedCall); return nil; } @@ -111,16 +141,22 @@ callOptions:(GRPCCallOptions *)callOptions { return; } @synchronized(self) { - // Detect if all objects weakly referenced in _wrappedCalls are (implicitly) removed. In such - // case the channel is no longer referenced by a grpc_call object and can be destroyed after - // a certain delay. + // Detect if all objects weakly referenced in _wrappedCalls are (implicitly) removed. + // _wrappedCalls.count does not work here since the hash table may include deallocated weak + // references. _wrappedCalls.allObjects forces removal of those objects. if (_wrappedCalls.allObjects.count == 0) { + // No more call has reference to this channel. We may start the timer for destroying the + // channel now. NSDate *now = [NSDate date]; NSAssert(now != nil, @"Unable to create NSDate object 'now'."); _lastTimedDestroy = now; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)_destroyDelay * NSEC_PER_SEC), _timerQueue, ^{ @synchronized(self) { + // Check _lastTimedDestroy against now in case more calls are created (and + // maybe destroyed) after this dispatch_async. In that case the current + // dispatch_after block should be discarded; the channel should be + // destroyed in a later dispatch_after block. if (now != nil && self->_lastTimedDestroy == now) { self->_wrappedChannel = nil; self->_lastTimedDestroy = nil; @@ -145,38 +181,6 @@ callOptions:(GRPCCallOptions *)callOptions { } } -@end - -@implementation GRPCPooledChannel (Test) - -- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration - destroyDelay:(NSTimeInterval)destroyDelay { - NSAssert(channelConfiguration != nil, @"channelConfiguration cannot be empty."); - if (channelConfiguration == nil) { - return nil; - } - - if ((self = [super init])) { - _channelConfiguration = [channelConfiguration copy]; - _destroyDelay = destroyDelay; - _wrappedCalls = [NSHashTable weakObjectsHashTable]; - _wrappedChannel = nil; - _lastTimedDestroy = nil; -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 - if (@available(iOS 8.0, macOS 10.10, *)) { - _timerQueue = dispatch_queue_create(NULL, - dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); - } else { -#else - { -#endif - _timerQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); - } - } - - return self; -} - - (GRPCChannel *)wrappedChannel { GRPCChannel *channel = nil; @synchronized(self) { |