updated channel buffering code

This commit is contained in:
hyung-hwan 2025-06-13 23:36:43 +09:00
parent 0c5da297d0
commit 34c0ba457b
2 changed files with 25 additions and 8 deletions

31
chan.c
View File

@ -57,10 +57,13 @@ int hip_chan_send(hip_chan_t* c, const void* ptr, hip_oow_t len)
hip = c->hip;
caller = UCTX_FROM_LINK(hip->running);
if (c->unit_count < c->unit_capa)
if (HIP_LIST_IS_EMPTY(&c->recvq))
{
/* buffered */
hip_uint8_t* dptr;
if (c->unit_count >= c->unit_capa) goto block;
/* the buffer is not full. write to the buffer */
if (len > c->unit_size) len = c->unit_size; /* can't buffer longer than the specified unit size */
dptr = &c->buf[c->unit_wpos * c->unit_size];
memcpy(dptr, ptr, len);
@ -71,10 +74,16 @@ int hip_chan_send(hip_chan_t* c, const void* ptr, hip_oow_t len)
}
c->unit_wpos = (c->unit_wpos + 1) % c->unit_capa;
c->unit_count++;
/* give another routine a chance to read.
* does this cause too many context switches?
* without this, there is a high chance the the same routine
* starves the channel by reading and writing in succession
* if it read and write on the same channel */
hip_yield(hip);
return len;
}
if (!HIP_LIST_IS_EMPTY(&c->recvq)) /* there is a receving routine */
else /* there is a receiving routing waiting */
{
hip_uctx_link_t* x;
hip_uctx_t* recver;
@ -95,6 +104,7 @@ int hip_chan_send(hip_chan_t* c, const void* ptr, hip_oow_t len)
}
block:
/* remember the data holder and places the current running routine in the send queue */
caller->chan_data_ptr = (hip_uint8_t*)ptr;
caller->chan_data_len = len;
@ -115,16 +125,22 @@ int hip_chan_recv(hip_chan_t* c, void* ptr, hip_oow_t len)
hip = c->hip;
caller = UCTX_FROM_LINK(hip->running);
if (c->unit_count > 0)
if (HIP_LIST_IS_EMPTY(&c->sendq))
{
if (c->unit_count <= 0) goto block;
/* the buffer is not empty. there's data to read */
if (len > c->unit_size) len = c->unit_size;
memcpy(ptr, &c->buf[c->unit_rpos * c->unit_size], len);
c->unit_rpos = (c->unit_rpos + 1) % c->unit_capa;
c->unit_count--;
/* In receiving, i doubt it causes starvation to not yield to another routine.
* let me not switch to the scheduler here for now. */
/*hip_yield(hip);*/
return len;
}
if (!HIP_LIST_IS_EMPTY(&c->sendq)) /* there is a sending routine */
else /* there is a sending routine */
{
hip_uctx_link_t* x;
hip_uctx_t* sener;
@ -145,6 +161,7 @@ int hip_chan_recv(hip_chan_t* c, void* ptr, hip_oow_t len)
return len;
}
block:
/* remember the data holder and place the calling routine in the receive queue */
caller->chan_data_ptr = ptr;
caller->chan_data_len = len;

2
ctx.c
View File

@ -828,7 +828,7 @@ int main()
setbuf(stdout, NULL);
hip = hip_open(HIP_FLAG_LAZY);
chan = hip_chan_open(hip, 100, 0);
chan = hip_chan_open(hip, 100, 1);
hip_newrtn(hip, 0, uf1, chan);
hip_newrtn(hip, 0, uf2, HIP_NULL);