mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04:00
[input] implement timeouts
This commit is contained in:
parent
edb9eff34b
commit
1d4c62d446
@ -67,9 +67,8 @@ to fill whenever it reads.
|
|||||||
**notcurses_get** allows a **struct timespec** to be specified as a timeout.
|
**notcurses_get** allows a **struct timespec** to be specified as a timeout.
|
||||||
If **ts** is **NULL**, **notcurses_get** will block until it reads input, or
|
If **ts** is **NULL**, **notcurses_get** will block until it reads input, or
|
||||||
is interrupted by a signal. If its values are zeroes, there will be no blocking.
|
is interrupted by a signal. If its values are zeroes, there will be no blocking.
|
||||||
Otherwise, **ts** specifies a minimum time to wait for input before giving up.
|
Otherwise, **ts** specifies an absolute deadline (using the same source and
|
||||||
On timeout, 0 is returned. Signals in **sigmask** will be masked and blocked in
|
timezone as **gettimeofday(2)**). On timeout, 0 is returned. Event
|
||||||
the same manner as a call to **ppoll(2)**. **sigmask** may be **NULL**. Event
|
|
||||||
details will be reported in **ni**, unless **ni** is NULL.
|
details will be reported in **ni**, unless **ni** is NULL.
|
||||||
|
|
||||||
**notcurses_inputready_fd** provides a file descriptor suitable for use with
|
**notcurses_inputready_fd** provides a file descriptor suitable for use with
|
||||||
@ -181,6 +180,7 @@ are resolved.
|
|||||||
|
|
||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
|
|
||||||
|
**gettimeofday(2)**,
|
||||||
**poll(2)**,
|
**poll(2)**,
|
||||||
**notcurses(3)**,
|
**notcurses(3)**,
|
||||||
**notcurses_refresh(3)**,
|
**notcurses_refresh(3)**,
|
||||||
|
@ -1070,7 +1070,8 @@ ncinput_equal_p(const ncinput* n1, const ncinput* n2){
|
|||||||
// timespec to bound blocking. Returns a single Unicode code point, or
|
// timespec to bound blocking. Returns a single Unicode code point, or
|
||||||
// (uint32_t)-1 on error. 'sigmask' may be NULL. Returns 0 on a timeout. If an
|
// (uint32_t)-1 on error. 'sigmask' may be NULL. Returns 0 on a timeout. If an
|
||||||
// event is processed, the return value is the 'id' field from that event.
|
// event is processed, the return value is the 'id' field from that event.
|
||||||
// 'ni' may be NULL.
|
// 'ni' may be NULL. 'ts' is an *absolute* time relative to gettimeofday()
|
||||||
|
// (see pthread_cond_timedwait(3)).
|
||||||
API uint32_t notcurses_get(struct notcurses* n, const struct timespec* ts,
|
API uint32_t notcurses_get(struct notcurses* n, const struct timespec* ts,
|
||||||
ncinput* ni)
|
ncinput* ni)
|
||||||
__attribute__ ((nonnull (1)));
|
__attribute__ ((nonnull (1)));
|
||||||
|
44
src/lib/in.c
44
src/lib/in.c
@ -23,7 +23,6 @@
|
|||||||
// integrate main specials trie with automaton, enable input_errors
|
// integrate main specials trie with automaton, enable input_errors
|
||||||
// wake up input thread when space becomes available
|
// wake up input thread when space becomes available
|
||||||
// (needs pipes/eventfds)
|
// (needs pipes/eventfds)
|
||||||
// handle timeouts
|
|
||||||
|
|
||||||
static sig_atomic_t resize_seen;
|
static sig_atomic_t resize_seen;
|
||||||
|
|
||||||
@ -844,6 +843,13 @@ inc_input_events(inputctx* ictx){
|
|||||||
pthread_mutex_unlock(&ictx->stats->lock);
|
pthread_mutex_unlock(&ictx->stats->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
inc_input_errors(inputctx* ictx){
|
||||||
|
pthread_mutex_lock(&ictx->stats->lock);
|
||||||
|
++ictx->stats->s.input_errors;
|
||||||
|
pthread_mutex_unlock(&ictx->stats->lock);
|
||||||
|
}
|
||||||
|
|
||||||
// add a decoded, valid Unicode to the bulk output buffer, or drop it if no
|
// add a decoded, valid Unicode to the bulk output buffer, or drop it if no
|
||||||
// space is available.
|
// space is available.
|
||||||
static void
|
static void
|
||||||
@ -1472,7 +1478,7 @@ pump_control_read(inputctx* ictx, unsigned char c){
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Reached invalid init state %d\n", ictx->state);
|
logerror("Reached invalid init state %d\n", ictx->state);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -1732,12 +1738,10 @@ block_on_input(inputctx* ictx){
|
|||||||
sigdelset(&smask, SIGWINCH);
|
sigdelset(&smask, SIGWINCH);
|
||||||
while((events = ppoll(pfds, pfdcount, ts, &smask)) < 0){
|
while((events = ppoll(pfds, pfdcount, ts, &smask)) < 0){
|
||||||
#endif
|
#endif
|
||||||
fprintf(stderr, "GOT EVENTS: %d!\n", events);
|
|
||||||
if(errno != EINTR && errno != EAGAIN && errno != EBUSY && errno != EWOULDBLOCK){
|
if(errno != EINTR && errno != EAGAIN && errno != EBUSY && errno != EWOULDBLOCK){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(resize_seen){
|
if(resize_seen){
|
||||||
fprintf(stderr, "SAW A RESIZE!\n");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1814,7 +1818,13 @@ internal_get(inputctx* ictx, const struct timespec* ts, ncinput* ni){
|
|||||||
}
|
}
|
||||||
pthread_mutex_lock(&ictx->ilock);
|
pthread_mutex_lock(&ictx->ilock);
|
||||||
while(!ictx->ivalid){
|
while(!ictx->ivalid){
|
||||||
pthread_cond_wait(&ictx->icond, &ictx->ilock);
|
if(pthread_cond_timedwait(&ictx->icond, &ictx->ilock, ts)){
|
||||||
|
if(errno == ETIMEDOUT){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
inc_input_errors(ictx);
|
||||||
|
return (uint32_t)-1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
memcpy(ni, &ictx->inputs[ictx->iread], sizeof(*ni));
|
memcpy(ni, &ictx->inputs[ictx->iread], sizeof(*ni));
|
||||||
if(++ictx->iread == ictx->isize){
|
if(++ictx->iread == ictx->isize){
|
||||||
@ -1826,18 +1836,6 @@ internal_get(inputctx* ictx, const struct timespec* ts, ncinput* ni){
|
|||||||
return ni->id;
|
return ni->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct initial_responses* inputlayer_get_responses(inputctx* ictx){
|
|
||||||
struct initial_responses* iresp;
|
|
||||||
pthread_mutex_lock(&ictx->ilock);
|
|
||||||
while(!ictx->initdata_complete){
|
|
||||||
pthread_cond_wait(&ictx->icond, &ictx->ilock);
|
|
||||||
}
|
|
||||||
iresp = ictx->initdata_complete;
|
|
||||||
ictx->initdata_complete = NULL;
|
|
||||||
pthread_mutex_unlock(&ictx->ilock);
|
|
||||||
return iresp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// infp has already been set non-blocking
|
// infp has already been set non-blocking
|
||||||
uint32_t notcurses_get(notcurses* nc, const struct timespec* ts, ncinput* ni){
|
uint32_t notcurses_get(notcurses* nc, const struct timespec* ts, ncinput* ni){
|
||||||
uint32_t r = internal_get(nc->tcache.ictx, ts, ni);
|
uint32_t r = internal_get(nc->tcache.ictx, ts, ni);
|
||||||
@ -1984,3 +1982,15 @@ linesigs_enable(tinfo* ti){
|
|||||||
int notcurses_linesigs_enable(notcurses* n){
|
int notcurses_linesigs_enable(notcurses* n){
|
||||||
return linesigs_enable(&n->tcache);
|
return linesigs_enable(&n->tcache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct initial_responses* inputlayer_get_responses(inputctx* ictx){
|
||||||
|
struct initial_responses* iresp;
|
||||||
|
pthread_mutex_lock(&ictx->ilock);
|
||||||
|
while(!ictx->initdata_complete){
|
||||||
|
pthread_cond_wait(&ictx->icond, &ictx->ilock);
|
||||||
|
}
|
||||||
|
iresp = ictx->initdata_complete;
|
||||||
|
ictx->initdata_complete = NULL;
|
||||||
|
pthread_mutex_unlock(&ictx->ilock);
|
||||||
|
return iresp;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user