logical const is a subset of transitive const

Bill Baxter dnewsgroup at billbaxter.com
Fri Sep 14 15:04:10 PDT 2007


Steven Schveighoffer wrote:
> "Bill Baxter" wrote
>> Janice Caron wrote:
>>> On 9/14/07, Steven Schveighoffer <schveiguy at yahoo.com> wrote:
>>>> I disagree.  Declaring it const means that calling that function will 
>>>> not
>>>> change any members of the date object.
>>>>
>>>> Declaring it pure means that it will always return the same value, which
>>>> means it would be safe for multiple threads to access without locking (I 
>>>> am
>>>> very new to this concept, but I got all my knowledge from wikipedia:
>>>> http://en.wikipedia.org/wiki/Functional_programming)
>>> I stand corrected. Yes, you are right. A function can be declared
>>> const and still read and write global variables, and hence not be
>>> threadsafe.
>> Whoa.  Excuse me while I get up off the floor after having the rug pulled 
>> out from under me.
>>
>> Was the point of const then perhaps more micro-level optimizations? Things 
>> like if "X is const then I can assume the value in this register is still 
>> valid without having to re-fetch from main memory".  For instance
>>     X* foo;
>>     foo.bar = 10;
>>     func(foo);  // takes fully_const X*
>>
>>     // In C++ const the next line requires re-fetching foo.bar
>>     // from memory,
>>     // because func might actually change fully_const X*.
>>     // In D it could reuse the value in register, or even assume it's
>>     // still the constant 10.
>>
>>     Y biff = foo.bar;
>>
>> Just a guess.  IANACW (compiler writer).
> 
> IAANACW (I am also not a compiler writer).
> 
> You are wrong in your assumption.  Even in a single thread, I can circumvent 
> the constness by having a global non-const pointer to my object, and using 
> that object.  Very bad implementation, but it would not break the rules. 
> For example:
> 
> X mutableinstance;
> 
> class X
> {
>    int bar;
> }
> 
> func(const X myref)
> {
>   mutableinstance.bar++; // I can do this because I'm not changing myref
> }
> 
> myfoolishfunc()
> {
>   X foo = new X;
>   mutableinstance = foo;
>   foo.bar = 10;
>   func(foo); // increments foo.bar because mutableinstance is foo
> 
>   int biff = foo.bar; // biff now should be 11.
> }

Yeh, ok.  It's perverse, but it does show clearly that even transitive 
const is not enough to guarantee anything.   But that example is 
definitely teetering on the edge of undefined behavior.  It depends on 
whether you take "const X myref" to mean "this function will not modify 
the contents of myref" vs "this function will not modify myref via the 
myref handle".   It might be reasonable to say that if you alias a const 
argument then you're in undefined behavior territory.

> (BTW you cannot assume 
> the register is still valid after calling func because func is allowed to 
> change registers, even if it is pure).

Well, if so, that rather pokes a hole in my example.  So I have no clue 
what great optimizations Walter has in mind.  He should just tell us.

> However, in multithreaded land, it is questionable whether you can assume 
> that foo will not change even with pure functions because another thread 
> could conceivably come along and wreck foo while you are calling your pure 
> function.

Isn't that "you're on your own" territory there?  Sure some other thread 
could be changing foo, but if you're using that sort of threading then 
it was up to you to properly mutex protect foo.  I think the purpose of 
pure is more to support constructs with more limited scope, like 
parallel foreach loops.

> Multithreaded programming is hard.  const sucks.  There are a lot of strange 
> rules.  Not being a compiler writer, I have no idea what compiler advantages 
> transitive const has over logical const, but I'm going to defer to Walter on 
> that because he is the compiler writer, and he seems to be very hard-set on 
> it. 

If there is some clear advantage to transitive, then it shouldn't be too 
difficult for Walter to explain what it is.   It may even be beneficial. 
  Writing things down is a good way to discover flaws in one's own 
logic.  There's a reason journals actually require people to write the 
whole article rather than just allowing them to publish their 
conclusions.  :-)

--bb



More information about the Digitalmars-d mailing list