summaryrefslogtreecommitdiff
path: root/include/yasl
diff options
context:
space:
mode:
Diffstat (limited to 'include/yasl')
-rw-r--r--include/yasl/app.h3
-rw-r--r--include/yasl/loop.h63
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.