aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/surface/call.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/surface/call.c')
-rw-r--r--src/core/surface/call.c64
1 files changed, 57 insertions, 7 deletions
diff --git a/src/core/surface/call.c b/src/core/surface/call.c
index 561c24e547..ebd6ace962 100644
--- a/src/core/surface/call.c
+++ b/src/core/surface/call.c
@@ -76,7 +76,7 @@ typedef struct {
/* Completion function to call at the end of the operation */
grpc_ioreq_completion_func on_complete;
void *user_data;
- /* a bit mask of which request ops are needed (1 << opid) */
+ /* a bit mask of which request ops are needed (1u << opid) */
gpr_uint32 need_mask;
/* a bit mask of which request ops are now completed */
gpr_uint32 complete_mask;
@@ -128,30 +128,80 @@ struct grpc_call {
/* TODO(ctiller): share with cq if possible? */
gpr_mu mu;
- gpr_uint8 is_client;
+ /* how far through the stream have we read? */
read_state read_state;
+ /* how far through the stream have we written? */
write_state write_state;
+ /* client or server call */
+ gpr_uint8 is_client;
+ /* is the alarm set */
gpr_uint8 have_alarm;
+ /* are we currently performing a send operation */
gpr_uint8 sending;
+ /* pairs with completed_requests */
gpr_uint8 num_completed_requests;
+ /* flag that we need to request more data */
gpr_uint8 need_more_data;
+ /* Active ioreqs.
+ request_set and request_data contain one element per active ioreq
+ operation.
+
+ request_set[op] is an integer specifying a set of operations to which
+ the request belongs:
+ - if it is < GRPC_IOREQ_OP_COUNT, then this operation is pending
+ completion, and the integer represents to which group of operations
+ the ioreq belongs. Each group is represented by one master, and the
+ integer in request_set is an index into masters to find the master
+ data.
+ - if it is REQSET_EMPTY, the ioreq op is inactive and available to be
+ started
+ - finally, if request_set[op] is REQSET_DONE, then the operation is
+ complete and unavailable to be started again
+
+ request_data[op] is the request data as supplied by the initiator of
+ a request, and is valid iff request_set[op] <= GRPC_IOREQ_OP_COUNT.
+ The set fields are as per the request type specified by op.
+
+ Finally, one element of masters is set per active _set_ of ioreq
+ operations. It describes work left outstanding, result status, and
+ what work to perform upon operation completion. As one ioreq of each
+ op type can be active at once, by convention we choose the first element
+ of the group to be the master -- ie the master of in-progress operation
+ op is masters[request_set[op]]. This allows constant time allocation
+ and a strong upper bound of a count of masters to be calculated. */
gpr_uint8 request_set[GRPC_IOREQ_OP_COUNT];
grpc_ioreq_data request_data[GRPC_IOREQ_OP_COUNT];
reqinfo_master masters[GRPC_IOREQ_OP_COUNT];
+
+ /* Dynamic array of ioreq's that have completed: the count of
+ elements is queued in num_completed_requests.
+ This list is built up under lock(), and flushed entirely during
+ unlock().
+ We know the upper bound of the number of elements as we can only
+ have one ioreq of each type active at once. */
completed_request completed_requests[GRPC_IOREQ_OP_COUNT];
+ /* Incoming buffer of messages */
grpc_byte_buffer_queue incoming_queue;
+ /* Buffered read metadata waiting to be returned to the application.
+ Element 0 is initial metadata, element 1 is trailing metadata. */
grpc_metadata_array buffered_metadata[2];
+ /* All metadata received - unreffed at once at the end of the call */
grpc_mdelem **owned_metadata;
size_t owned_metadata_count;
size_t owned_metadata_capacity;
+ /* Received call statuses from various sources */
received_status status[STATUS_SOURCE_COUNT];
+ /* Deadline alarm - if have_alarm is non-zero */
grpc_alarm alarm;
+ /* Call refcount - to keep the call alive during asynchronous operations */
gpr_refcount internal_refcount;
+ /* Data that the legacy api needs to track. To be deleted at some point
+ soon */
legacy_state *legacy_state;
};
@@ -274,7 +324,7 @@ static int is_op_live(grpc_call *call, grpc_ioreq_op op) {
reqinfo_master *master;
if (set >= GRPC_IOREQ_OP_COUNT) return 0;
master = &call->masters[set];
- return (master->complete_mask & (1 << op)) == 0;
+ return (master->complete_mask & (1u << op)) == 0;
}
static void lock(grpc_call *call) { gpr_mu_lock(&call->mu); }
@@ -362,7 +412,7 @@ static void finish_live_ioreq_op(grpc_call *call, grpc_ioreq_op op,
size_t i;
/* ioreq is live: we need to do something */
master = &call->masters[master_set];
- master->complete_mask |= 1 << op;
+ master->complete_mask |= 1u << op;
if (status != GRPC_OP_OK) {
master->status = status;
master->complete_mask = master->need_mask;
@@ -564,7 +614,7 @@ static grpc_call_error start_ioreq_error(grpc_call *call,
grpc_call_error ret) {
size_t i;
for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) {
- if (mutated_ops & (1 << i)) {
+ if (mutated_ops & (1u << i)) {
call->request_set[i] = REQSET_EMPTY;
}
}
@@ -650,7 +700,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs,
} else if (call->request_set[op] == REQSET_DONE) {
return start_ioreq_error(call, have_ops, GRPC_CALL_ERROR_ALREADY_INVOKED);
}
- have_ops |= 1 << op;
+ have_ops |= 1u << op;
data = reqs[i].data;
call->request_data[op] = data;
@@ -664,7 +714,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs,
master->on_complete = completion;
master->user_data = user_data;
- if (have_ops & (1 << GRPC_IOREQ_RECV_MESSAGE)) {
+ if (have_ops & (1u << GRPC_IOREQ_RECV_MESSAGE)) {
call->need_more_data = 1;
}