previous up next     contents index
Next: Blocked Non-main Threads Up: Threads Previous: Environment Configuration

Threads in Embedded MzScheme

 

    When MzScheme is embedded in an application with an event-based model -- i.e., the execution of Scheme code in the main thread is repeatedly triggered by external events until the application exits -- special hooks must be set to insure that non-main threads execute correctly. For example, during the execution in the main thread, a new thread may be created; the new thread may still be running when the main thread returns to the event loop, and it may be arbitrarily long before the main thread is executed again from the event loop. Under such circumstances, the embedding program must explicitly allow MzScheme to execute the non-main threads; this is done by periodically calling the function  scheme_check_threads.

Thread-checking only needs to be performed when non-main threads exist (or when there are active callback triggers). The embedding application can set the global function pointer  scheme_notify_multithread to be a function that takes an integer parameter and returns void. This function will be called with 1 when thread-checking is needed, and 0 when thread checking is not longer needed. This prevents unnecessary  scheme_check_threads polling.

As shown below, MrEd sets up  scheme_check_threads polling using the wxWindows wxTimer class. (Any regular event-loop-based callback is appropriate.) The  scheme_notify_multithread pointer is set to MrEdInstallThreadTimer.

class MrEdThreadTimer : public wxTimer
{
 public:
  void Notify(void); /* callback when timer expires */
};

static int threads_go;
static MrEdThreadTimer *theThreadTimer;

void MrEdThreadTimer::Notify()
{
  if (threads_go)
    Start(THREAD_WAIT_TIME, TRUE);

  scheme_check_threads();
}

static void MrEdInstallThreadTimer(int on)
{
  if (!theThreadTimer)
    theThreadTimer = new MrEdThreadTimer;

  if (on)
    theThreadTimer->Start(THREAD_WAIT_TIME, TRUE);
  else
    theThreadTimer->Stop();

  threads_go = on;
  if (on)
    do_this_time = 1;
}





PLT