www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Shared Delegates

reply Andrew Wiley <wiley.andrew.j gmail.com> writes:
--00151773eb4210b89d04af848895
Content-Type: text/plain; charset=ISO-8859-1

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?

--00151773eb4210b89d04af848895
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

Okay, I realize there have been some discussions about this, but I have a f=
ew questions about shared delegates because right now they are definitely b=
roken, but I&#39;m not sure how.<div>Take this code example:</div><div><br>

</div><div><div>synchronized class Thing {</div><div>=A0 =A0 =A0 =A0 void d=
oSomeWork(void delegate() work) {</div><div>=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 work();</div><div>=A0 =A0 =A0 =A0 }</div><div>=A0 =A0 =A0 =A0 void work() =
{}</div><div>}</div><div><br></div>
<div>
void main() {</div><div>=A0 =A0 =A0 =A0 auto th =3D new Thing();</div><div>=
=A0 =A0 =A0 =A0 th.doSomeWork(&amp;th.work);</div><div>}</div></div><div><b=
r></div><div>This doesn&#39;t compile because the type of &quot;&amp;th.wor=
k&quot; is &quot;void delegate() shared&quot;, which cannot be cast implici=
tly to &quot;void delegate()&quot;.</div>

<div>My first question would be whether that type is correct. It&#39;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&#39;m just not clear on the exact meaning of &quot;shared&quot; in genera=
l, but it seems like whether the data is shared or not is irrelevant when t=
he 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.</div>

<div>If that type is correct, the problem is that &quot;void delegate() sha=
red&quot; doesn&#39;t parse as a type (there is a workaround because you ca=
n create variables of this type through alias and typeof).</div><div><br>

</div><div>What, exactly, is wrong here?</div>

--00151773eb4210b89d04af848895--
Oct 17 2011
next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-10-17 20:33:59 +0000, Andrew Wiley <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. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Oct 17 2011
next sibling parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 17.10.2011 22:43, schrieb Michel Fortin:
 On 2011-10-17 20:33:59 +0000, Andrew Wiley <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 -- Kind Regards Benjamin Thaut
Oct 17 2011
parent Benjamin Thaut <code benjamin-thaut.de> writes:
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. -- Kind Regards Benjamin Thaut
Oct 17 2011
prev sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-10-19 20:36:37 +0000, Andrew Wiley <wiley.andrew.j gmail.com> said:

 
 On Mon, Oct 17, 2011 at 3:43 PM, Michel Fortin 
 <michel.fortin michelf.com>wrote:
 
 On 2011-10-17 20:33:59 +0000, Andrew Wiley <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.

Actually, I've been thinking about this some more, and I think that the delegate should only implicitly convert if the argument types are safe to share across threads as well.

I disagree.
 If I had a class that looked like this:
 synchronized class Thing2 {
        void doSomeWork(int i) {}
        void doSomeOtherWork(Thing2 t) {}
        void work() {}
 }
 
 The actual argument type in doSomeOtherWork is required to be shared(Thing2)
 (which isn't a problem here because Thing2 is a synchronized class, but you
 see the point).

Is it? Whether the argument was shared or not, the thread in which the function code runs can only access thread-local data from that thread, including the arguments and global variables. It won't be able to send references to non-shared data to other threads just because its context pointer is shared (or synchronized). -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Oct 19 2011
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2011-10-19 21:53:12 +0000, Andrew Wiley <wiley.andrew.j gmail.com> said:

 
 On Wed, Oct 19, 2011 at 4:11 PM, Michel Fortin 
 <michel.fortin michelf.com>wrote:
 
 On 2011-10-19 20:36:37 +0000, Andrew Wiley <wiley.andrew.j gmail.com>
 said:
 
 
 On Mon, Oct 17, 2011 at 3:43 PM, Michel Fortin <michel.fortin michelf.com
 **wrote:

On 2011-10-17 20:33:59 +0000, Andrew Wiley <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.

Actually, I've been thinking about this some more, and I think that the delegate should only implicitly convert if the argument types are safe to share across threads as well.

I disagree. If I had a class that looked like this:
 synchronized class Thing2 {
 void doSomeWork(int i) {}
 void doSomeOtherWork(Thing2 t) {}
 void work() {}
 }
 
 The actual argument type in doSomeOtherWork is required to be
 shared(Thing2)
 (which isn't a problem here because Thing2 is a synchronized class, but
 you
 see the point).

Is it? Whether the argument was shared or not, the thread in which the function code runs can only access thread-local data from that thread, including the arguments and global variables. It won't be able to send references to non-shared data to other threads just because its context pointer is shared (or synchronized).

The problem is that what's behind the context pointer is also shared. If this delegate is just a closure, that doesn't matter, since the context is basically immutable. The problem I see is when the delegate is actually a member function that stores data in an object. If it was passed a reference to non-shared data, it could store that reference in a shared object, breaking transitive shared.

