int handle_write(struct handle *h, const void *data, int len) { assert(h->output); bufchain_add(&h->u.o.queued_data, data, len); handle_try_output(&h->u.o); return bufchain_size(&h->u.o.queued_data); }
int handle_write(struct handle *h, const void *data, int len) { assert(h->type == HT_OUTPUT); assert(h->u.o.outgoingeof == EOF_NO); bufchain_add(&h->u.o.queued_data, data, len); handle_try_output(&h->u.o); return bufchain_size(&h->u.o.queued_data); }
void handle_write_eof(struct handle *h) { /* * This function is called when we want to proactively send an * end-of-file notification on the handle. We can only do this by * actually closing the handle - so never call this on a * bidirectional handle if we're still interested in its incoming * direction! */ assert(h->type == HT_OUTPUT); if (!h->u.o.outgoingeof == EOF_NO) { h->u.o.outgoingeof = EOF_PENDING; handle_try_output(&h->u.o); } }
void handle_got_event(HANDLE event) #endif { struct handle *h; assert(handles_by_evtomain); h = find234(handles_by_evtomain, &event, handle_find_evtomain); if (!h) { /* * This isn't an error condition. If two or more event * objects were signalled during the same select operation, * and processing of the first caused the second handle to * be closed, then it will sometimes happen that we receive * an event notification here for a handle which is already * deceased. In that situation we simply do nothing. */ #ifdef MPEXT return 0; #else return; #endif } if (h->u.g.moribund) { /* * A moribund handle is one which we have either already * signalled to die, or are waiting until its current I/O op * completes to do so. Either way, it's treated as already * dead from the external user's point of view, so we ignore * the actual I/O result. We just signal the thread to die if * we haven't yet done so, or destroy the handle if not. */ if (h->u.g.done) { handle_destroy(h); } else { h->u.g.done = TRUE; h->u.g.busy = TRUE; SetEvent(h->u.g.ev_from_main); } #ifdef MPEXT return 0; #else return; #endif } switch (h->type) { int backlog; case HT_INPUT: h->u.i.busy = FALSE; /* * A signal on an input handle means data has arrived. */ if (h->u.i.len == 0) { /* * EOF, or (nearly equivalently) read error. */ h->u.i.defunct = TRUE; h->u.i.gotdata(h, NULL, -h->u.i.readerr); } else { backlog = h->u.i.gotdata(h, h->u.i.buffer, h->u.i.len); handle_throttle(&h->u.i, backlog); } #ifdef MPEXT return 1; #else break; #endif case HT_OUTPUT: h->u.o.busy = FALSE; /* * A signal on an output handle means we have completed a * write. Call the callback to indicate that the output * buffer size has decreased, or to indicate an error. */ if (h->u.o.writeerr) { /* * Write error. Send a negative value to the callback, * and mark the thread as defunct (because the output * thread is terminating by now). */ h->u.o.defunct = TRUE; h->u.o.sentdata(h, -h->u.o.writeerr); } else { bufchain_consume(&h->u.o.queued_data, h->u.o.lenwritten); h->u.o.sentdata(h, bufchain_size(&h->u.o.queued_data)); handle_try_output(&h->u.o); } #ifdef MPEXT return 0; #else break; #endif case HT_FOREIGN: /* Just call the callback. */ h->u.f.callback(h->u.f.ctx); #ifdef MPEXT return 0; #else break; #endif } #ifdef MPEXT return 0; #endif }
void handle_got_event(HANDLE event) { struct handle *h; assert(handles_by_evtomain); h = find234(handles_by_evtomain, &event, handle_find_evtomain); if (!h) { /* * This isn't an error condition. If two or more event * objects were signalled during the same select operation, * and processing of the first caused the second handle to * be closed, then it will sometimes happen that we receive * an event notification here for a handle which is already * deceased. In that situation we simply do nothing. */ return; } if (h->u.g.moribund) { /* * A moribund handle is already treated as dead from the * external user's point of view, so do nothing with the * actual event. Just signal the thread to die if * necessary, or destroy the handle if not. */ if (h->u.g.done) { handle_destroy(h); } else { h->u.g.done = TRUE; h->u.g.busy = TRUE; SetEvent(h->u.g.ev_from_main); } return; } if (!h->output) { int backlog; h->u.i.busy = FALSE; /* * A signal on an input handle means data has arrived. */ if (h->u.i.len == 0) { /* * EOF, or (nearly equivalently) read error. */ h->u.i.gotdata(h, NULL, -h->u.i.readerr); h->u.i.defunct = TRUE; } else { backlog = h->u.i.gotdata(h, h->u.i.buffer, h->u.i.len); handle_throttle(&h->u.i, backlog); } } else { h->u.o.busy = FALSE; /* * A signal on an output handle means we have completed a * write. Call the callback to indicate that the output * buffer size has decreased, or to indicate an error. */ if (h->u.o.writeerr) { /* * Write error. Send a negative value to the callback, * and mark the thread as defunct (because the output * thread is terminating by now). */ h->u.o.sentdata(h, -h->u.o.writeerr); h->u.o.defunct = TRUE; } else { bufchain_consume(&h->u.o.queued_data, h->u.o.lenwritten); h->u.o.sentdata(h, bufchain_size(&h->u.o.queued_data)); handle_try_output(&h->u.o); } } }