Scheme threads are sometimes blocked on file descriptors, such as an input file or the X event socket. Blocked non-main threads do not block the main thread, and therefore do not affect the event loop, so scheme_check_threads is sufficient to implement this case correctly. However, it is wasteful to poll these descriptors with scheme_check_threads when nothing else is happening in the application and when a lower-level poll on the file descriptors can be installed. If the global function pointer scheme_wakeup_on_input is set, then this case is handled more efficiently by turning off thread checking and issuing a ``wakeup'' request on the blocking file descriptors through scheme_wakeup_on_input. (The scheme_wakeup_on_input function is only used on platforms with file descriptions.)
A scheme_wakeup_on_input procedure takes a pointer to an array of three fd_sets (sortof) and returns void. The scheme_wakeup_on_input does not sleep; it just sets up callbacks on the specified file descriptors. When input is ready on any of those file descriptors, the callbacks are be removed and scheme_wake_up is called.
For example, the X Windows version of MrEd formerly set scheme_wakeup_on_input to this MrEdNeedWakeup:
static XtInputId *scheme_cb_ids = NULL; static int num_cbs; static void MrEdNeedWakeup(void *fds) { int limit, count, i, p; fd_set *rd, *wr, *ex; rd = (fd_set *)fds; wr = ((fd_set *)fds) + 1; ex = ((fd_set *)fds) + 2; limit = getdtablesize(); /* See if we need to do any work, really: */ count = 0; for (i = 0; i < limit; i++) { if (MZ_FD_ISSET(i, rd)) count++; if (MZ_FD_ISSET(i, wr)) count++; if (MZ_FD_ISSET(i, ex)) count++; } if (!count) return; /* Remove old callbacks: */ if (scheme_cb_ids) for (i = 0; i < num_cbs; i++) notify_set_input_func((Notify_client)NULL, (Notify_func)NULL, scheme_cb_ids[i]); num_cbs = count; scheme_cb_ids = new int[num_cbs]; /* Install callbacks */ p = 0; for (i = 0; i < limit; i++) { if (MZ_FD_ISSET(i, rd)) scheme_cb_ids[p++] = XtAppAddInput(wxAPP_CONTEXT, i, (XtPointer *)XtInputReadMask, (XtInputCallbackProc)MrEdWakeUp, NULL); if (MZ_FD_ISSET(i, wr)) scheme_cb_ids[p++] = XtAppAddInput(wxAPP_CONTEXT, i, (XtPointer *)XtInputWriteMask, (XtInputCallbackProc)MrEdWakeUp, NULL); if (MZ_FD_ISSET(i, ex)) scheme_cb_ids[p++] = XtAppAddInput(wxAPP_CONTEXT, i, (XtPointer *)XtInputExceptMask, (XtInputCallbackProc)MrEdWakeUp, NULL); } } /* callback function when input/exception is detected: */ Bool MrEdWakeUp(XtPointer, int *, XtInputId *) { int i; if (scheme_cb_ids) { /* Remove all callbacks: */ for (i = 0; i < num_cbs; i++) XtRemoveInput(scheme_cb_ids[i]); scheme_cb_ids = NULL; /* ``wake up'' */ scheme_wake_up(); } return FALSE; }