I think I see what you mean, but you're probably missing one little detail… Implicitly casting the delegate to non-shared won't change what compiled code the delegate points to. The compiled code of the delegate was compiled with a shared 'this' pointer in mind. Since the attributes of the 'this' pointer is engraved in the compiled code when the function was compiled, changing the attributes of the delegate (a mere pointer to that code) won't change how the function treats 'this'. And since the 'this' pointer is shared inside the function you can't assign anything to it that isn't shared. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Oct 19 2011
prev sibling next sibling parent Andrew Wiley <wiley.andrew.j gmail.com> writes:
--00151774047414e44904af8c7b71
Content-Type: text/plain; charset=ISO-8859-1

On Tue, Oct 18, 2011 at 12:53 AM, Benjamin Thaut <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>
 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.

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>

I just fail at searching, or should I file it? --00151774047414e44904af8c7b71 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Tue, Oct 18, 2011 at 12:53 AM, Benjamin Thaut= <span dir=3D"ltr">&lt;<a href=3D"mailto:code benjamin-thaut.de">code benja= min-thaut.de</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote" sty= le=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"> Am 17.10.2011 22:43, schrieb Michel Fortin:<div><div></div><div class=3D"h5= "><br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> On 2011-10-17 20:33:59 +0000, Andrew Wiley &lt;<a href=3D"mailto:wiley.andr= ew.j gmail.com" target=3D"_blank">wiley.andrew.j gmail.com</a>&gt; said:<br=

<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> <br> Okay, I realize there have been some discussions about this, but I have a<b= r> few questions about shared delegates because right now they are<br> definitely<br> broken, but I&#39;m not sure how.<br> Take this code example:<br> <br> synchronized class Thing {<br> void doSomeWork(void delegate() work) {<br> work();<br> }<br> void work() {}<br> }<br> <br> void main() {<br> auto th =3D new Thing();<br> th.doSomeWork(&amp;th.work);<br> }<br> <br> This doesn&#39;t compile because the type of &quot;&amp;th.work&quot; is &q= uot;void delegate()<br> shared&quot;, which cannot be cast implicitly to &quot;void delegate()&quot= ;.<br> My first question would be whether that type is correct. It&#39;s true<br> that the<br> data pointer of the delegate points to a shared object, but given that<br> the<br> function locks it, does that really matter in this case? I guess I&#39;m ju= st<br> not clear on the exact meaning of &quot;shared&quot; in general, but it see= ms like<br> whether the data is shared or not is irrelevant when the delegate<br> points to<br> a public member of a synchronized class. If it was a delegate pointing<br> to a<br> private/protected member (which should be illegal in this case), that<br> would<br> not be true.<br> If that type is correct, the problem is that &quot;void delegate() shared&q= uot;<br> doesn&#39;t parse as a type (there is a workaround because you can create<b= r> variables of this type through alias and typeof).<br> <br> What, exactly, is wrong here?<br> </blockquote> <br> I think what&#39;s wrong is that a shared delegate should implicitly conver= t<br> to a non-shared one. The delegate is shared since it can be called<br> safely from any thread, and making it non-shared only prevent you from<br> propagating it to more thread so it&#39;s not harmful in any way.<br> <br> </blockquote> <br></div></div> I reported this exact issue already a few months ago and simply didn&#39;t = get any comment on it. If you really try to use shared to are going to hit = more such problems.<br> <br> See the shared section of my blogpost: <a href=3D"http://3d.benjamin-thaut.= de/?p=3D18" target=3D"_blank">http://3d.benjamin-thaut.de/?<u></u>p=3D18</a=
<br><font color=3D"#888888"><br></font></blockquote><div><br></div><div>Ah=

Did I just fail at searching, or should I file it?=A0</div> </div><br> --00151774047414e44904af8c7b71--
Oct 17 2011
prev sibling next sibling parent Andrew Wiley <wiley.andrew.j gmail.com> writes:
--90e6ba47677fe8a3b604af8d1cdb
Content-Type: text/plain; charset=ISO-8859-1

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<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><
 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?

