diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/yasl/app.h | 3 | ||||
| -rw-r--r-- | include/yasl/loop.h | 63 |
2 files changed, 59 insertions, 7 deletions
diff --git a/include/yasl/app.h b/include/yasl/app.h index bf6de9c..b7e1c13 100644 --- a/include/yasl/app.h +++ b/include/yasl/app.h @@ -98,7 +98,8 @@ YASL_API void yasl_surface_request_frame(struct yasl_surface *s); * @param code Application-defined message code (yasl_user_event.code). * @param payload Arbitrary pointer passed through to the event. * @param size Optional payload size. - * @return true if queued successfully, false if queue is full or memory failed. + * @return true if queued; false if memory failed or d is not run by yasl_run(). + * Applications that run their own loop use yasl_loop_post() instead. */ YASL_API bool yasl_post_event(struct yasl_display *d, struct yasl_surface *s, uint32_t code, void *payload, size_t size); diff --git a/include/yasl/loop.h b/include/yasl/loop.h index 9faa8f7..a8e9974 100644 --- a/include/yasl/loop.h +++ b/include/yasl/loop.h @@ -3,7 +3,8 @@ * Optional event loop, file watches, and timers. * * Use the loop's owning thread for all calls and callbacks, except - * yasl_loop_now_ns(). A display borrows a supplied loop. For window applications, + * yasl_loop_now_ns(), yasl_loop_kick(), and yasl_loop_post(), which any thread + * may call. A display borrows a supplied loop. For window applications, * drive yasl_display_dispatch(), drain input, then yasl_display_flush(); the * standalone loop_run() function does not replace this cycle. Timer intervals are * nanoseconds; timeout_ms arguments are milliseconds. Do not recursively step/run @@ -29,10 +30,11 @@ extern "C" { */ YASL_API struct yasl_loop *yasl_loop_create(void); /** - * Release a loop, its watches, and its timers. + * Release a loop, its watches, its timers, and its signal watch. * @param l Loop, or NULL for no action. * Close displays borrowing this loop first. Must not run during a loop callback - * or an active step/run. Watched file descriptors are not closed. + * or an active step/run. Watched file descriptors are not closed. Posted + * functions that have not run are dropped; no thread may still post or kick. */ YASL_API void yasl_loop_destroy(struct yasl_loop *l); /** @@ -59,13 +61,62 @@ YASL_API int yasl_loop_step(struct yasl_loop *l, int timeout_ms); */ YASL_API void yasl_loop_quit(struct yasl_loop *l); /** - * Signal the loop's wake pipe without dispatching callbacks. + * Wake a loop that is waiting, without running any callback. * @param l Loop, or NULL for no action. - * Multiple signals may coalesce. This does not schedule a redraw or enqueue an - * event, and it does not provide a cross-thread application messaging contract. + * May be called from any thread and from a signal handler. The loop must stay + * alive until the call returns. A waiting yasl_loop_step(), yasl_loop_run(), or + * yasl_display_dispatch() on this loop returns early; a loop that is not + * waiting returns early from its next wait instead. Kicks coalesce. This does + * not schedule a redraw or enqueue an event; use yasl_loop_post() to run code + * on the owning thread. */ YASL_API void yasl_loop_kick(struct yasl_loop *l); /** + * Run a function on the loop's owning thread. + * @param l Loop. + * @param fn Required function, called once with ud during a later step. + * @param ud Borrowed userdata until fn runs. + * @return true if queued; false for NULL arguments, a loop without a wake + * pipe, or allocation failure. + * May be called from any thread, but not from a signal handler. Wakes the loop + * like yasl_loop_kick(). Functions run in posting order, during a + * yasl_loop_step() or display dispatch on the owning thread. They may post + * again; a function posted while posts are running waits for a later step. + * Stop posting before yasl_loop_destroy(), which drops functions that have + * not run. + */ +YASL_API bool yasl_loop_post(struct yasl_loop *l, void (*fn)(void *ud), void *ud); +/** + * Deliver POSIX signals to a callback on the loop's owning thread. + * @param l Loop. + * @param signals Signal numbers to watch; the array is read during the call. + * @param n Number of entries, at least one. + * @param cb Required callback, given ud and one signal number per delivery. + * @param ud Borrowed userdata until the watch is removed. + * @return true if every signal is watched; false with errno set and no + * dispositions changed. EINVAL means a NULL or invalid argument, including + * SIGKILL and SIGSTOP. EBUSY means another loop watches one of the signals. + * Replaces this loop's previous watch, if any. Installs one process-wide + * handler per signal with SA_RESTART and an empty handler mask, and saves the + * previous action. The handler only records the signal and wakes the loop, + * so it may run on any thread. YASL does not change any thread's signal mask: + * a signal blocked in every thread stays pending and is not delivered. Caught + * signals reset to their default action across exec, so spawned programs + * do not inherit the handler. Repeated deliveries of one signal before the + * callback runs coalesce into one callback. SIGCHLD reports stopped and + * continued children as well as exits. Callbacks run during yasl_loop_step() + * or display dispatch, and may remove the watch. + */ +YASL_API bool yasl_loop_watch_signals(struct yasl_loop *l, const int *signals, int n, + void (*cb)(void *ud, int signo), void *ud); +/** + * Stop watching signals and restore their previous actions. + * @param l Loop, or NULL for no action. + * Does nothing if the loop watches no signals. Signals that arrived but have + * not reached the callback are dropped. yasl_loop_destroy() also unwatches. + */ +YASL_API void yasl_loop_unwatch_signals(struct yasl_loop *l); +/** * Read the monotonic clock used by YASL timers and timing results. * @return Nanoseconds from CLOCK_MONOTONIC, unrelated to wall-clock time. * May be called from any thread. |
