aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/objective-c/GRPCClient/private/GRPCChannelPool.m
diff options
context:
space:
mode:
authorGravatar Muxi Yan <mxyan@google.com>2018-12-06 18:26:51 -0800
committerGravatar Muxi Yan <mxyan@google.com>2018-12-06 18:26:51 -0800
commitda759f1fc63ceb0c893bb6027bacfadfda5ab111 (patch)
treee529cda89aaf09bbc91b95505bc0d5fdc615851a /src/objective-c/GRPCClient/private/GRPCChannelPool.m
parentf9e50322bf1d6be736b415831eea44130b9dedfe (diff)
batch fixes
Diffstat (limited to 'src/objective-c/GRPCClient/private/GRPCChannelPool.m')
-rw-r--r--src/objective-c/GRPCClient/private/GRPCChannelPool.m82
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) {