notcurses_get: restore old delaybound behavior #2169

This commit is contained in:
nick black 2021-09-17 15:23:18 -04:00 committed by nick black
parent b3912e96e9
commit 5eed1abe8e
3 changed files with 21 additions and 4 deletions

View File

@ -692,7 +692,7 @@ typedef struct ncinput {
// timespec to bound blocking. Returns a single Unicode code point, or
// (uint32_t)-1 on error. Returns 0 on a timeout. If an event is processed, the
// return value is the 'id' field from that event. 'ni' may be NULL. 'ts' is an
// *absolute* time relative to gettimeofday() (see pthread_cond_timedwait(3)).
// a delay bound against gettimeofday() (see pthread_cond_timedwait(3)).
uint32_t notcurses_get(struct notcurses* n, const struct timespec* ts,
ncinput* ni);

View File

@ -1070,7 +1070,7 @@ ncinput_equal_p(const ncinput* n1, const ncinput* n2){
// timespec to bound blocking. Returns a single Unicode code point, or
// (uint32_t)-1 on error. Returns 0 on a timeout. If an event is processed, the
// return value is the 'id' field from that event. 'ni' may be NULL. 'ts' is an
// *absolute* time relative to gettimeofday() (see pthread_cond_timedwait(3)).
// a delay bound against gettimeofday() (see pthread_cond_timedwait(3)).
API uint32_t notcurses_get(struct notcurses* n, const struct timespec* ts,
ncinput* ni)
__attribute__ ((nonnull (1)));

View File

@ -1828,6 +1828,7 @@ internal_get(inputctx* ictx, const struct timespec* ts, ncinput* ni){
}else{
int r = pthread_cond_timedwait(&ictx->icond, &ictx->ilock, ts);
if(r == ETIMEDOUT){
pthread_mutex_unlock(&ictx->ilock);
return 0;
}else if(r < 0){
inc_input_errors(ictx);
@ -1851,9 +1852,23 @@ internal_get(inputctx* ictx, const struct timespec* ts, ncinput* ni){
return ni->id;
}
static void
delaybound_to_deadline(const struct timespec* ts, struct timespec* absdl){
if(ts){
// incoming ts is a delay bound, but we want an absolute deadline for
// pthread_cond_timedwait(). convert it.
struct timeval tv;
gettimeofday(&tv, NULL);
absdl->tv_sec = ts->tv_sec + tv.tv_sec;
absdl->tv_nsec = ts->tv_nsec + tv.tv_usec * 1000;
}
}
// infp has already been set non-blocking
uint32_t notcurses_get(notcurses* nc, const struct timespec* ts, ncinput* ni){
uint32_t r = internal_get(nc->tcache.ictx, ts, ni);
struct timespec absdl;
delaybound_to_deadline(ts, &absdl);
uint32_t r = internal_get(nc->tcache.ictx, ts ? &absdl : NULL, ni);
if(r != (uint32_t)-1){
++nc->stats.s.input_events;
}
@ -1863,8 +1878,10 @@ uint32_t notcurses_get(notcurses* nc, const struct timespec* ts, ncinput* ni){
// FIXME better performance if we move this within the locked area
int notcurses_getvec(notcurses* n, const struct timespec* ts,
ncinput* ni, int vcount){
struct timespec absdl;
delaybound_to_deadline(ts, &absdl);
for(int v = 0 ; v < vcount ; ++v){
uint32_t u = notcurses_get(n, ts, &ni[v]);
uint32_t u = notcurses_get(n, ts ? &absdl : NULL, &ni[v]);
if(u == (uint32_t)-1){
if(v == 0){
return -1;