This is the mail archive of the guile@cygnus.com mailing list for the guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: tselect



The non-blocking I/O issue is important to me as well. I think it
would be wonderful to have the magic scm_internal_select and have that
yield as appropriate. I too would like to run threads in parallel with
a repl, and run multiple repls in parallel without the repl blocking
on every read. There are ways to hack non-blocking I/O onto guile, but
I think it should just work automatically.

As for this:
> (add-select-callback <callback> <reads> <writes> <excepts> [<secs> <usecs>])
>
>    Add <callback> for this thread to the global set of activation
>    subscribers.
>
>    For a callback, activation means that the *current* thread evaluates
>    the callback in the dynamic context of the thread with which the
>    callback is associated.


The sole virtue I see for this over having multiple threads that use a
new magical select is that it should (sort of) work without
threads. Also, it appears ill-defined what would happen if such a
callback calls a captured continuation or throws an exception that it
doesn't catch - would the continuation do an implicit context switch?
Would it make the callback's thread start running in the thread that
the callback is activated in? What would happen to the thread it was
originally running in? All in all, it doesn't seem to me that this
will have clean interactions with threads.

In a later message, Mikael Djurfeldt wrote:
> (define (event-loop)
>   (select () () ()))

Unless your plans for select want to change the interface, this
appears to be a call that blocks the current thread forever, barring
activation of callbacks. Presumably, the repl and the X event handler
would be appropriate callbacks. Wouldn't it make more sense to just
have at least one of those two run as the current thread, and have the
other invoked as a callback when the other blocks in
scm_internal_select? Or better yet, write the two as separate threads
that call an appropriate select when they have nothing to do? For example:

With threads:

Thread 1:

;; presumably the magic scm_internal_select will get invoked on reads that
;; would block.
(top-repl)

Thread 2:

;; somewhat in pseudo-code
(let loop ()
  (if (X-event-available)
      (handle-one-X-event)
      (select (list X-connection-fdes) () ()))
  (loop))



Without threads:

(define (X-event-handler)
  (if (X-event-available)
      (begin 
	(handle-one-X-event) 
	(X-event-handler))
      ;; else simply return, thus yielding control to scm_internal_select
      ))


(add-select-callback X-event-handler (list X-connection-fdes) () ())

(top-repl)



These should be more or less functionally the same, modulo locking
issues. So really, add-select-callback just seems to be a hack to
avoid using threads, and doesn't seem to provide too much useful
functionality otherwise. But then, I did not see the suggested event
broker stuff that led to this proposal.


On the issue of thread stuff in general, I agree that having
pre-emptive threads would be a wonderful thing, but cooperative
threads that yield on I/O that would block seem just as good, and in
some ways better.


 - Maciej Stachowiak