is no intention in changing the way shared works.

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. --90e6ba47677fe8a3b604af8d1cdb Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Tue, Oct 18, 2011 at 1:11 AM, Benjamin Thaut = <span dir=3D"ltr">&lt;<a href=3D"mailto:code benjamin-thaut.de">code benjam= in-thaut.de</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote" styl= e=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"> Am 18.10.2011 08:03, schrieb Andrew Wiley:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"><div class=3D"im"> On Tue, Oct 18, 2011 at 12:53 AM, Benjamin Thaut &lt;<a href=3D"mailto:code= benjamin-thaut.de" target=3D"_blank">code benjamin-thaut.de</a><br></div><= div class=3D"im"> &lt;mailto:<a href=3D"mailto:code benjamin-thaut.de" target=3D"_blank">code= benjamin-thaut.de</a><u></u>&gt;&gt; wrote:<br> <br> =A0 =A0Am 17.10.2011 22:43, schrieb Michel Fortin:<br> <br> =A0 =A0 =A0 =A0On 2011-10-17 20:33:59 +0000, Andrew Wiley<br></div><div><d= iv></div><div class=3D"h5"> =A0 =A0 =A0 =A0&lt;<a href=3D"mailto:wiley.andrew.j gmail.com" target=3D"_= blank">wiley.andrew.j gmail.com</a> &lt;mailto:<a href=3D"mailto:wiley.andr= ew.j gmail.com" target=3D"_blank">wiley.andrew.j gmail.<u></u>com</a>&gt;&g= t; said:<br> <br> <br> =A0 =A0 =A0 =A0 =A0 =A0Okay, I realize there have been some discussions ab= out this,<br> =A0 =A0 =A0 =A0 =A0 =A0but I have a<br> =A0 =A0 =A0 =A0 =A0 =A0few questions about shared delegates because right = now they are<br> =A0 =A0 =A0 =A0 =A0 =A0definitely<br> =A0 =A0 =A0 =A0 =A0 =A0broken, but I&#39;m not sure how.<br> =A0 =A0 =A0 =A0 =A0 =A0Take this code example:<br> <br> =A0 =A0 =A0 =A0 =A0 =A0synchronized class Thing {<br> =A0 =A0 =A0 =A0 =A0 =A0void doSomeWork(void delegate() work) {<br> =A0 =A0 =A0 =A0 =A0 =A0work();<br> =A0 =A0 =A0 =A0 =A0 =A0}<br> =A0 =A0 =A0 =A0 =A0 =A0void work() {}<br> =A0 =A0 =A0 =A0 =A0 =A0}<br> <br> =A0 =A0 =A0 =A0 =A0 =A0void main() {<br> =A0 =A0 =A0 =A0 =A0 =A0auto th =3D new Thing();<br> =A0 =A0 =A0 =A0 =A0 =A0th.doSomeWork(&amp;th.work);<br> =A0 =A0 =A0 =A0 =A0 =A0}<br> <br> =A0 =A0 =A0 =A0 =A0 =A0This doesn&#39;t compile because the type of &quot;= &amp;th.work&quot; is &quot;void<br> =A0 =A0 =A0 =A0 =A0 =A0delegate()<br> =A0 =A0 =A0 =A0 =A0 =A0shared&quot;, which cannot be cast implicitly to &q= uot;void delegate()&quot;.<br> =A0 =A0 =A0 =A0 =A0 =A0My first question would be whether that type is cor= rect.<br> =A0 =A0 =A0 =A0 =A0 =A0It&#39;s true<br> =A0 =A0 =A0 =A0 =A0 =A0that the<br> =A0 =A0 =A0 =A0 =A0 =A0data pointer of the delegate points to a shared obj= ect, but<br> =A0 =A0 =A0 =A0 =A0 =A0given that<br> =A0 =A0 =A0 =A0 =A0 =A0the<br> =A0 =A0 =A0 =A0 =A0 =A0function locks it, does that really matter in this = case? I<br> =A0 =A0 =A0 =A0 =A0 =A0guess I&#39;m just<br> =A0 =A0 =A0 =A0 =A0 =A0not clear on the exact meaning of &quot;shared&quot= ; in general, but<br> =A0 =A0 =A0 =A0 =A0 =A0it seems like<br> =A0 =A0 =A0 =A0 =A0 =A0whether the data is shared or not is irrelevant whe= n the<br> =A0 =A0 =A0 =A0 =A0 =A0delegate<br> =A0 =A0 =A0 =A0 =A0 =A0points to<br> =A0 =A0 =A0 =A0 =A0 =A0a public member of a synchronized class. If it was = a<br> =A0 =A0 =A0 =A0 =A0 =A0delegate pointing<br> =A0 =A0 =A0 =A0 =A0 =A0to a<br> =A0 =A0 =A0 =A0 =A0 =A0private/protected member (which should be illegal i= n this<br> =A0 =A0 =A0 =A0 =A0 =A0case), that<br> =A0 =A0 =A0 =A0 =A0 =A0would<br> =A0 =A0 =A0 =A0 =A0 =A0not be true.<br> =A0 =A0 =A0 =A0 =A0 =A0If that type is correct, the problem is that &quot;= void<br> =A0 =A0 =A0 =A0 =A0 =A0delegate() shared&quot;<br> =A0 =A0 =A0 =A0 =A0 =A0doesn&#39;t parse as a type (there is a workaround = because you<br> =A0 =A0 =A0 =A0 =A0 =A0can create<br> =A0 =A0 =A0 =A0 =A0 =A0variables of this type through alias and typeof).<b= r> <br> =A0 =A0 =A0 =A0 =A0 =A0What, exactly, is wrong here?<br> <br> <br> =A0 =A0 =A0 =A0I think what&#39;s wrong is that a shared delegate should i= mplicitly<br> =A0 =A0 =A0 =A0convert<br> =A0 =A0 =A0 =A0to a non-shared one. The delegate is shared since it can be= called<br> =A0 =A0 =A0 =A0safely from any thread, and making it non-shared only preve= nt<br> =A0 =A0 =A0 =A0you from<br> =A0 =A0 =A0 =A0propagating it to more thread so it&#39;s not harmful in an= y way.<br> <br> <br> =A0 =A0I reported this exact issue already a few months ago and simply<br> =A0 =A0didn&#39;t get any comment on it. If you really try to use shared t= o are<br> =A0 =A0going to hit more such problems.<br> <br> =A0 =A0See the shared section of my blogpost:<br></div></div> =A0 =A0<a href=3D"http://3d.benjamin-thaut.de/?__p=3D18" target=3D"_blank"=
http://3d.benjamin-thaut.de/?_<u></u>_p=3D18</a> &lt;<a href=3D"http://3d.=

