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


Marius Vollmer <mvo@zagadka.ping.de> writes:

> Mikael Djurfeldt <mdj@nada.kth.se> writes:
> 
> > Problems:
> > 
> > * We need non-blocking ports in the STk port if we want to have a
> >   compatible behaviour.
> 
> I have not closely examined STk for its `threadiness' so I don't know
> how things really are, but I think we don't want to have non-blocking
> ports (in the sense of non-blocking.scm).  We want to have I/O
> primitives that work with the coop threads.  A call to such a I/O
> primitive should only block the calling thread and not the whole
> process.

Exactly.  (Also, there is no sense in nonblocking.scm.  That was
basically only a workaround to get some code running.)

> I think that this is what you are talking about, but "non-blocking
> ports" sounds to me like there are also *blocking ports*, and you have
> to use a special kind of port to not hang the whole process.

Well, this is exactly the situation right now---the (currently)
"normal" ports blocks the whole process while the soft-port in
nonblocking.scm only blocks the thread.  But I agree that the
non-blocking port should be the normal thing, and if it is, no-one
would want to have the other kind.  :)

[...]

> Then, I'm not sure if we really need non-blocking I/O for STk
> compatability, a event-driven repl might be just as good.  I have
> implemented such a beast for Guile-gtk and while it *is* kinda hacky,
> it is better than non-blocking.scm, I feel.

Well, scm_internal_select () gives an easy possibility to make all I/O
primitives behave normally.  Note that the major mechanism of
scm_internal_select () will be necessary even if we use event-driven
style (i. e. in the case we want to be able to use threads).

> But: non-blocking I/O is the way to go, anyway.

OK--seems we're on the same track.

> We should have that even without POSIX threads
                      ^^^^
I'm a bit worried about this "even".  You said something similar in a
previous letter.  In my view, the non-blocking I/O isn't necessary
anylonger when we switch to POSIX threads, because I/O primitives will
either be thread safe (for non-user-space thread support) or replaced
(for user-space thread support).  This simply means that
scm_internal_select will become select.

This will of course break the call-back interface I suggested in my
previous letter---hmm...

Maybe it's best to implement the main repl in an event-driven style
after all and introduce the call-back interface separately from
select?

(Oops!  Now I suddenly realize something which I forgot to add in the
 previous letter to make it comprehensible:  The event-loop would be
 implemented:

 (define (event-loop)
   (select () () ()))

 )

> and I think we can
> implement it in a clean way because we directly control the
> implementation of the I/O routines.  We don't have to redefine
> read(3), write(3) etc like user-space POSIX thread implementations
> have to.

Exactly.

> On the other hand, we can probably use much of the code of one of the
> Linux user-space thread packages.

I wouldn't think so.  We need to adapt it specially to COOP threads.
I know how to do that.

> > 1. Move to POSIX threads.
> > 
> >    + Brings us to Nirvana.
> 
> I'm not sure.  Writing correct code for really concurrent threads
> requires a whole new level of attention to whole new details.  Many
> people might not want to invest that and settle for cooperative
> threads.  Me included.

It makes it possible to run threads on multiple processors.  And,
basing the Guile design now on cooperative threads only, excludes a
future move to multiple processors.  And I expect the future to be
full of processors.  :)

[...]

> > 2. Have COOP go preemptive
> 
> This is not necessary to get decent I/O behaviour for threads and only
> complicates things unnecessarily, I think.

I agree that our current approach fixes the I/O problem, but we still
have the problem that user code can contain computation intense
portions.  If we have some graphics support, then, in another thread,
graphics will freeze while the first thread computes.  I know this
very concretely from my neuron simulator.  ;-)

> > 3. Implement *real* non-blocking ports for the COOP threads.
> 
> That's what we should do, I think.

I still maintain that POSIX is Nirvana and preemptive COOP threads a
pretty good prophet.

> > In the prettiest versions of solutions 2 and 3, both need I/O to be
> > coordinated through a specially designed `select', so I suggest that I
> > implement a function `tselect' (for "thread select") which does this
> > job.  It will be implemented in such a way that it works both with and
> > without threads linked into Guile.
> 
> Here is how I would approach it.  

[...]

> We should have support for the event driven programming model (always)
> and -- implemented on top of it -- non-blocking I/O for cooperative
> threads (when QuickThreads are configured in).

[...]

> Then we can have implement the low-level I/O operations in terms of
> this event-loop.  When such an I/O routine wants to access a
> file-descriptor, it registers an appropriate callback with the
> event-loop and waits on a semaphore (or something).  Then the callback
> triggers this semaphore and the thread awakes.  The callback is
> removed.  When the event-loop is not running when the routine wants to
> go to sleep it starts it instead of sleeping, checking the semaphore
> each time select returns.

This is too inefficient.

The event-loop should instead be implemented on top of
scm_internal_select.  That way, blocking on I/O will in most cases
simply consist of a merge of the activation conditions and a call to
OS select.  But we still need to implement the repl on top of the
event loop if we're not going to use the interface suggested in my
previous letter.

> Yes, I think this is exactly the same as your proposed solution.

Well, apart from me wanting scm_internal_select be the primitive and
the event loop implemented on top of it.

> The event-loop thingie should be made explicit, so that applications
> that don't want (or can't) use coop threads still can use a central
> event broker.

Yes.  (If we're not going to use the add-select-callback interface.)

/mdj