On Tue, 2007-07-10 at 12:59 -0400, Sandro Magi wrote:
> On 7/10/07, skaller <[EMAIL PROTECTED]> wrote:

> As long as you can continue useful computation while blocking, and you
> can do so safely, then you have a good concurrency model. 

On blocking: it's the other way around. The current fibre
executes UNTIL it blocks (or dies). 

Blocking is the only way to hand control over 
to another fibre. If a fibre deadlocks, it is removed,
so fibres simply cannot deadlock.

> I'm not sure
> I see wow your approach is more efficient or safer than futures+event
> loops (doesn't seem less efficient either). 

It isn't more efficient or safer because the model DOES use
futures and event loops!

Felix programs are run by a scheduler loop. A 'thread' is just
a continuation. There's a list of them. The scheduler pops 
the top one off the list and runs it until it yields with
a service request or dies.

The scheduler then executes the service request.
For channel I/O: if the channel is ready to be read/written,
then a pointer is moved and the current thread and the one
blocked on the channel are both rescheduled. [goto start]

If the channel is not ready for the I/O, then the current
thread is pushed onto the channels wait list. [goto start]

Notice .. the thread has disappeared! The scheduler has
forgotten it! It is now owned by the channel. And the channel
is owned by some other active thread on the scheduler list,
directly, or indirectly (via other channels and threads).

If this is NOT the case .. the I/O request could never
be serviced and the fact the thread is forgotten is 
just right .. it's unreachable so the garbage collector
simply deletes it.

That's IT! For synchronous scheduling. It's a master list of
active fibres, plus channels with lists of fibres waiting
on some other fibre to write (or read) on them.

The C++ code that does all this is more or less trivial.
Context switching consists of popping a pointer off a list,
and calling

        p=p->resume()

on it -- one list pop, and one virtual function dispatch.
Checking if a channel is ready amounts to checking if
its list of blocked readers (or writers) is a NULL pointer.
Channel transfer consists of popping one fibre off the channel
list and pushing it onto the master scheduler list.

In other words .. the operations are all a couple of lines
of very basic C code. Felix can context switch well in
excess of a million threads in 2 seconds on my AMD64.

So far I covered only synchronous threading. Async events
work by the service holding onto the
fthread pointer until the request -- eg a socket read --
has been completed, then queues the fthread into a 
ready queue.

This async ready queue is only consulted when all the
synchronous threads have died. At that time, a thread
is popped off the async queue and pushed onto the sync
queue.

This is more expensive because the async queue interfaces
pthreads and so the queue object has mutual exclusion locking.
All the operations which block the OS, such as socket I/O,
are handled by forwarding the requests to a server in 
this manner.

We have two standard servers: demux (for sockets etc)
and a timer thread.

At this point we do not have servers for:

(a) SCARY ... Unix signals :)
(b) Interprocess Communication
(c) other stuff, eg Windowing systems ..


> So what you want is functional reactive programming (FRP), which
> provides such dynamic circuit switching. You should definitely look
> into it if you haven't already. 

I have, but my stuff was in the works long before FRP was invented,
so they're just re-inventing my wheel .. :)

> What you describe, basic primitive
> values and combinators to wire circuits, is essentially a dataflow
> graph as built using FRP signals/events + combinators. However, there
> are concurrency dangers in executing this graph naively. See FrTime
> [1] for details. These are the exact same concurrency problems that
> event loops in E solve.

With synchronous threads there are no dangers, other than the usual
problem of making a mess of your code :) I've done that.. it's quite
easy to forget to plug a channel in, so that when a fibre reads it
it suicides .. that may be unexpected but it is well defined
behaviour.

With asynchronous threads (pre-emptive threads) there are
definitely issues .. but whilst Felix DOES provide the programmer
with pre-emptive threading as well as the synchronous threading,
the emphasis is on not needing this stuff: the async I/O system
interfaces to the sync I/O system seamlessly.

Still, once you add the async I/O into the picture lockups
are possible -- and this is entirely unavoidable when you're
reliant on external event sources.

> A 'vat' is pretty much the 'process' abstraction, which I think you'd
> agree is fairly important and well-founded.

No, it is only half a system, so it is meaningless. It is only
when you specify a way processes communicate that you have an
actual model.

>  The vat is the unit of
> concurrency, failure, persistence and resource control. E also
> enforces the property that each 'process' has a single event loop by
> which all computation is driven, and this+persistence turns a process
> into an E vat.

Right. But I still don't know what that achieves .. or how it
is different from Felix.

Every Felix 'pthread' has its own event loop too:

spawn_pthread { .... };

actually spawns a complete new synchronous scheduler with
its own async queue as well. [And until recently it also
spawned its own socket and timer server which was a really
bad idea .. that's fixed now]

This isn't a process because these threads still share memory
and a single garbage collector. However there are channels
for them too, pchannels. Which are a mutex locked synchronisation
primitive.

Major difference here is that pthreads don't get deleted by
the operating system when they deadlock .. they're usually
only reaped when the main process terminates.

-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to