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;
}