October 20, 2011
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/

October 20, 2011
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).
October 20, 2011
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.


1 2
Next ›   Last »