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