u></u>p=3D18</a>&gt;<div class=3D"im"> <br> <br> <br> Ah, I was looking through the bug reports and didn&#39;t see this exact bug= .<br> Did I just fail at searching, or should I file it?<br> <br> </div></blockquote> <br> I didn&#39;t file it yet, so file it. I do however think that currently the= re is no intention in changing the way shared works.<div><div></div><div cl= ass=3D"h5"><br></div></div></blockquote><div><br></div><div>This much is cl= early a bug, and Michel&#39;s explanation of how shared delegates should wo= rk makes a lot of sense.=A0</div> <div>As for the synchronized classes that synchronize access to not-really-= shared members, well, I don&#39;t think that&#39;s changing. The problem is= that the compiler can&#39;t *guarantee* that the reference you hold is the= only reference. TDPL has a discussion of why an &quot;A owns B, so A&#39;s= lock should be good enough for B&quot; wasn&#39;t implemented.</div> <div>As for the overloading on shared, the idea there was that you should r= eally 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 r= oot 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 w= on&#39;t know when you fall, you&#39;ll just see the corruption when you hi= t the floor.</div> </div> --90e6ba47677fe8a3b604af8d1cdb--
Oct 17 2011
prev sibling next sibling parent Andrew Wiley <wiley.andrew.j gmail.com> writes:
--90e6ba47677fd79ac504af8d4869
Content-Type: text/plain; charset=ISO-8859-1

On Tue, Oct 18, 2011 at 1:48 AM, Andrew Wiley <wiley.andrew.j gmail.com>wrote:

 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<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><
 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?

is no intention in changing the way shared works.

delegates should work makes a lot of sense.

