March 02, 2015
On 2/27/15 11:18 PM, ketmar wrote:
> On Fri, 27 Feb 2015 20:51:54 +0000, deadalnix wrote:
>
>> On Friday, 27 February 2015 at 04:13:03 UTC, Steven Schveighoffer wrote:
>>> In that case, you shouldn't be subject to any kind of race conditions.
>>> But we can't make the library/language based on this assumption. Your
>>> case is the exceptional case.
>>>
>>>
>> His case is not @safe, so we can ignore that problem.
>
> the compiler tends to disagree:
>
> === test.d ===
> int myglobal;
>
> class A {
>    ~this () @safe { if (myglobal == 42) assert(0); }
> }
>
> void main () {
>    auto a = new A;
> }
> ======
>
> dmd -w -c -o- test.d
>
> wow! no warnings, no errors!
>

I think in this case, the compiler can probably statically reject the code. But there are definitely ways around that, so I don't think full compliance is possible. I also think it's wrong-headed to have the compiler reject such code based on a GC deficiency.

The only solution is to have GC-allocated data be destroyed in the same thread it's allocated in. This brings the multi-threaded program into the same realm as yours -- looks like one thread for unshared data :)

-Steve
March 03, 2015
On Mon, 02 Mar 2015 15:43:42 -0500, Steven Schveighoffer wrote:

> On 2/27/15 11:18 PM, ketmar wrote:
>> On Fri, 27 Feb 2015 20:51:54 +0000, deadalnix wrote:
>>
>>> On Friday, 27 February 2015 at 04:13:03 UTC, Steven Schveighoffer wrote:
>>>> In that case, you shouldn't be subject to any kind of race
>>>> conditions.
>>>> But we can't make the library/language based on this assumption. Your
>>>> case is the exceptional case.
>>>>
>>>>
>>> His case is not @safe, so we can ignore that problem.
>>
>> the compiler tends to disagree:
>>
>> === test.d ===
>> int myglobal;
>>
>> class A {
>>    ~this () @safe { if (myglobal == 42) assert(0); }
>> }
>>
>> void main () {
>>    auto a = new A;
>> }
>> ======
>>
>> dmd -w -c -o- test.d
>>
>> wow! no warnings, no errors!
>>
>>
> I think in this case, the compiler can probably statically reject the code.

it can't, 'cause it doesn't know how the given object is going to be allocated. i may completely skip GC and use my own allocator, which has no troubles with threads, for example.

March 03, 2015
On 3/2/15 10:38 PM, ketmar wrote:
> On Mon, 02 Mar 2015 15:43:42 -0500, Steven Schveighoffer wrote:
>
>> I think in this case, the compiler can probably statically reject the
>> code.
>
> it can't, 'cause it doesn't know how the given object is going to be
> allocated. i may completely skip GC and use my own allocator, which has
> no troubles with threads, for example.
>

Classes are expected to be GC allocated. But the point is moot, because statically rejecting this does not guarantee abuse will not happen. And I don't think this restriction should be enshrined in the language anyway -- it's quite possible to write a GC that behaves correctly here.

-Steve
March 03, 2015
On Saturday, 28 February 2015 at 04:18:38 UTC, ketmar wrote:
>> His case is not @safe, so we can ignore that problem.
>
> the compiler tends to disagree:
>
> === test.d ===
> int myglobal;
>
> class A {
>   ~this () @safe { if (myglobal == 42) assert(0); }
> }
>
> void main () {
>   auto a = new A;
> }
> ======
>
> dmd -w -c -o- test.d
>
> wow! no warnings, no errors!

And what's the problem?
March 03, 2015
On 3/3/15 9:22 AM, Kagamin wrote:
> On Saturday, 28 February 2015 at 04:18:38 UTC, ketmar wrote:
>>> His case is not @safe, so we can ignore that problem.
>>
>> the compiler tends to disagree:
>>
>> === test.d ===
>> int myglobal;
>>
>> class A {
>>   ~this () @safe { if (myglobal == 42) assert(0); }
>> }
>>
>> void main () {
>>   auto a = new A;
>> }
>> ======
>>
>> dmd -w -c -o- test.d
>>
>> wow! no warnings, no errors!
>
> And what's the problem?

This:

void main()
{
   myglobal = 42;
   spawnThread((){myglobal = 0; auto a = new A; a = null; while(1){}});

   // trigger assert in A.dtor.
   int[] mem;
   while(1)
   {
      mem.length += 10000;
   }
}

-Steve
March 03, 2015
On Tuesday, 3 March 2015 at 14:42:40 UTC, Steven Schveighoffer wrote:
>    // trigger assert in A.dtor.

You mean assert breaks something?
March 03, 2015
On 3/3/15 9:57 AM, Kagamin wrote:
> On Tuesday, 3 March 2015 at 14:42:40 UTC, Steven Schveighoffer wrote:
>>    // trigger assert in A.dtor.
>
> You mean assert breaks something?

OK, if you want to be pedantic:

int *myglobal;

repeat same code, but access what myglobal points to instead of setting to 42. Memory corruption is what @safe code is trying to prevent. This would lead to memory corruption.

-Steve
March 03, 2015
On Tue, 03 Mar 2015 14:22:15 +0000, Kagamin wrote:

> On Saturday, 28 February 2015 at 04:18:38 UTC, ketmar wrote:
>>> His case is not @safe, so we can ignore that problem.
>>
>> the compiler tends to disagree:
>>
>> === test.d ===
>> int myglobal;
>>
>> class A {
>>   ~this () @safe { if (myglobal == 42) assert(0); }
>> }
>>
>> void main () {
>>   auto a = new A;
>> }
>> ======
>>
>> dmd -w -c -o- test.d
>>
>> wow! no warnings, no errors!
> 
> And what's the problem?

the answer is in your quotation.

March 03, 2015
On Tue, 03 Mar 2015 08:53:03 -0500, Steven Schveighoffer wrote:

> Classes are expected to be GC allocated.
O_O

classes are expected to be heap-allocated, methinks, and heap is not necessary garbage collected.

> it's quite possible to write a GC that behaves correctly here.

it's *almost* possible, i'd say. or, in another words, it's not possible without turning threads to garbage-collected resource (at least it's not possible without havy and dirty hackery and/or support from compiler itself).

March 04, 2015
On Tuesday, 3 March 2015 at 18:38:11 UTC, Steven Schveighoffer wrote:
> int *myglobal;
>
> repeat same code, but access what myglobal points to instead of setting to 42. Memory corruption is what @safe code is trying to prevent. This would lead to memory corruption.

You mean, the class destructor accesses a GC-allocated memory? That's indeed unsafe, but unrelated to globals.