On Tue, Oct 18, 2011 at 1:11 AM, Benjamin Thaut <code@benjamin-thaut.de> wrote:
Am 18.10.2011 08:03, schrieb Andrew Wiley:
On Tue, Oct 18, 2011 at 12:53 AM, Benjamin Thaut <code@benjamin-thaut.de
<mailto:code@benjamin-thaut.de>> wrote:

   Am 17.10.2011 22:43, schrieb Michel Fortin:

       On 2011-10-17 20:33:59 +0000, Andrew Wiley
       <wiley.andrew.j@gmail.com <mailto:wiley.andrew.j@gmail.com>> said:


           Okay, I realize there have been some discussions about this,
           but I have a
           few questions about shared delegates because right now they are
           definitely
           broken, but I'm not sure how.
           Take this code example:

           synchronized class Thing {
           void doSomeWork(void delegate() work) {
           work();
           }
           void work() {}
           }

           void main() {
           auto th = new Thing();
           th.doSomeWork(&th.work);
           }

           This doesn't compile because the type of "&th.work" is "void
           delegate()
           shared", which cannot be cast implicitly to "void delegate()".
           My first question would be whether that type is correct.
           It's true
           that the
           data pointer of the delegate points to a shared object, but
           given that
           the
           function locks it, does that really matter in this case? I
           guess I'm just
           not clear on the exact meaning of "shared" in general, but
           it seems like
           whether the data is shared or not is irrelevant when the
           delegate
           points to
           a public member of a synchronized class. If it was a
           delegate pointing
           to a
           private/protected member (which should be illegal in this
           case), that
           would
           not be true.
           If that type is correct, the problem is that "void
           delegate() shared"
           doesn't parse as a type (there is a workaround because you
           can create
           variables of this type through alias and typeof).

           What, exactly, is wrong here?


       I think what's wrong is that a shared delegate should implicitly
       convert
       to a non-shared one. The delegate is shared since it can be called
       safely from any thread, and making it non-shared only prevent
       you from
       propagating it to more thread so it's not harmful in any way.


   I reported this exact issue already a few months ago and simply
   didn't get any comment on it. If you really try to use shared to are
   going to hit more such problems.

   See the shared section of my blogpost:
   http://3d.benjamin-thaut.de/?__p=18 <http://3d.benjamin-thaut.de/?p=18>



Ah, I was looking through the bug reports and didn't see this exact bug.
Did I just fail at searching, or should I file it?


I didn't file it yet, so file it. I do however think that currently there is no intention in changing the way shared works.


This much is clearly a bug, and Michel's explanation of how shared delegates should work makes a lot of sense. 
As for the synchronized classes that synchronize access to not-really-shared members, well, I don't think that's changing. The problem is that the compiler can't *guarantee* that the reference you hold is the only reference. TDPL has a discussion of why an "A owns B, so A's lock should be good enough for B" wasn't implemented.
As for the overloading on shared, the idea there was that you should really either be multithreaded or not - trying to implement both shared and non-shared versions of code is generally a bad idea and quite bug prone. If it *might* be shared, just synchronize it. Premature optimization is the root of quite a bit of evil, and trying to make some things thread safe and some things not is walking a tightrope without any sense of balance - you won't know when you fall, you'll just see the corruption when you hit the floor.