// Sends a value into the channel. If the channel is unbuffered, this will // block until a receiver receives the value. If the channel is buffered and at // capacity, this will block until a receiver receives a value. Returns 0 if // the send succeeded or -1 if it failed. If -1 is returned, errno will be set. int chan_send(chan_t* chan, void* data) { if (chan_is_closed(chan)) { // Cannot send on closed channel. errno = EPIPE; return -1; } return chan_is_buffered(chan) ? buffered_chan_send(chan, data) : unbuffered_chan_send(chan, data); }
static int unbuffered_chan_recv(chan_t* chan, void** data) { pthread_mutex_lock(chan->r_mu); if (chan_is_closed(chan)) { errno = EPIPE; return -1; } int success = blocking_pipe_read(chan->pipe, data); pthread_mutex_unlock(chan->r_mu); return success; }
static void lt_accept_loop(void *arg) { proxy_server *srv = (proxy_server*)arg; lthread_t *lt = NULL; proxy_conn_t *proxy = NULL; int ret; void* msgs[2]; lthread_chan_t* chans[2]; lthread_sel_t *sel = lthread_sel_create(); chans[0] = srv->accepts_ch; chans[1] = srv->die_ch; while(!srv->is_die) { ret = chan_select(sel, chans, msgs, 0, 2, LTHREAD_FOREVER); switch(ret) { case 0: //recv ok fprintf(stderr, "recv accept channel ok\n"); proxy = (proxy_conn_t*)msgs[0]; if(NULL == proxy && chan_is_closed(msgs[0])) { ret = -10; break; } lthread_create(<, (void*)lt_request_cli, (void*)proxy); //yield myself lthread_sleep(0); break; case 1: //server die ret = -11; break; default: break; } if(ret < 0) { fprintf(stderr, "%s#%d ret=%d\n", __FUNCTION__, __LINE__, ret); break; } } lthread_sel_dispose(sel); }
static void lt_proxy_loop_write(void* arg) { proxy_conn_t *proxy = (proxy_conn_t*)arg; //proxy_conn_t *other = proxy->other; proxy_server *srv = &g_srv; int ret; lthread_chan_t* chans[3]; void* msgs[3]; kstring_t *buf = NULL; lthread_sel_t* sel = lthread_sel_create(); chans[0] = proxy->write_ch; chans[1] = proxy->die_ch; chans[2] = srv->die_ch; fprintf(stderr, "%s#%d started\n", __FUNCTION__, __LINE__); while(!proxy->is_die) { ret = chan_select(sel, chans, msgs, 0, 3, LTHREAD_FOREVER); switch(ret) { case 0: //recv channel ok buf = msgs[0]; if(NULL == buf && chan_is_closed(chans[0])) { //channel closed ret = -10; fprintf(stderr, "%s#%d chan closed priv=%d\n", __FUNCTION__, __LINE__, proxy->is_priv); break; } assert(NULL != buf); //fprintf(stderr, "recv new writer\n"); ret = net_conn_write(&proxy->conn.base, (uint8_t*)buf->s, buf->l, LTHREAD_FOREVER); if(ret <= 0) { fprintf(stderr, "write failed ret=%d priv=%d\n", ret, proxy->is_priv); ret = -11; } ks_free(buf); free(buf); buf = NULL; break; case 1: //proxy already die ret = -12; break; case 2: //server already die ret = -13; break; default: break; } //after switch if(ret < 0) { fprintf(stderr, "%s#%d error is_priv=%d ret=%d\n", __FUNCTION__, __LINE__, proxy->is_priv, ret); break; } } if(NULL != buf) { ks_free(buf); free(buf); } assert(0 == chan_size(chans[0])); if(!proxy->is_die) { proxy->is_die = 1; chan_close(proxy->die_ch); } net_conn_shutdown(&proxy->conn.base); lthread_sel_dispose(sel); }