Possible @property compromise
TommiT
tommitissari at hotmail.com
Fri Feb 1 05:04:17 PST 2013
On Friday, 1 February 2013 at 04:22:51 UTC, Zach the Mystic wrote:
> On Friday, 1 February 2013 at 03:39:19 UTC, TommiT wrote:
>> On Friday, 1 February 2013 at 03:13:42 UTC, Zach the Mystic
>> wrote:
>>> On Friday, 1 February 2013 at 02:27:30 UTC, TommiT wrote:
>>>> And here's another example of why it is as big of a problem
>>>> as I make it sound to be:
>>>>
>>>> import std.concurrency;
>>>>
>>>> struct Array
>>>> {
>>>> int _len;
>>>>
>>>> length struct // Using Zach's syntax
>>>> {
>>>> @property get() { return _len; }
>>>> alias this = get;
>>>> void opAssign(int rhs) { _len = rhs; }
>>>> }
>>>> }
>>>>
>>>> void func(T)(T t)
>>>> {
>>>> auto v = t;
>>>> v = 10;
>>>> }
>>>>
>>>> void main()
>>>> {
>>>> Array arr;
>>>> spawn(&func!int, arr.length);
>>>> arr.length = 20; // And here we have a data-race.
>>>> // Good luck trying to find these
>>>> // kinds of bugs.
>>>> }
>>>
>>> I'm sorry, I know very little about race conditions. If you
>>> might explain just a little bit about what is happening here,
>>> I'd be in a better position to understand what you're saying.
>>> I really can't say anything other than please describe what
>>> this does and why it's a problem at this time.
>>
>> spawn(&func!int, arr.length);
>>
>> ...creates a new thread and runs the following function call
>> in it:
>> func!(int)(arr.length)
>>
>> While that function call is evaluating in the new thread, the
>> old thread may simultaneosly execute:
>> arr.length = 20;
>>
>> Since both of those threads end up at some point calling
>> arr.length.opAssign and therefore both of them may assign to
>> arr._len simultaneously, that's a data-race. It would be
>> data-race also if only one of them wrote to it and the other
>> one just read it.
>
> I'm familiar with the fact that programmers face endless woes
> with regard to data-races. I thought that D has unshared data
> by default. But since Array arr is defined in main instead of
> outside main, therefore it is sharable between the two threads?
> If two threads have access to the same data, what makes length
> as a property different from length as an int? This problem may
> be over my head for now...
Actually, that example of mine was wrong - it's not a data-race.
I failed to notice that in:
spawn(&func!int, arr.length);
...arr.length is actually converted to int using alias this. My
bad.
Now I'm going to repeat the "spooky modification at a distance"
problem I showed earlier, but this time, instead of writing it in
the new syntax and the new struct behaviour you invented, I write
it using current D syntax:
import std.concurrency;
struct Array
{
int _len;
struct PropType
{
Array* _outer; // In your syntax this was implicit
@property int get()
{
return _outer._len;
}
alias this = get;
void opAssign(int rhs)
{
_outer._len = rhs;
}
}
PropType length;
}
void func(T)(T t)
if (isImplicitlyConvertible!(T,int))
{
// Given that is(T == Array.PropType), then
// all 3 lines below do the same thing:
t = 42;
t.opAssign(42);
t._outer._len = 42;
}
void main()
{
Array arr;
// setting the _outer pointer to the enclosing object:
arr.length._outer = &arr;
assert(arr._len == 0);
func(arr.length); // no conversion to int happening here
assert(arr._len == 42);
}
So, it's possible to modify arr._len just by passing arr.length
by value to a function.
More information about the Digitalmars-d
mailing list