Skip to content
Snippets Groups Projects
Commit cfcaccc6 authored by Jorge Canizales's avatar Jorge Canizales
Browse files

Revert "Revert "Pass a non-infinite deadline to grpc_completion_queue_next()...

Revert "Revert "Pass a non-infinite deadline to grpc_completion_queue_next() to prevent queues from blocking indefinitely in poll()""
parent 180ca863
No related branches found
No related tags found
No related merge requests found
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
typedef void(^GRPCQueueCompletionHandler)(bool success); typedef void(^GRPCQueueCompletionHandler)(bool success);
extern const int64_t kGRPCCompletionQueueDefaultTimeoutSecs;
/** /**
* This class lets one more easily use |grpc_completion_queue|. To use it, pass the value of the * This class lets one more easily use |grpc_completion_queue|. To use it, pass the value of the
* |unmanagedQueue| property of an instance of this class to |grpc_channel_create_call|. Then for * |unmanagedQueue| property of an instance of this class to |grpc_channel_create_call|. Then for
...@@ -49,6 +51,11 @@ typedef void(^GRPCQueueCompletionHandler)(bool success); ...@@ -49,6 +51,11 @@ typedef void(^GRPCQueueCompletionHandler)(bool success);
*/ */
@interface GRPCCompletionQueue : NSObject @interface GRPCCompletionQueue : NSObject
@property(nonatomic, readonly) grpc_completion_queue *unmanagedQueue; @property(nonatomic, readonly) grpc_completion_queue *unmanagedQueue;
@property(nonatomic, readonly) int64_t timeoutSecs;
+ (instancetype)completionQueue; + (instancetype)completionQueue;
- (instancetype)init;
- (instancetype)initWithTimeout:(int64_t)timeoutSecs NS_DESIGNATED_INITIALIZER;
@end @end
...@@ -35,6 +35,9 @@ ...@@ -35,6 +35,9 @@
#import <grpc/grpc.h> #import <grpc/grpc.h>
const int64_t kGRPCCompletionQueueDefaultTimeoutSecs = 60;
@implementation GRPCCompletionQueue @implementation GRPCCompletionQueue
+ (instancetype)completionQueue { + (instancetype)completionQueue {
...@@ -42,8 +45,13 @@ ...@@ -42,8 +45,13 @@
} }
- (instancetype)init { - (instancetype)init {
return [self initWithTimeout:kGRPCCompletionQueueDefaultTimeoutSecs];
}
- (instancetype)initWithTimeout:(int64_t)timeoutSecs {
if ((self = [super init])) { if ((self = [super init])) {
_unmanagedQueue = grpc_completion_queue_create(NULL); _unmanagedQueue = grpc_completion_queue_create(NULL);
_timeoutSecs = timeoutSecs;
// This is for the following block to capture the pointer by value (instead // This is for the following block to capture the pointer by value (instead
// of retaining self and doing self->_unmanagedQueue). This is essential // of retaining self and doing self->_unmanagedQueue). This is essential
...@@ -61,22 +69,28 @@ ...@@ -61,22 +69,28 @@
gDefaultConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); gDefaultConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
}); });
dispatch_async(gDefaultConcurrentQueue, ^{ dispatch_async(gDefaultConcurrentQueue, ^{
// Using a non-infinite deadline to re-enter grpc_completion_queue_next()
// alleviates https://github.com/grpc/grpc/issues/5593
gpr_timespec deadline = (timeoutSecs < 0)
? gpr_inf_future(GPR_CLOCK_REALTIME)
: gpr_time_from_seconds(timeoutSecs, GPR_CLOCK_REALTIME);
while (YES) { while (YES) {
// The following call blocks until an event is available. // The following call blocks until an event is available or the deadline elapses.
grpc_event event = grpc_completion_queue_next(unmanagedQueue, grpc_event event = grpc_completion_queue_next(unmanagedQueue, deadline, NULL);
gpr_inf_future(GPR_CLOCK_REALTIME),
NULL);
GRPCQueueCompletionHandler handler; GRPCQueueCompletionHandler handler;
switch (event.type) { switch (event.type) {
case GRPC_OP_COMPLETE: case GRPC_OP_COMPLETE:
handler = (__bridge_transfer GRPCQueueCompletionHandler)event.tag; handler = (__bridge_transfer GRPCQueueCompletionHandler)event.tag;
handler(event.success); handler(event.success);
break; break;
case GRPC_QUEUE_TIMEOUT:
// Nothing to do here
break;
case GRPC_QUEUE_SHUTDOWN: case GRPC_QUEUE_SHUTDOWN:
grpc_completion_queue_destroy(unmanagedQueue); grpc_completion_queue_destroy(unmanagedQueue);
return; return;
default: default:
[NSException raise:@"Unrecognized completion type" format:@""]; [NSException raise:@"Unrecognized completion type" format:@"type=%d", event.type];
} }
}; };
}); });
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment