previous up next     contents index
Next: Sleeping by Embedded MzScheme Up: Threads in Embedded MzScheme Previous: Threads in Embedded MzScheme

Blocked Non-main Threads

 

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



PLT