int chanrecv(Channel *c, void *v) { while (1) { int result = channbrecv(c, v); if (result != LTCHAN_NONE) return result; lthread_cond_wait(c->rcond, 0); } }
static int memqueue_poll_queue(poll_args_t *user_args) { int rev = 0; int i = 0; int total_msgs = 0; int total_bound_queues = 0; cli_binder_t *cli_binder = NULL; memqueue_t *q = NULL; cli_binder = cli_binder_create(user_args->timeout); for (i = 0; i < user_args->total; i++) { q = h_get(memqueue_ins.queue_store, user_args->queue_args[i].q_id); if (!q) continue; total_bound_queues++; if (q->consumer_expiry && user_args->queue_args[i].consumer_id != NULL) memqueue_refresh_consumer(q, user_args->queue_args[i].consumer_id); memqueue_resched(&memqueue_ins, q); //printf("q->rev is %d and user_rev is %d\n", q->rev, user_args->queue_args[i].rev); if (q->rev < user_args->queue_args[i].rev) rev = -1; else rev = user_args->queue_args[i].rev; /* bind poller */ memqueue_bind(q, cli_binder, rev, user_args->queue_args[i].include_consumers); total_msgs += cli_binder_enqueue_msgs(cli_binder, q, rev, user_args->queue_args[i].latest); } if (total_bound_queues == 0) { cli_binder_free(cli_binder); memqueue_respond(MEMQUEUE_NOT_FOUND, NULL); return 0; } /* Do we have messages that match our rev requirements already? */ if (total_msgs == 0) lthread_cond_wait(cli_binder->cond, cli_binder->timeout); if (cli_binder_has_pending_msgs(cli_binder)) memqueue_respond(MEMQUEUE_MSGS, cli_binder); else memqueue_respond(MEMQUEUE_TIMEOUT, NULL); memqueue_unbind_all(cli_binder); cli_binder_release_pending_msgs(cli_binder); cli_binder_free(cli_binder); return 0; }
int _chansend(Channel *c, void *v, int block) { if (c->closed) return LTCHAN_CLOSED; // special condition for 0 // if the buffer size is 0 (synchronous), then we will go over the // the buffer limit regardless... (and block later until chan receieves it) while (1) { int cond = (c->cursize >= c->bufsize); if (c->bufsize == 0) cond = (c->cursize > c->bufsize); if (!cond) { break; } if (block) { lthread_cond_wait(c->wcond, 0); } else { return LTCHAN_FULL; } } // check again in case we close the channel if (c->closed) return LTCHAN_CLOSED; _lt_ch_list *elem = malloc(sizeof(_lt_ch_list)); elem->prev = c->tail; elem->elem = malloc(c->elemsize); memmove(elem->elem, v, c->elemsize); elem->next = NULL; if (c->head == NULL) { // no elements c->head = elem; c->tail = elem; } else { c->tail->next = elem; c->tail = elem; } c->cursize++; // let readers know that we've just inserted an element lthread_cond_broadcast(c->rcond); // if buffer is overfull and we're blocking, block // (special condition for 0: block always) if (block || c->bufsize == 0) { while (c->cursize > c->bufsize) { lthread_cond_wait(c->wcond, 0); } } return 0; }