|  | @@ -91,13 +91,9 @@ typedef struct gprcsharp_batch_context {
 | 
	
		
			
				|  |  |      grpc_call_details call_details;
 | 
	
		
			
				|  |  |      grpc_metadata_array request_metadata;
 | 
	
		
			
				|  |  |    } server_rpc_new;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /* callback will be called upon completion */
 | 
	
		
			
				|  |  | -  callback_funcptr callback;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  } grpcsharp_batch_context;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -grpcsharp_batch_context *grpcsharp_batch_context_create() {
 | 
	
		
			
				|  |  | +GPR_EXPORT grpcsharp_batch_context *GPR_CALLTYPE grpcsharp_batch_context_create() {
 | 
	
		
			
				|  |  |    grpcsharp_batch_context *ctx = gpr_malloc(sizeof(grpcsharp_batch_context));
 | 
	
		
			
				|  |  |    memset(ctx, 0, sizeof(grpcsharp_batch_context));
 | 
	
		
			
				|  |  |    return ctx;
 | 
	
	
		
			
				|  | @@ -192,7 +188,7 @@ void grpcsharp_metadata_array_move(grpc_metadata_array *dest,
 | 
	
		
			
				|  |  |    src->metadata = NULL;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void grpcsharp_batch_context_destroy(grpcsharp_batch_context *ctx) {
 | 
	
		
			
				|  |  | +GPR_EXPORT void GPR_CALLTYPE grpcsharp_batch_context_destroy(grpcsharp_batch_context *ctx) {
 | 
	
		
			
				|  |  |    if (!ctx) {
 | 
	
		
			
				|  |  |      return;
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -306,25 +302,14 @@ grpcsharp_completion_queue_destroy(grpc_completion_queue *cq) {
 | 
	
		
			
				|  |  |    grpc_completion_queue_destroy(cq);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -GPR_EXPORT grpc_completion_type GPR_CALLTYPE
 | 
	
		
			
				|  |  | -grpcsharp_completion_queue_next_with_callback(grpc_completion_queue *cq) {
 | 
	
		
			
				|  |  | -  grpc_event ev;
 | 
	
		
			
				|  |  | -  grpcsharp_batch_context *batch_context;
 | 
	
		
			
				|  |  | -  grpc_completion_type t;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  ev = grpc_completion_queue_next(cq, gpr_inf_future);
 | 
	
		
			
				|  |  | -  t = ev.type;
 | 
	
		
			
				|  |  | -  if (t == GRPC_OP_COMPLETE && ev.tag) {
 | 
	
		
			
				|  |  | -    /* NEW API handler */
 | 
	
		
			
				|  |  | -    batch_context = (grpcsharp_batch_context *)ev.tag;
 | 
	
		
			
				|  |  | -    batch_context->callback((gpr_int32) ev.success, batch_context);
 | 
	
		
			
				|  |  | -    grpcsharp_batch_context_destroy(batch_context);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +GPR_EXPORT grpc_event GPR_CALLTYPE
 | 
	
		
			
				|  |  | +grpcsharp_completion_queue_next(grpc_completion_queue *cq) {
 | 
	
		
			
				|  |  | +  return grpc_completion_queue_next(cq, gpr_inf_future);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  /* return completion type to allow some handling for events that have no
 | 
	
		
			
				|  |  | -   * tag - such as GRPC_QUEUE_SHUTDOWN
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -  return t;
 | 
	
		
			
				|  |  | +GPR_EXPORT grpc_event GPR_CALLTYPE
 | 
	
		
			
				|  |  | +grpcsharp_completion_queue_pluck(grpc_completion_queue *cq, void *tag) {
 | 
	
		
			
				|  |  | +  return grpc_completion_queue_pluck(cq, tag, gpr_inf_future);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /* Channel */
 | 
	
	
		
			
				|  | @@ -413,14 +398,11 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_destroy(grpc_call *call) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  GPR_EXPORT grpc_call_error GPR_CALLTYPE
 | 
	
		
			
				|  |  | -grpcsharp_call_start_unary(grpc_call *call, callback_funcptr callback,
 | 
	
		
			
				|  |  | +grpcsharp_call_start_unary(grpc_call *call, grpcsharp_batch_context *ctx,
 | 
	
		
			
				|  |  |                             const char *send_buffer, size_t send_buffer_len,
 | 
	
		
			
				|  |  |                             grpc_metadata_array *initial_metadata) {
 | 
	
		
			
				|  |  |    /* TODO: don't use magic number */
 | 
	
		
			
				|  |  |    grpc_op ops[6];
 | 
	
		
			
				|  |  | -  grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
 | 
	
		
			
				|  |  | -  ctx->callback = callback;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
 | 
	
		
			
				|  |  |    grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
 | 
	
		
			
				|  |  |                                  initial_metadata);
 | 
	
	
		
			
				|  | @@ -454,34 +436,12 @@ grpcsharp_call_start_unary(grpc_call *call, callback_funcptr callback,
 | 
	
		
			
				|  |  |    return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/* Synchronous unary call */
 | 
	
		
			
				|  |  | -GPR_EXPORT void GPR_CALLTYPE
 | 
	
		
			
				|  |  | -grpcsharp_call_blocking_unary(grpc_call *call,
 | 
	
		
			
				|  |  | -                              grpc_completion_queue *dedicated_cq,
 | 
	
		
			
				|  |  | -                              callback_funcptr callback,
 | 
	
		
			
				|  |  | -                              const char *send_buffer, size_t send_buffer_len,
 | 
	
		
			
				|  |  | -                              grpc_metadata_array *initial_metadata) {
 | 
	
		
			
				|  |  | -  GPR_ASSERT(grpcsharp_call_start_unary(call, callback, send_buffer,
 | 
	
		
			
				|  |  | -                                        send_buffer_len,
 | 
	
		
			
				|  |  | -                                        initial_metadata) == GRPC_CALL_OK);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /* TODO: we would like to use pluck, but we don't know the tag */
 | 
	
		
			
				|  |  | -  GPR_ASSERT(grpcsharp_completion_queue_next_with_callback(dedicated_cq) ==
 | 
	
		
			
				|  |  | -             GRPC_OP_COMPLETE);
 | 
	
		
			
				|  |  | -  grpc_completion_queue_shutdown(dedicated_cq);
 | 
	
		
			
				|  |  | -  GPR_ASSERT(grpcsharp_completion_queue_next_with_callback(dedicated_cq) ==
 | 
	
		
			
				|  |  | -             GRPC_QUEUE_SHUTDOWN);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  GPR_EXPORT grpc_call_error GPR_CALLTYPE
 | 
	
		
			
				|  |  |  grpcsharp_call_start_client_streaming(grpc_call *call,
 | 
	
		
			
				|  |  | -                                      callback_funcptr callback,
 | 
	
		
			
				|  |  | +                                      grpcsharp_batch_context *ctx,
 | 
	
		
			
				|  |  |                                        grpc_metadata_array *initial_metadata) {
 | 
	
		
			
				|  |  |    /* TODO: don't use magic number */
 | 
	
		
			
				|  |  |    grpc_op ops[4];
 | 
	
		
			
				|  |  | -  grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
 | 
	
		
			
				|  |  | -  ctx->callback = callback;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
 | 
	
		
			
				|  |  |    grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
 | 
	
		
			
				|  |  |                                  initial_metadata);
 | 
	
	
		
			
				|  | @@ -510,13 +470,10 @@ grpcsharp_call_start_client_streaming(grpc_call *call,
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming(
 | 
	
		
			
				|  |  | -    grpc_call *call, callback_funcptr callback, const char *send_buffer,
 | 
	
		
			
				|  |  | +    grpc_call *call, grpcsharp_batch_context *ctx, const char *send_buffer,
 | 
	
		
			
				|  |  |      size_t send_buffer_len, grpc_metadata_array *initial_metadata) {
 | 
	
		
			
				|  |  |    /* TODO: don't use magic number */
 | 
	
		
			
				|  |  |    grpc_op ops[5];
 | 
	
		
			
				|  |  | -  grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
 | 
	
		
			
				|  |  | -  ctx->callback = callback;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
 | 
	
		
			
				|  |  |    grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
 | 
	
		
			
				|  |  |                                  initial_metadata);
 | 
	
	
		
			
				|  | @@ -549,13 +506,10 @@ GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming(
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  GPR_EXPORT grpc_call_error GPR_CALLTYPE
 | 
	
		
			
				|  |  |  grpcsharp_call_start_duplex_streaming(grpc_call *call,
 | 
	
		
			
				|  |  | -                                      callback_funcptr callback,
 | 
	
		
			
				|  |  | +                                      grpcsharp_batch_context *ctx,
 | 
	
		
			
				|  |  |                                        grpc_metadata_array *initial_metadata) {
 | 
	
		
			
				|  |  |    /* TODO: don't use magic number */
 | 
	
		
			
				|  |  |    grpc_op ops[3];
 | 
	
		
			
				|  |  | -  grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
 | 
	
		
			
				|  |  | -  ctx->callback = callback;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
 | 
	
		
			
				|  |  |    grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
 | 
	
		
			
				|  |  |                                  initial_metadata);
 | 
	
	
		
			
				|  | @@ -581,13 +535,10 @@ grpcsharp_call_start_duplex_streaming(grpc_call *call,
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  GPR_EXPORT grpc_call_error GPR_CALLTYPE
 | 
	
		
			
				|  |  | -grpcsharp_call_send_message(grpc_call *call, callback_funcptr callback,
 | 
	
		
			
				|  |  | +grpcsharp_call_send_message(grpc_call *call, grpcsharp_batch_context *ctx,
 | 
	
		
			
				|  |  |                              const char *send_buffer, size_t send_buffer_len) {
 | 
	
		
			
				|  |  |    /* TODO: don't use magic number */
 | 
	
		
			
				|  |  |    grpc_op ops[1];
 | 
	
		
			
				|  |  | -  grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
 | 
	
		
			
				|  |  | -  ctx->callback = callback;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    ops[0].op = GRPC_OP_SEND_MESSAGE;
 | 
	
		
			
				|  |  |    ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len);
 | 
	
		
			
				|  |  |    ops[0].data.send_message = ctx->send_message;
 | 
	
	
		
			
				|  | @@ -597,12 +548,9 @@ grpcsharp_call_send_message(grpc_call *call, callback_funcptr callback,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  GPR_EXPORT grpc_call_error GPR_CALLTYPE
 | 
	
		
			
				|  |  |  grpcsharp_call_send_close_from_client(grpc_call *call,
 | 
	
		
			
				|  |  | -                                      callback_funcptr callback) {
 | 
	
		
			
				|  |  | +                                      grpcsharp_batch_context *ctx) {
 | 
	
		
			
				|  |  |    /* TODO: don't use magic number */
 | 
	
		
			
				|  |  |    grpc_op ops[1];
 | 
	
		
			
				|  |  | -  grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
 | 
	
		
			
				|  |  | -  ctx->callback = callback;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    ops[0].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx);
 | 
	
	
		
			
				|  | @@ -610,14 +558,11 @@ grpcsharp_call_send_close_from_client(grpc_call *call,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  GPR_EXPORT grpc_call_error GPR_CALLTYPE
 | 
	
		
			
				|  |  |  grpcsharp_call_send_status_from_server(grpc_call *call,
 | 
	
		
			
				|  |  | -                                       callback_funcptr callback,
 | 
	
		
			
				|  |  | +                                       grpcsharp_batch_context *ctx,
 | 
	
		
			
				|  |  |                                         grpc_status_code status_code,
 | 
	
		
			
				|  |  |                                         const char *status_details) {
 | 
	
		
			
				|  |  |    /* TODO: don't use magic number */
 | 
	
		
			
				|  |  |    grpc_op ops[1];
 | 
	
		
			
				|  |  | -  grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
 | 
	
		
			
				|  |  | -  ctx->callback = callback;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    ops[0].op = GRPC_OP_SEND_STATUS_FROM_SERVER;
 | 
	
		
			
				|  |  |    ops[0].data.send_status_from_server.status = status_code;
 | 
	
		
			
				|  |  |    ops[0].data.send_status_from_server.status_details =
 | 
	
	
		
			
				|  | @@ -629,25 +574,18 @@ grpcsharp_call_send_status_from_server(grpc_call *call,
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  GPR_EXPORT grpc_call_error GPR_CALLTYPE
 | 
	
		
			
				|  |  | -grpcsharp_call_recv_message(grpc_call *call, callback_funcptr callback) {
 | 
	
		
			
				|  |  | +grpcsharp_call_recv_message(grpc_call *call, grpcsharp_batch_context *ctx) {
 | 
	
		
			
				|  |  |    /* TODO: don't use magic number */
 | 
	
		
			
				|  |  |    grpc_op ops[1];
 | 
	
		
			
				|  |  | -  grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
 | 
	
		
			
				|  |  | -  ctx->callback = callback;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    ops[0].op = GRPC_OP_RECV_MESSAGE;
 | 
	
		
			
				|  |  |    ops[0].data.recv_message = &(ctx->recv_message);
 | 
	
		
			
				|  |  |    return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  GPR_EXPORT grpc_call_error GPR_CALLTYPE
 | 
	
		
			
				|  |  | -grpcsharp_call_start_serverside(grpc_call *call, callback_funcptr callback) {
 | 
	
		
			
				|  |  | +grpcsharp_call_start_serverside(grpc_call *call, grpcsharp_batch_context *ctx) {
 | 
	
		
			
				|  |  |    /* TODO: don't use magic number */
 | 
	
		
			
				|  |  |    grpc_op ops[2];
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
 | 
	
		
			
				|  |  | -  ctx->callback = callback;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
 | 
	
		
			
				|  |  |    ops[0].data.send_initial_metadata.count = 0;
 | 
	
		
			
				|  |  |    ops[0].data.send_initial_metadata.metadata = NULL;
 | 
	
	
		
			
				|  | @@ -684,9 +622,7 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_shutdown(grpc_server *server) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  GPR_EXPORT void GPR_CALLTYPE
 | 
	
		
			
				|  |  |  grpcsharp_server_shutdown_and_notify_callback(grpc_server *server,
 | 
	
		
			
				|  |  | -                                              callback_funcptr callback) {
 | 
	
		
			
				|  |  | -  grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
 | 
	
		
			
				|  |  | -  ctx->callback = callback;
 | 
	
		
			
				|  |  | +                                              grpcsharp_batch_context *ctx) {
 | 
	
		
			
				|  |  |    grpc_server_shutdown_and_notify(server, ctx);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -696,10 +632,7 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_destroy(grpc_server *server) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  GPR_EXPORT grpc_call_error GPR_CALLTYPE
 | 
	
		
			
				|  |  |  grpcsharp_server_request_call(grpc_server *server, grpc_completion_queue *cq,
 | 
	
		
			
				|  |  | -                              callback_funcptr callback) {
 | 
	
		
			
				|  |  | -  grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
 | 
	
		
			
				|  |  | -  ctx->callback = callback;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +                              grpcsharp_batch_context *ctx) {
 | 
	
		
			
				|  |  |    return grpc_server_request_call(
 | 
	
		
			
				|  |  |        server, &(ctx->server_rpc_new.call), &(ctx->server_rpc_new.call_details),
 | 
	
		
			
				|  |  |        &(ctx->server_rpc_new.request_metadata), cq, cq, ctx);
 | 
	
	
		
			
				|  | @@ -796,3 +729,8 @@ grpcsharp_test_callback(callback_funcptr callback) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /* For testing */
 | 
	
		
			
				|  |  |  GPR_EXPORT void *GPR_CALLTYPE grpcsharp_test_nop(void *ptr) { return ptr; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* For testing */
 | 
	
		
			
				|  |  | +GPR_EXPORT gpr_int32 GPR_CALLTYPE grpcsharp_sizeof_grpc_event(void) {
 | 
	
		
			
				|  |  | +  return sizeof(grpc_event);
 | 
	
		
			
				|  |  | +}
 |