Filed as http://d.puremagic.com/issues/show_bug.cgi?id=6823 For now, I can just cast things at the call site. --90e6ba47677fd79ac504af8d4869 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Tue, Oct 18, 2011 at 1:48 AM, Andrew Wiley <s= pan dir=3D"ltr">&lt;<a href=3D"mailto:wiley.andrew.j gmail.com">wiley.andre= w.j gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote" st= yle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"> <div class=3D"gmail_quote"><div><div></div><div class=3D"h5">On Tue, Oct 18= , 2011 at 1:11 AM, Benjamin Thaut <span dir=3D"ltr">&lt;<a href=3D"mailto:c= ode benjamin-thaut.de" target=3D"_blank">code benjamin-thaut.de</a>&gt;</sp= an> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> Am 18.10.2011 08:03, schrieb Andrew Wiley:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"><div> On Tue, Oct 18, 2011 at 12:53 AM, Benjamin Thaut &lt;<a href=3D"mailto:code= benjamin-thaut.de" target=3D"_blank">code benjamin-thaut.de</a><br></div><= div> &lt;mailto:<a href=3D"mailto:code benjamin-thaut.de" target=3D"_blank">code= benjamin-thaut.de</a><u></u>&gt;&gt; wrote:<br> <br> =A0 =A0Am 17.10.2011 22:43, schrieb Michel Fortin:<br> <br> =A0 =A0 =A0 =A0On 2011-10-17 20:33:59 +0000, Andrew Wiley<br></div><div><d= iv></div><div> =A0 =A0 =A0 =A0&lt;<a href=3D"mailto:wiley.andrew.j gmail.com" target=3D"_= blank">wiley.andrew.j gmail.com</a> &lt;mailto:<a href=3D"mailto:wiley.andr= ew.j gmail.com" target=3D"_blank">wiley.andrew.j gmail.<u></u>com</a>&gt;&g= t; said:<br> <br> <br> =A0 =A0 =A0 =A0 =A0 =A0Okay, I realize there have been some discussions ab= out this,<br> =A0 =A0 =A0 =A0 =A0 =A0but I have a<br> =A0 =A0 =A0 =A0 =A0 =A0few questions about shared delegates because right = now they are<br> =A0 =A0 =A0 =A0 =A0 =A0definitely<br> =A0 =A0 =A0 =A0 =A0 =A0broken, but I&#39;m not sure how.<br> =A0 =A0 =A0 =A0 =A0 =A0Take this code example:<br> <br> =A0 =A0 =A0 =A0 =A0 =A0synchronized class Thing {<br> =A0 =A0 =A0 =A0 =A0 =A0void doSomeWork(void delegate() work) {<br> =A0 =A0 =A0 =A0 =A0 =A0work();<br> =A0 =A0 =A0 =A0 =A0 =A0}<br> =A0 =A0 =A0 =A0 =A0 =A0void work() {}<br> =A0 =A0 =A0 =A0 =A0 =A0}<br> <br> =A0 =A0 =A0 =A0 =A0 =A0void main() {<br> =A0 =A0 =A0 =A0 =A0 =A0auto th =3D new Thing();<br> =A0 =A0 =A0 =A0 =A0 =A0th.doSomeWork(&amp;th.work);<br> =A0 =A0 =A0 =A0 =A0 =A0}<br> <br> =A0 =A0 =A0 =A0 =A0 =A0This doesn&#39;t compile because the type of &quot;= &amp;th.work&quot; is &quot;void<br> =A0 =A0 =A0 =A0 =A0 =A0delegate()<br> =A0 =A0 =A0 =A0 =A0 =A0shared&quot;, which cannot be cast implicitly to &q= uot;void delegate()&quot;.<br> =A0 =A0 =A0 =A0 =A0 =A0My first question would be whether that type is cor= rect.<br> =A0 =A0 =A0 =A0 =A0 =A0It&#39;s true<br> =A0 =A0 =A0 =A0 =A0 =A0that the<br> =A0 =A0 =A0 =A0 =A0 =A0data pointer of the delegate points to a shared obj= ect, but<br> =A0 =A0 =A0 =A0 =A0 =A0given that<br> =A0 =A0 =A0 =A0 =A0 =A0the<br> =A0 =A0 =A0 =A0 =A0 =A0function locks it, does that really matter in this = case? I<br> =A0 =A0 =A0 =A0 =A0 =A0guess I&#39;m just<br> =A0 =A0 =A0 =A0 =A0 =A0not clear on the exact meaning of &quot;shared&quot= ; in general, but<br> =A0 =A0 =A0 =A0 =A0 =A0it seems like<br> =A0 =A0 =A0 =A0 =A0 =A0whether the data is shared or not is irrelevant whe= n the<br> =A0 =A0 =A0 =A0 =A0 =A0delegate<br> =A0 =A0 =A0 =A0 =A0 =A0points to<br> =A0 =A0 =A0 =A0 =A0 =A0a public member of a synchronized class. If it was = a<br> =A0 =A0 =A0 =A0 =A0 =A0delegate pointing<br> =A0 =A0 =A0 =A0 =A0 =A0to a<br> =A0 =A0 =A0 =A0 =A0 =A0private/protected member (which should be illegal i= n this<br> =A0 =A0 =A0 =A0 =A0 =A0case), that<br> =A0 =A0 =A0 =A0 =A0 =A0would<br> =A0 =A0 =A0 =A0 =A0 =A0not be true.<br> =A0 =A0 =A0 =A0 =A0 =A0If that type is correct, the problem is that &quot;= void<br> =A0 =A0 =A0 =A0 =A0 =A0delegate() shared&quot;<br> =A0 =A0 =A0 =A0 =A0 =A0doesn&#39;t parse as a type (there is a workaround = because you<br> =A0 =A0 =A0 =A0 =A0 =A0can create<br> =A0 =A0 =A0 =A0 =A0 =A0variables of this type through alias and typeof).<b= r> <br> =A0 =A0 =A0 =A0 =A0 =A0What, exactly, is wrong here?<br> <br> <br> =A0 =A0 =A0 =A0I think what&#39;s wrong is that a shared delegate should i= mplicitly<br> =A0 =A0 =A0 =A0convert<br> =A0 =A0 =A0 =A0to a non-shared one. The delegate is shared since it can be= called<br> =A0 =A0 =A0 =A0safely from any thread, and making it non-shared only preve= nt<br> =A0 =A0 =A0 =A0you from<br> =A0 =A0 =A0 =A0propagating it to more thread so it&#39;s not harmful in an= y way.<br> <br> <br> =A0 =A0I reported this exact issue already a few months ago and simply<br> =A0 =A0didn&#39;t get any comment on it. If you really try to use shared t= o are<br> =A0 =A0going to hit more such problems.<br> <br> =A0 =A0See the shared section of my blogpost:<br></div></div> =A0 =A0<a href=3D"http://3d.benjamin-thaut.de/?__p=3D18" target=3D"_blank"=
http://3d.benjamin-thaut.de/?_<u></u>_p=3D18</a> &lt;<a href=3D"http://3d.=

