On 7/15/2014 10:15 PM, Johannes Pfau wrote:
Yes, I actually tried tested that simple implementation with gdc. With
aggressive optimizations the code inlines just fine and it'll generate
the same asm as an access to a volatile variable in C. But it's not
space-effecient: Even if it inlines, the function is still in the
object file as a distinct function. There's TypeInfo and there's the
assert(this), there's an initializer symbol and I guess there could be
copy constructors as well. I expect many bug reports/fixes till we get
a Volatile!T wrapper to be really space-efficient.

D is intended to have a robust enough feature set in order to implement types as library types rather than builtin, and have them operate as good as a builtin type would. These are more general issues, and are not specific to volatile.


3. if you really hate peek/poke calls appearing in the code, you
can use UFCS to make them look like variables
But you cant do REGISTER.peek() |= 0b1;
As you mentioned in the DIP, read-modify-write operations should be
split up, as their semantics are murky.
But not necessarily in user code. REGISTER |= is quite common in C and
it's perfectly safe.

The point is it is not perfectly safe. There is no definition, and certainly no portable definition, as to how many read/write cycles such an operation entails. That's what I meant, and DIP62 says pretty much said the same thing. Please allow me to quote:

"CISC machines may allow other operations to memory than simple load/store operations. The question is then if a read-modify-write operation like 'x++' should translate to 'r = load x; r++; x = store r' or to a single add instruction 'add x;'. This DIP does not dictate any specific behaviour, but this is recommended: If it is known that instructions operating on memory do not work for memory mapped IO as expected, compilers should default to generating a load/modify/store sequence. Otherwise compilers should generate the same code sequence as for regular variables. It is recommended to provide a compiler switch on CISC architectures to allow the user to choose between these two different behaviours."


If people will have to split this up into peek |=
poke that's a step backwards from C.

Support for op= is fairly simple for VolatilePointerToUint to implement, and it can implement them in terms of peek/poke for precise and portable semantics.


A few months
ago you suggested namespaces for D - in addition to modules - which
would have lead to a complexity disaster.
C++ namespaces are now implemented in D, and will they lead to
complexity disaster? Certainly not in the implementation. For users?
I don't think so, but we'll see.
You were initially in favor of an option which would have allowed to
use namespaces in D code as well (namespace A {}). The current
implementation is mostly limited to C++ so that's better, but my point
was that nobody cared about complexity back then.

I objected to several proposals for namespace support that I regarded as significantly more complex.


This just shows the priorities of the project leads:
Desktop apps matter, we add @nogc, c++ namespaces, shared,
immutable, const, -cov, ...
but for embedded systems we won't even add one qualifier.

I don't think this is the right argument. It isn't about embedded
systems should be acknowledged with a qualifier. I see it as about
how often does MMIO logic appear in an actual embedded program? In
the embedded systems I've written, it only appears in a handful of
places. It is not pervasive.

But it's not only about frequency, it's also about convenience and
safety. How often is opDispatch actually used? The synchronized
statement? Nevertheless they are there, because someone thought these
use cases are important enough.

The synchronized statement was something I thought would be widely used. It turns out to be largely a failure. opDispatch is actually pretty simple, and I believe it is an "enabling" feature that hasn't, but will, come into its own.

Nevertheless, we should not follow the trap of "we made a mistake on A, so that justifies making another mistake B". Nor should we say "feature X has reasons A,B,C,D, therefore reason D is justification enough for other things." Changes to D must stand/fall on their own merits.


The perceived importance of a special qualifier for MMIO code is highly
subjective,

Of course. There is no doubt that both yours and my opinions here are 
subjective.


but I think that most embedded programmers would say it's
necessary.

I do believe that a wrapper type around peek/poke satisfies essentially all your necessary requirements, except for transitivity.


In Andrei's Leverage talk he said (5:57): "Consider this:
Convenience, modeling power, efficiency: [...] You gonna have to have a
large language. This is a fact of life. [...]". We have
weak pure/ strong pure & immutable for functional programming, A
complete set of OO primitives, builtin unit tests, code coverage, ... I
think it's a correct argument to say that you think embedded system
programming is not important enough for the additional complexity
introduced by a new qualifier.

That is not what I'm saying at all. Please do not conflate disagreement about the best way to achieve a goal with disagreement about the goal.

I understand that you and others put a lot of work into DIP62. As I said before, it's a very nice example of a well-done DIP.

Reply via email to