diff options
author | 2015-02-04 12:51:14 -0800 | |
---|---|---|
committer | 2015-02-04 12:51:14 -0800 | |
commit | fd9d0b47e504fc79bb58d809696c1b964070af7d (patch) | |
tree | 21c91490b0c56ad16e47009ade39ab307bc04fc4 /src/core/surface/call.c | |
parent | e2b2b1fb676eef687f0ea088aa74a13b52cbf755 (diff) | |
parent | d6731628bcedbe150d4f7cd09656bd506979b00f (diff) |
Merge branch 'async-api' of github.com:ctiller/grpc into async-api
Diffstat (limited to 'src/core/surface/call.c')
-rw-r--r-- | src/core/surface/call.c | 64 |
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; } |