u></u>p=3D18</a>&gt;<div> <br> <br> <br> Ah, I was looking through the bug reports and didn&#39;t see this exact bug= .<br> Did I just fail at searching, or should I file it?<br> <br> </div></blockquote> <br> I didn&#39;t file it yet, so file it. I do however think that currently the= re is no intention in changing the way shared works.<div><div></div><div><b= r></div></div></blockquote><div><br></div></div></div><div>This much is cle= arly a bug, and Michel&#39;s explanation of how shared delegates should wor= k makes a lot of sense.=A0</div> </div></blockquote><div><br></div><div>Filed as=A0<a href=3D"http://d.purem= agic.com/issues/show_bug.cgi?id=3D6823">http://d.puremagic.com/issues/show_= bug.cgi?id=3D6823</a></div><div>For now, I can just cast things at the call= site.</div> </div> --90e6ba47677fd79ac504af8d4869--
Oct 18 2011
prev sibling next sibling parent Andrew Wiley <wiley.andrew.j gmail.com> writes:
--20cf303bff601aab6d04afaccd66
Content-Type: text/plain; charset=ISO-8859-1

On Mon, Oct 17, 2011 at 3:43 PM, Michel Fortin <michel.fortin michelf.com>wrote:

 On 2011-10-17 20:33:59 +0000, Andrew Wiley <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.

