On 7/15/14, 9:25 AM, Johannes Pfau wrote:
DIP62 describes how to solve this problem and make embedded programming
a first-class citizen in D:
http://wiki.dlang.org/DIP62
[snip]

The good:

This is a very crisply-written and comprehensive proposal. It could use a little work (e.g. define the typing relationships among volatile, other qualifiers, and unqualified if any) but completeness is outstanding.

The bad:

I think we should reject this proposal. Moreover, the comprehensiveness of the DIP gives me confidence to assess that no amount of work on the proposal could take it to acceptance.

The ugly:

There's none! Actually there's some nice stuff: we could use a bunch of this proposal to specify alternative approaches such as peek/poke.

=============

My rationale:

* I reject he premise ("The volatile qualifier is often used for embedded programming in C/C++[1]".) At most I agree with "often" as in "you'll see at least one use of volatile in some, maybe many, embedded programs" but not "volatile is present many times in a typical embedded application". Hardware/firmware providers often focus on giving access to low-level hardware facilities by using classic encapsulation and exposing APIs, as opposed to just publishing the raw addresses of various ports. Furthermore, the link given as a justification (http://www.barrgroup.com/Embedded-Systems/How-To/C-Volatile-Keyword) is not support for the statement in text, but instead a mere description of volatile, which is also technically incorrect (viz. the use of volatile with threads).

* "volatile" has been one of the most awkward parts of the C and C++ specifications. If we're to learn of anything about it, it's we must stay away from it. It is extremely heavy for what it provides.

* Currently C++ defines observable behavior as "reads and writes of volatile variables and sequences of calls to certain library functions". There is only a small burden associated with sequences of function calls, but the volatile parts are complicating the specification enormously. We'd be better off specifying sequences of calls to functions as defined behavior.

* Adding qualifiers is heavy for the language definition and implementation. Probably they're the most impactful artifact to add.

* Transitivity is only partially justified. For immutable and shared data, transitivity is motivated by code access patterns that chase pointers, but for volatile data there's no hardware reality reflected by transitivity: MMIO only pertains simple address ranges, not node-based volatile structures. The justification in section "Transitivity" is valid but puts undue emphasis on obscure interrupt service routines; even C doesn't go that far (instead it just limits the functions such routines may call).

* The DIP is correct in mentioning that "volatility" is a property of the memory location so it should apply to the respective variable's type, as opposed to just letting the variable have a regular type and then unsafely relying on calls to e.g. peek and poke. But here's a practicality argument that's been already mentioned - such volatile data is rare and classic encapsulation techniques can be applied to it.

* The scalability aspect should be emphasized: a large system may have more need to synchronize threads or to characterize parts of it as functional (pure + immutable). In contrast, a large embedded system does not manifest a proportionally larger presence of volatile data.

==============

I think an approach based on functions peek/poke is a lot more promising. D programs must define sequences of std calls anyway, otherwise even the simplest programs that use writeln("What's your name?") followed by a readln() are incorrect. So in a way peek/poke come for "free".

Clearly an approach that adds a qualifier would have superior abstraction capabilities, but my experience with C++ (both specification and use) has been that the weight to power ratio of volatile is enormous.


Andrei

Reply via email to