Non-main threads are sometimes blocked on input file descriptors. 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 takes a pointer to an fd_set 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 version of MrEd sets 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;
limit = getdtablesize();
count = 0;
for (i = 0; i < limit; i++)
if (FD_ISSET(i, (fd_set *)fds))
count++;
if (!count)
return;
/* If old callbacks are installed, remove them: */
if (scheme_cb_ids)
for (i = 0; i < num_cbs; i++)
XtRemoveInput(scheme_cb_ids[i]);
num_cbs = 2 * count;
scheme_cb_ids = new XtInputId[num_cbs];
p = 0;
for (i = 0; i < limit; i++)
/* For each FD, install a callback for input/exceptions: */
if (FD_ISSET(i, (fd_set *)fds)) {
scheme_cb_ids[p] = XtAppAddInput(wxAPP_CONTEXT, i,
(XtPointer *)XtInputReadMask,
(XtInputCallbackProc)MrEdWakeUp, NULL);
scheme_cb_ids[p+count] = XtAppAddInput(wxAPP_CONTEXT, i,
(XtPointer *)XtInputExceptMask,
(XtInputCallbackProc)MrEdWakeUp,
NULL);
p++;
}
}
/* 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;
}