delegate should only implicitly convert if the argument types are safe to share across threads as well. If I had a class that looked like this: synchronized class Thing2 { void doSomeWork(int i) {} void doSomeOtherWork(Thing2 t) {} void work() {} } The actual argument type in doSomeOtherWork is required to be shared(Thing2) (which isn't a problem here because Thing2 is a synchronized class, but you see the point). These same rules should apply to shared delegates. I'm not sure exactly how this works for value types because they're always safe to pass as arguments yet shared(int) clearly isn't the same as int, but the rules will be the same for delegates as for member functions. With that in mind, I'm not sure exactly how the implicit conversions should work, but the argument types should always be properly share-able. --20cf303bff601aab6d04afaccd66 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Mon, Oct 17, 2011 at 3:43 PM, Michel Fortin <= span dir=3D"ltr">&lt;<a href=3D"mailto:michel.fortin michelf.com">michel.fo= rtin michelf.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote"= style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"> <div><div></div><div class=3D"h5">On 2011-10-17 20:33:59 +0000, Andrew Wile= y &lt;<a href=3D"mailto:wiley.andrew.j gmail.com" target=3D"_blank">wiley.a= ndrew.j gmail.com</a>&gt; said:<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> <br> Okay, I realize there have been some discussions about this, but I have a<b= r> few questions about shared delegates because right now they are definitely<= br> broken, but I&#39;m not sure how.<br> Take this code example:<br> <br> synchronized class Thing {<br> =A0 =A0 =A0 =A0void doSomeWork(void delegate() work) {<br> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0work();<br> =A0 =A0 =A0 =A0}<br> =A0 =A0 =A0 =A0void work() {}<br> }<br> <br> void main() {<br> =A0 =A0 =A0 =A0auto th =3D new Thing();<br> =A0 =A0 =A0 =A0th.doSomeWork(&amp;th.work);<br> }<br> <br> This doesn&#39;t compile because the type of &quot;&amp;th.work&quot; is &q= uot;void delegate()<br> shared&quot;, which cannot be cast implicitly to &quot;void delegate()&quot= ;.<br> My first question would be whether that type is correct. It&#39;s true that= the<br> data pointer of the delegate points to a shared object, but given that the<= br> function locks it, does that really matter in this case? I guess I&#39;m ju= st<br> not clear on the exact meaning of &quot;shared&quot; in general, but it see= ms like<br> whether the data is shared or not is irrelevant when the delegate points to= <br> a public member of a synchronized class. If it was a delegate pointing to a= <br> private/protected member (which should be illegal in this case), that would= <br> not be true.<br> If that type is correct, the problem is that &quot;void delegate() shared&q= uot;<br> doesn&#39;t parse as a type (there is a workaround because you can create<b= r> variables of this type through alias and typeof).<br> <br> What, exactly, is wrong here?<br> </blockquote> <br></div></div> I think what&#39;s wrong is that a shared delegate should implicitly conver= t 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 propagatin= g it to more thread so it&#39;s not harmful in any way.<br> <font color=3D"#888888"> <br></font></blockquote><div><br></div><div>Actually, I&#39;ve been thinkin= g about this some more, and I think that the delegate should only implicitl= y convert if the argument types are safe to share across threads as well.</= div> <div>If I had a class that looked like this:</div><div>synchronized class T= hing2 {<br>=A0 =A0 =A0 =A0void doSomeWork(int i) {}</div><div>=A0 =A0 =A0 = =A0void doSomeOtherWork(Thing2 t) {}<br>=A0 =A0 =A0 =A0void work() {}<br>}<= br><br></div><div>The actual argument type in doSomeOtherWork is required t= o be shared(Thing2) (which isn&#39;t a problem here because Thing2 is a syn= chronized class, but you see the point).</div> <div>These same rules should apply to shared delegates. I&#39;m not sure ex= actly how this works for value types because they&#39;re always safe to pas= s as arguments yet shared(int) clearly isn&#39;t the same as int, but the r= ules will be the same for delegates as for member functions.</div> <div><br></div><div>With that in mind, I&#39;m not sure exactly how the imp= licit conversions should work, but the argument types should always be prop= erly share-able.</div><div>=A0</div></div><br> --20cf303bff601aab6d04afaccd66--
Oct 19 2011
prev sibling next sibling parent Andrew Wiley <wiley.andrew.j gmail.com> writes:
--90e6ba1efd92fbc1e304afaddecf
Content-Type: text/plain; charset=ISO-8859-1

On Wed, Oct 19, 2011 at 4:11 PM, Michel Fortin <michel.fortin michelf.com>wrote:

 On 2011-10-19 20:36:37 +0000, Andrew Wiley <wiley.andrew.j gmail.com>
 said:


 On Mon, Oct 17, 2011 at 3:43 PM, Michel Fortin <michel.fortin michelf.com
**wrote:

On 2011-10-17 20:33:59 +0000, Andrew Wiley <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.

Actually, I've been thinking about this some more, and I think that the delegate should only implicitly convert if the argument types are safe to share across threads as well.

I disagree. If I had a class that looked like this:
 synchronized class Thing2 {
       void doSomeWork(int i) {}
       void doSomeOtherWork(Thing2 t) {}
       void work() {}
 }

 The actual argument type in doSomeOtherWork is required to be
 shared(Thing2)
 (which isn't a problem here because Thing2 is a synchronized class, but
 you
 see the point).

Is it? Whether the argument was shared or not, the thread in which the function code runs can only access thread-local data from that thread, including the arguments and global variables. It won't be able to send references to non-shared data to other threads just because its context pointer is shared (or synchronized).

this delegate is just a closure, that doesn't matter, since the context is basically immutable. The problem I see is when the delegate is actually a member function that stores data in an object. If it was passed a reference to non-shared data, it could store that reference in a shared object, breaking transitive shared. --90e6ba1efd92fbc1e304afaddecf Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Wed, Oct 19, 2011 at 4:11 PM, Michel Fortin <= span dir=3D"ltr">&lt;<a href=3D"mailto:michel.fortin michelf.com">michel.fo= rtin michelf.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote"= style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"> <div class=3D"im">On 2011-10-19 20:36:37 +0000, Andrew Wiley &lt;<a href=3D= "mailto:wiley.andrew.j gmail.com" target=3D"_blank">wiley.andrew.j gmail.co= m</a>&gt; said:<br> <br> </div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-l= eft:1px #ccc solid;padding-left:1ex"><div class=3D"im"> <br> On Mon, Oct 17, 2011 at 3:43 PM, Michel Fortin &lt;<a href=3D"mailto:michel= .fortin michelf.com" target=3D"_blank">michel.fortin michelf.com</a>&gt;<u>= </u>wrote:<br> <br> </div><div><div></div><div class=3D"h5"><blockquote class=3D"gmail_quote" s= tyle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> On 2011-10-17 20:33:59 +0000, Andrew Wiley &lt;<a href=3D"mailto:wiley.andr= ew.j gmail.com" target=3D"_blank">wiley.andrew.j gmail.com</a>&gt;<br> said:<br> <br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> Okay, I realize there have been some discussions about this, but I have a<b= r> few questions about shared delegates because right now they are definitely<= br> broken, but I&#39;m not sure how.<br> Take this code example:<br> <br> synchronized class Thing {<br> void doSomeWork(void delegate() work) {<br> work();<br> }<br> void work() {}<br> }<br> <br> void main() {<br> auto th =3D new Thing();<br> th.doSomeWork(&amp;th.work);<br> }<br> <br> This doesn&#39;t compile because the type of &quot;&amp;th.work&quot; is &q= uot;void delegate()<br> shared&quot;, which cannot be cast implicitly to &quot;void delegate()&quot= ;.<br> My first question would be whether that type is correct. It&#39;s true that= <br> the<br> data pointer of the delegate points to a shared object, but given that the<= br> function locks it, does that really matter in this case? I guess I&#39;m ju= st<br> not clear on the exact meaning of &quot;shared&quot; in general, but it see= ms like<br> whether the data is shared or not is irrelevant when the delegate points<br=

a public member of a synchronized class. If it was a delegate pointing to<b= r> a<br> private/protected member (which should be illegal in this case), that<br> would<br> not be true.<br> If that type is correct, the problem is that &quot;void delegate() shared&q= uot;<br> doesn&#39;t parse as a type (there is a workaround because you can create<b= r> variables of this type through alias and typeof).<br> <br> What, exactly, is wrong here?<br> </blockquote> <br> I think what&#39;s wrong is that a shared delegate should implicitly conver= t to<br> a non-shared one. The delegate is shared since it can be called safely from= <br> any thread, and making it non-shared only prevent you from propagating it t= o<br> more thread so it&#39;s not harmful in any way.<br> </blockquote> <br></div></div><div class=3D"im"> Actually, I&#39;ve been thinking about this some more, and I think that the= <br> delegate should only implicitly convert if the argument types are safe to<b= r> share across threads as well.<br> </div></blockquote> <br> I disagree.<div class=3D"im"><br> <br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> If I had a class that looked like this:<br> synchronized class Thing2 {<br> =A0 =A0 =A0 void doSomeWork(int i) {}<br> =A0 =A0 =A0 void doSomeOtherWork(Thing2 t) {}<br> =A0 =A0 =A0 void work() {}<br> }<br> <br> The actual argument type in doSomeOtherWork is required to be shared(Thing2= )<br> (which isn&#39;t a problem here because Thing2 is a synchronized class, but= you<br> see the point).<br> </blockquote> <br></div> Is it? Whether the argument was shared or not, the thread in which the func= tion code runs can only access thread-local data from that thread, includin= g the arguments and global variables. It won&#39;t be able to send =A0refer= ences to non-shared data to other threads just because its context pointer = is shared (or synchronized).<div> <div></div><div class=3D"h5"><br> <br></div></div></blockquote><div><br></div><div>The problem is that what&#= 39;s behind the context pointer is also shared. If this delegate is just a = closure, that doesn&#39;t matter, since the context is basically immutable.= </div> <div>The problem I see is when the delegate is actually a member function t= hat stores data in an object. If it was passed a reference to non-shared da= ta, it could store that reference in a shared object, breaking transitive s= hared.=A0</div> </div> --90e6ba1efd92fbc1e304afaddecf--
Oct 19 2011
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Wed, 19 Oct 2011 20:51:25 -0400, Michel Fortin <michel.fortin michelf.com>
wrote:
 On 2011-10-19 21:53:12 +0000, Andrew Wiley <wiley.andrew.j gmail.com> said:

[snip] Also, I how shared works is being misunderstood. Making a class synchronized should limit all member functions and field to being shared or immutable, but it doesn't place any limits on the argument to the member functions. So in the below: synchronized class Thing2 { void doSomeWork(int i) {} void doSomeOtherWork(Thing2 t) {} void work() {} } i is of type int, not shared(int).
Oct 19 2011
prev sibling parent Andrew Wiley <wiley.andrew.j gmail.com> writes:
--001517740474839e8004afb3d05a
Content-Type: text/plain; charset=ISO-8859-1

On Wed, Oct 19, 2011 at 9:38 PM, Robert Jacques <sandford jhu.edu> wrote:

 On Wed, 19 Oct 2011 20:51:25 -0400, Michel Fortin <
 michel.fortin michelf.com> wrote:

 On 2011-10-19 21:53:12 +0000, Andrew Wiley <wiley.andrew.j gmail.com>
 said:

[snip] Also, I how shared works is being misunderstood. Making a class synchronized should limit all member functions and field to being shared or immutable, but it doesn't place any limits on the argument to the member functions. So in the below: synchronized class Thing2 { void doSomeWork(int i) {} void doSomeOtherWork(Thing2 t) {} void work() {} } i is of type int, not shared(int).

Ah, I see, so I can pass unshared data or references to unshared data into member functions, and the type system keeps me from saving them to member fields because member fields will be flagged as shared, but the arguments need not be. That makes a lot more sense. Sorry for the noise. --001517740474839e8004afb3d05a Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Wed, Oct 19, 2011 at 9:38 PM, Robert Jacques = <span dir=3D"ltr">&lt;<a href=3D"mailto:sandford jhu.edu">sandford jhu.edu<= /a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:= 0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"> <div class=3D"im">On Wed, 19 Oct 2011 20:51:25 -0400, Michel Fortin &lt;<a = href=3D"mailto:michel.fortin michelf.com" target=3D"_blank">michel.fortin m= ichelf.com</a>&gt; wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"> On 2011-10-19 21:53:12 +0000, Andrew Wiley &lt;<a href=3D"mailto:wiley.andr= ew.j gmail.com" target=3D"_blank">wiley.andrew.j gmail.com</a>&gt; said:<br=

<br></div> [snip]<br> <br> Also, I how shared works is being misunderstood. Making a class synchronize= d should limit all member functions and field to being shared or immutable,= but it doesn&#39;t place any limits on the argument to the member function= s. So in the below:<div class=3D"im"> <br> <br> synchronized class Thing2 {<br> =A0 =A0 =A0 =A0void doSomeWork(int i) {}<br> =A0 =A0 =A0 =A0void doSomeOtherWork(Thing2 t) {}<br> =A0 =A0 =A0 =A0void work() {}<br> }<br> <br></div> i is of type int, not shared(int).<br></blockquote><div><br></div><div><br>= </div><div>Ah, I see, so I can pass unshared data or references to unshared= data into member functions, and the type system keeps me from saving them = to member fields because member fields will be flagged as shared, but the a= rguments need not be. That makes a lot more sense.</div> <div>Sorry for the noise.=A0</div></div><br> --001517740474839e8004afb3d05a--
Oct 19 2011