[gambit-list] Pushing events between C++ and Scheme + timers
Marc Feeley
feeley at IRO.UMontreal.CA
Wed Dec 8 15:37:00 EST 2004
> > Marc Feeley wrote:
> >Are you willing to start a C thread for the Scheme code?
>
> I could but I'd rather avoid it if I can.
That is a problem because the timers will only expire on time if C
returns control to Scheme in a timely manner. Polling should be
avoided... A possible solution is for the Scheme world to tell the C
world when its next scheduled timeout will be (i.e. the first
suspended thread on the Scheme thread scheduler's timeout queue), and
C has to call back to Scheme at that point at the lattest (so you have
to manage one timer on the C side for this). There's currently no way
to tell when the next scheduled timeout will be, but a Scheme function
for this can easily be added to _thread.scm (5 lines of code).
> >This would
> >decouple control between Scheme and C, allowing timers to be
> >implemented in Scheme with the I/O timeout mechanisms.
>
> How would you implement these timers?
Here's some sample code:
(define-type timer
mutex
)
(define (timer-start timeout thunk)
(let* ((m (make-mutex))
(t (make-timer m)))
(mutex-lock! m) ; make sure mutex is locked
(thread-start!
(make-thread
(lambda ()
(if (mutex-lock! m timeout) ; block at most until timeout
#f ; timer was stopped before the timeout
(thunk)))))
t))
(define (timer-stop timer)
(mutex-unlock! (timer-mutex timer)))
(define t (timer-start 5 (lambda () (pp 'hello))))
;(timer-stop t) ; uncomment to stop timer prematurely
(let loop () (thread-sleep! 1) (pp '*) (loop))
Alternatively, you could put the timeout on some blocking I/O
operation or synchronization operation (mutex, condition variable,
thread join, etc) and get the equivalent of a timer.
> >Then you need
> >two pipes between the C and Scheme worlds. These pipes could be
> >actual OS pipes, sockets, or a new type of device (this would be more
> >efficient and portable, but require the implementation of a new device
> >in _os_io.c).
>
> Can they be simple Scheme lists?
>
> I thought I could have 3 Scheme functions I would call from C++ where one
> would start the Scheme loop in a Scheme thread and the other two would
> let C++ post events (sexp) to the "incoming events" Scheme list and the
> other would retrieve them from the "outgoing" list. The post/retrieve
> functions would use a mutex to block access to the lists/queues. Then I
> could do the timer by launching another thread within Gambit.
>
> Maybe I'm misunderstanding the nature of integration that would be
> required here. Please let me know!
It can't just be a Scheme list. You need some synchronization
mechanism. Ideally the Scheme side should just try to get an event and
block until an event is available. A FIFO created with open-vector-pipe
like this would do:
(receive (in out) (open-vector-pipe '(direction: input))
; in is the input port side of the FIFO and out is the
; output port side of the FIFO
(write 111 out) ; first event
(write 222 out) ; second event
(write 333 out) ; third event
(force-output out)
(list (read in) (read in))) ; returns (111 222)
So the C side should call a Scheme function to add an event to
the FIFO (on the output port side), and this will unblock the
Scheme thread that is blocked on a read on the input port side
of the FIFO.
Marc
More information about the Gambit-list
mailing list