[gambit-list] Embedding swank-gambit

Marc Feeley feeley at iro.umontreal.ca
Mon May 23 16:41:02 EDT 2011

On 2011-05-23, at 3:40 PM, Roger Wilson wrote:

> I'm evaluating using Gambit-C Scheme as a scripting type language within my application.  The main app is written in C++ and I've got the C++ -> Scheme -> C++ calls all working.  That was all straightforward and I'm pretty happy with that.  I'm now trying to integrate swank and have hit a bit of a dead end.  I can run swank-gambit on its own and it just worked, the problem has come trying to run it  alongside the thread that communicates with the host C++ app.  I've tried replacing the code at the bottom of swank-gambit.scm with the following based on the iOS sample.  This creates a new thread that returns to the C++ host, while the primordial thread creates the swank server.
> (continuation-capture
> (lambda (cont)
>    (thread-start!
>     (make-thread
>      (lambda ()
>        (continuation-return cont #f))))
>    ;; the primordial thread is running this...
>    (swank-server-register!)
>    (thread-sleep! +inf.0)
>    exit)))
> That works in as much as it creates the tcp listen port and slime can connect to it, however it seems that the connection is rarely if ever serviced.  The calls between C++ and Scheme in the other thread all continue ok.  Can someone point me in the direction I need to fix this please?  I suspect I've got a fundamentally wrong understanding of swank or the whole Gambit threading model.  Do I somehow need to provide execution time to the primordial thread?
> Roger.

Gambit implements green threads, and this may be the cause of your problem.  If you use the FFI to call a C++ function that blocks, or if your main function in C++ blocks and only calls the Scheme code occasionally (for example when there is a GUI event), then the context switching of the Scheme threads will not happen and your Scheme threads will not get to run (even if they are conceptually runnable).

To circumvent this problem here are a few suggestions:

1) Call the following function regularly from your C++ code:

(c-define (heartbeat) () void "heartbeat" "extern"
  (##thread-heartbeat!))  ;; make sure other threads get to run

This can be done by creating a timer on the C++ side which will generate an event that your main loop uses to call the heartbeat function.  That is what the examples/iOS example does, with the added feature that the timer events will be generated at a higher frequency when there are runnable Scheme threads, and slowly when there are none.

2) Some GUI libraries have an "idle" event that serves a similar purpose.

3) Run the Scheme code in a different OS thread, and communicate with it using a socket.

4) Rewrite your application so that the main function is in Scheme, and write your main loop in Scheme.  This is possible in some situations, such as when using X11 because the events are delivered on a socket (the X11 "connection") which you can wait on with "##device-port-wait-for-input!".  See the directory examples/Xlib-simple for an example.


More information about the Gambit-list mailing list