From: | "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> |
Newsgroups: | comp.compilers |
Date: | Sun, 18 Mar 2012 20:35:08 +0100 |
Organization: | cbb software GmbH |
References: | 12-03-012 12-03-041 |
Keywords: | design, history |
Posted-Date: | 20 Mar 2012 18:10:11 EDT |
On Sat, 17 Mar 2012 12:31:13 -0700 (PDT), Rock Brentwood wrote:
> A concrete example of where this distinction proves critical: take a
> look at the Windows API. Never mind the fact that it has over a couple
> thousand system calls, the real issue here is that the OS is
> explicitly message-passing. What you REALLY want is a program that
> runs like this:
> Item 1:
> function f() {
> ... do stuff ... wait for A ...
> while (B) {
> do stuff ... wait for B ... do stuff
> }
> }
> main routine:
> ... do stuff... f() ... do stuff ...
>
> where the waits are places where the program is awaiting events or
> messages. There is no support for this at the *language level* in the
> core of any common language.
This looks exactly like an entry call in Ada 83 [BTW, 83 = 1983]. E.g.
timed entry call:
select
A; -- call the entry A
or delay 1.0;
... -- Do something useful of A does not respond in 1s
end select;
> What Windows does is effectively force you to gut this structure turn
> it inside-out, so that the boundaries of the routine at the
> application level are: (exit) ... wait for A ... ((re-)enter). The re-
> entry is then kicked in by a "callback function" (the Windows'
> equivalent of what in embedded systems is referred to as an interrupt
> handler or other event handler). The paradigm puts handlers out in
> front, thereby effectively forcing you in the "single songwriter
> trying to thread an orchestra into a giant control loop" mode.
There are at least two ends in each communication. The "event controlled
paradigm" tries to simplify the problem by making it looking as if there
were only one place you would program it. This has issues and many problems
do not map onto it. But for half-duplex, multicast topologies it works
well.
> That means routine f() above would have an entry point for each wait
> -- including the one INSIDE the control flow structure. That means, in
> turn, the control flow structure is decimated and you see an explicit
> finite state machine crop up.
Which is a procedural view on the issue: the monitor, co-routine etc. There
is an object-oriented counterpart: a protected object, which can be safely
used by concurrent threads while maintaining its internal state. Sometimes
decomposition based on protected objects works better, sometimes it works
poor.
Anyway, both threads (tasks) and protected objects are present at the
language level.
The problem is not in having these primitives. The problem is in
integration them into the types system. And a larger problem is
composability. Either tasks or objects become unsafe when put together.
They are much safer than low-level stuff like raw messaging, events,
semaphores, but still not safe enough for software design.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Return to the
comp.compilers page.
Search the
comp.compilers archives again.