aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/objective-c/GRPCClient/GRPCCall.m
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2015-07-20 10:31:12 -0700
committerGravatar Craig Tiller <ctiller@google.com>2015-07-20 10:31:12 -0700
commit9d25e946828592d1e2a8fc51daa685995c771dd2 (patch)
tree5a2ff0898dbececd68defba3799146a003fb1bce /src/objective-c/GRPCClient/GRPCCall.m
parentacd095006f0ec7254223834043e7d8e1b592ef8c (diff)
parentcd329560d33ede65256a926a82279311dcc9b15e (diff)
Merge github.com:grpc/grpc into sometimes-its-good-just-to-check-in-with-each-other
Diffstat (limited to 'src/objective-c/GRPCClient/GRPCCall.m')
-rw-r--r--src/objective-c/GRPCClient/GRPCCall.m32
1 files changed, 22 insertions, 10 deletions
diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m
index 53e5abe177..9435bf2b35 100644
--- a/src/objective-c/GRPCClient/GRPCCall.m
+++ b/src/objective-c/GRPCClient/GRPCCall.m
@@ -35,10 +35,10 @@
#include <grpc/grpc.h>
#include <grpc/support/time.h>
+#import <RxLibrary/GRXConcurrentWriteable.h>
#import "private/GRPCChannel.h"
#import "private/GRPCCompletionQueue.h"
-#import "private/GRPCDelegateWrapper.h"
#import "private/GRPCWrappedCall.h"
#import "private/NSData+GRPC.h"
#import "private/NSDictionary+GRPC.h"
@@ -78,9 +78,13 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey";
// do. Particularly, in the face of errors, there's no ordering guarantee at
// all. This wrapper over our actual writeable ensures thread-safety and
// correct ordering.
- GRPCDelegateWrapper *_responseWriteable;
+ GRXConcurrentWriteable *_responseWriteable;
GRXWriter *_requestWriter;
+ // To create a retain cycle when a call is started, up until it finishes. See
+ // |startWithWriteable:| and |finishWithError:|.
+ GRPCCall *_self;
+
NSMutableDictionary *_requestMetadata;
NSMutableDictionary *_responseMetadata;
}
@@ -143,8 +147,13 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey";
#pragma mark Finish
- (void)finishWithError:(NSError *)errorOrNil {
+ // If the call isn't retained anywhere else, it can be deallocated now.
+ _self = nil;
+
+ // If there were still request messages coming, stop them.
_requestWriter.state = GRXWriterStateFinished;
_requestWriter = nil;
+
if (errorOrNil) {
[_responseWriteable cancelWithError:errorOrNil];
} else {
@@ -191,7 +200,7 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey";
return;
}
__weak GRPCCall *weakSelf = self;
- __weak GRPCDelegateWrapper *weakWriteable = _responseWriteable;
+ __weak GRXConcurrentWriteable *weakWriteable = _responseWriteable;
dispatch_async(_callQueue, ^{
[weakSelf startReadWithHandler:^(grpc_byte_buffer *message) {
@@ -216,7 +225,7 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey";
[weakSelf cancelCall];
return;
}
- [weakWriteable enqueueMessage:data completionHandler:^{
+ [weakWriteable enqueueValue:data completionHandler:^{
[weakSelf startNextRead];
}];
}];
@@ -276,6 +285,7 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey";
}
- (void)writesFinishedWithError:(NSError *)errorOrNil {
+ _requestWriter = nil;
if (errorOrNil) {
[self cancel];
} else {
@@ -335,12 +345,14 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey";
#pragma mark GRXWriter implementation
- (void)startWithWriteable:(id<GRXWriteable>)writeable {
- // The following produces a retain cycle self:_responseWriteable:self, which is only
- // broken when writesFinishedWithError: is sent to the wrapped writeable.
- // Care is taken not to retain self strongly in any of the blocks used in
- // the implementation of GRPCCall, so that the life of the instance is
- // determined by this retain cycle.
- _responseWriteable = [[GRPCDelegateWrapper alloc] initWithWriteable:writeable writer:self];
+ // Create a retain cycle so that this instance lives until the RPC finishes (or is cancelled).
+ // This makes RPCs in which the call isn't externally retained possible (as long as it is started
+ // before being autoreleased).
+ // Care is taken not to retain self strongly in any of the blocks used in this implementation, so
+ // that the life of the instance is determined by this retain cycle.
+ _self = self;
+
+ _responseWriteable = [[GRXConcurrentWriteable alloc] initWithWriteable:writeable];
[self sendHeaders:_requestMetadata];
[self invokeCall];
}