Better use of strong/weak ref to self in GRPCCall

pull/14529/head
Muxi Yan 7 years ago
parent 5739d34c46
commit 55ea27160e
  1. 87
      src/objective-c/GRPCClient/GRPCCall.m

@ -250,11 +250,13 @@ static NSString * const kBearerPrefix = @"Bearer ";
if (self.state == GRXWriterStatePaused) { if (self.state == GRXWriterStatePaused) {
return; return;
} }
__weak GRPCCall *weakSelf = self;
__weak GRXConcurrentWriteable *weakWriteable = _responseWriteable;
dispatch_async(_callQueue, ^{ dispatch_async(_callQueue, ^{
[weakSelf startReadWithHandler:^(grpc_byte_buffer *message) { __weak GRPCCall *weakSelf = self;
__weak GRXConcurrentWriteable *weakWriteable = self->_responseWriteable;
[self startReadWithHandler:^(grpc_byte_buffer *message) {
__strong GRPCCall *strongSelf = weakSelf;
__strong GRXConcurrentWriteable *strongWriteable = weakWriteable;
if (message == NULL) { if (message == NULL) {
// No more messages from the server // No more messages from the server
return; return;
@ -266,14 +268,14 @@ static NSString * const kBearerPrefix = @"Bearer ";
// don't want to throw, because the app shouldn't crash for a behavior // don't want to throw, because the app shouldn't crash for a behavior
// that's on the hands of any server to have. Instead we finish and ask // that's on the hands of any server to have. Instead we finish and ask
// the server to cancel. // the server to cancel.
[weakSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain [strongSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
code:GRPCErrorCodeResourceExhausted code:GRPCErrorCodeResourceExhausted
userInfo:@{NSLocalizedDescriptionKey: @"Client does not have enough memory to hold the server response."}]]; userInfo:@{NSLocalizedDescriptionKey: @"Client does not have enough memory to hold the server response."}]];
[weakSelf cancelCall]; [strongSelf cancelCall];
return; return;
} }
[weakWriteable enqueueValue:data completionHandler:^{ [strongWriteable enqueueValue:data completionHandler:^{
[weakSelf startNextRead]; [strongSelf startNextRead];
}]; }];
}]; }];
}); });
@ -333,12 +335,15 @@ static NSString * const kBearerPrefix = @"Bearer ";
_requestWriter.state = GRXWriterStatePaused; _requestWriter.state = GRXWriterStatePaused;
} }
__weak GRPCCall *weakSelf = self;
dispatch_async(_callQueue, ^{ dispatch_async(_callQueue, ^{
[weakSelf writeMessage:value withErrorHandler:^{ __weak GRPCCall *weakSelf = self;
[weakSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain [self writeMessage:value withErrorHandler:^{
code:GRPCErrorCodeInternal __strong GRPCCall *strongSelf = weakSelf;
userInfo:nil]]; if (strongSelf != nil) {
[strongSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
code:GRPCErrorCodeInternal
userInfo:nil]];
}
}]; }];
}); });
} }
@ -360,12 +365,13 @@ static NSString * const kBearerPrefix = @"Bearer ";
if (errorOrNil) { if (errorOrNil) {
[self cancel]; [self cancel];
} else { } else {
__weak GRPCCall *weakSelf = self;
dispatch_async(_callQueue, ^{ dispatch_async(_callQueue, ^{
[weakSelf finishRequestWithErrorHandler:^{ __weak GRPCCall *weakSelf = self;
[weakSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain [self finishRequestWithErrorHandler:^{
code:GRPCErrorCodeInternal __strong GRPCCall *strongSelf = weakSelf;
userInfo:nil]]; [strongSelf finishWithError:[NSError errorWithDomain:kGRPCErrorDomain
code:GRPCErrorCodeInternal
userInfo:nil]];
}]; }];
}); });
} }
@ -387,30 +393,37 @@ static NSString * const kBearerPrefix = @"Bearer ";
} }
- (void)invokeCall { - (void)invokeCall {
__weak GRPCCall *weakSelf = self;
[self invokeCallWithHeadersHandler:^(NSDictionary *headers) { [self invokeCallWithHeadersHandler:^(NSDictionary *headers) {
// Response headers received. // Response headers received.
self.responseHeaders = headers; __strong GRPCCall *strongSelf = weakSelf;
[self startNextRead]; if (strongSelf) {
strongSelf.responseHeaders = headers;
[strongSelf startNextRead];
}
} completionHandler:^(NSError *error, NSDictionary *trailers) { } completionHandler:^(NSError *error, NSDictionary *trailers) {
self.responseTrailers = trailers; __strong GRPCCall *strongSelf = weakSelf;
if (strongSelf) {
strongSelf.responseTrailers = trailers;
if (error) { if (error) {
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
if (error.userInfo) { if (error.userInfo) {
[userInfo addEntriesFromDictionary:error.userInfo]; [userInfo addEntriesFromDictionary:error.userInfo];
} }
userInfo[kGRPCTrailersKey] = self.responseTrailers; userInfo[kGRPCTrailersKey] = strongSelf.responseTrailers;
// TODO(jcanizales): The C gRPC library doesn't guarantee that the headers block will be // TODO(jcanizales): The C gRPC library doesn't guarantee that the headers block will be
// called before this one, so an error might end up with trailers but no headers. We // called before this one, so an error might end up with trailers but no headers. We
// shouldn't call finishWithError until ater both blocks are called. It is also when this is // shouldn't call finishWithError until ater both blocks are called. It is also when this is
// done that we can provide a merged view of response headers and trailers in a thread-safe // done that we can provide a merged view of response headers and trailers in a thread-safe
// way. // way.
if (self.responseHeaders) { if (strongSelf.responseHeaders) {
userInfo[kGRPCHeadersKey] = self.responseHeaders; userInfo[kGRPCHeadersKey] = strongSelf.responseHeaders;
}
error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo];
} }
error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo]; [strongSelf finishWithError:error];
} }
[self finishWithError:error];
}]; }];
// Now that the RPC has been initiated, request writes can start. // Now that the RPC has been initiated, request writes can start.
@synchronized(_requestWriter) { @synchronized(_requestWriter) {

Loading…
Cancel
Save