May 29, 2012
On 29-05-2012 14:19, Dmitry Olshansky wrote:
> On 29.05.2012 16:07, Regan Heath wrote:
>>
>> According to the docs here:
>> http://dlang.org/class.html#synchronized-functions
>>
>> A synchronized function locks "this" and as "this" is exposed
>> publicly... In the following code the "lock" statement and "synchronized
>> void bar" lock the same mutex.
>>
>> class Foo {
>> synchronized void bar() { ...statements... }
>> }
>>
>> void main()
>> {
>> Foo foo = new Foo();
>> lock(foo)
>> {
>> ...statements...
>> }
>> }
>>
>>> But locking on another class rather than something specifically
>>> intended as a mutex does seem to me like it's asking for trouble.
>
> I'd be darned but every Object in D has monitor fields. If I'm not
> mistaken it's the mutex you are looking for ;)
>
>

Indeed they do, and therefore each object must eat an entire word of memory for questionable gain.

Generalized object monitors is the worst idea in programming language and virtual machine design, ever.

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
May 29, 2012
On 29-05-2012 10:37, deadalnix wrote:
> Le 29/05/2012 01:35, Alex Rønne Petersen a écrit :
>> On 29-05-2012 01:24, Jonathan M Davis wrote:
>>> On Tuesday, May 29, 2012 01:11:49 Alex Rønne Petersen wrote:
>>>> I have no idea how synchronized classes work; they are not a documented
>>>> feature of the language. We have synchronized functions which
>>>> synchronize on the this reference. Perhaps synchronized classes just
>>>> make all functions in a class do this.
>>>
>>> Per TDPL, having individually synchronized functions is illegal.
>>> Either all
>>> of the functions in a class are synchronized or none of them are.
>>> Putting
>>> synchronized on a function should actually be illegal. It belongs
>>> only on
>>> classes or in synchronized blocks, never on functions.
>>>
>>> Now, unfortuntately, I don't believe that the compiler enforces any of
>>> that
>>> right now, so you end up synchronizing indivdual functions rather than
>>> whole
>>> classes, but the synchronized functions themselves should function the
>>> same.
>>>
>>>> Either way, this is a fundamental language design fallacy. This is
>>>> anti-pattern number one when it comes to locking:
>>>>
>>>> * http://stackoverflow.com/a/251668/438034
>>>> * http://msdn.microsoft.com/en-us/library/ms173179.aspx (The lock and
>>>> SyncLock Keywords section)
>>>
>>> Well, then you should probably be arguing about the design of
>>> synchronized
>>> classes/functions rather than synchronized(this). However, given the
>>> design of
>>> synchronized classes, synchronized(this) would probably never be
>>> appropriate.
>>> If you're using a synchronized class, then you don't need it. And if
>>> you're
>>> not using a synchronized class, then you shouldn't be synchronizing your
>>> class. I would definitely think that synchronized blocks should
>>> synchronize on
>>> something else, since they're trying to lock a much smaller area than an
>>> entire class.
>>>
>>> - Jonathan M Davis
>>
>> I don't think arguing about them makes sense at this point. Way too much
>> code would break if we changed the semantics. I'd consider it a mistake
>> and a lesson learned, rather.
>>
>> But I take it you agree that synchronized (this) and similar
>> "uncontrollable" synchronization blocks should be avoided?
>>
>
> I would say that breaking things here, with the right deprecation
> process, is the way to go.

Well, we could deprecate it over time, but it certainly can't be a day-to-day thing.

>
> shared isn't working properly ATM, so anyway, things will have to change
> in regard of shared memory support in the language.

And it never will. ;)

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
May 29, 2012
On 29.05.2012 16:26, Alex Rønne Petersen wrote:
> On 29-05-2012 14:19, Dmitry Olshansky wrote:
>> On 29.05.2012 16:07, Regan Heath wrote:
>>>
>>> According to the docs here:
>>> http://dlang.org/class.html#synchronized-functions
>>>
>>> A synchronized function locks "this" and as "this" is exposed
>>> publicly... In the following code the "lock" statement and "synchronized
>>> void bar" lock the same mutex.
>>>
>>> class Foo {
>>> synchronized void bar() { ...statements... }
>>> }
>>>
>>> void main()
>>> {
>>> Foo foo = new Foo();
>>> lock(foo)
>>> {
>>> ...statements...
>>> }
>>> }
>>>
>>>> But locking on another class rather than something specifically
>>>> intended as a mutex does seem to me like it's asking for trouble.
>>
>> I'd be darned but every Object in D has monitor fields. If I'm not
>> mistaken it's the mutex you are looking for ;)
>>
>>
>
> Indeed they do, and therefore each object must eat an entire word of
> memory for questionable gain.
>
> Generalized object monitors is the worst idea in programming language
> and virtual machine design, ever.
>

Agreed, awfuly crippled design for a language with Thread-local by default.
Looks like we have 'oh my god, what were they thinking' moment here.
If anything I'd rather re-implement the whole v-table infrastructure via mixins, templates & friends.

-- 
Dmitry Olshansky
May 29, 2012
On 2012-05-29 14:29, Dmitry Olshansky wrote:

> Agreed, awfuly crippled design for a language with Thread-local by default.
> Looks like we have 'oh my god, what were they thinking' moment here.
> If anything I'd rather re-implement the whole v-table infrastructure via
> mixins, templates & friends.

I'm pretty sure that was decided long before D 1.0 and way way longer before D2 where TLS was introduced.

-- 
/Jacob Carlborg
May 29, 2012
Le 29/05/2012 14:26, Alex Rønne Petersen a écrit :
> On 29-05-2012 14:19, Dmitry Olshansky wrote:
>> On 29.05.2012 16:07, Regan Heath wrote:
>>>
>>> According to the docs here:
>>> http://dlang.org/class.html#synchronized-functions
>>>
>>> A synchronized function locks "this" and as "this" is exposed
>>> publicly... In the following code the "lock" statement and "synchronized
>>> void bar" lock the same mutex.
>>>
>>> class Foo {
>>> synchronized void bar() { ...statements... }
>>> }
>>>
>>> void main()
>>> {
>>> Foo foo = new Foo();
>>> lock(foo)
>>> {
>>> ...statements...
>>> }
>>> }
>>>
>>>> But locking on another class rather than something specifically
>>>> intended as a mutex does seem to me like it's asking for trouble.
>>
>> I'd be darned but every Object in D has monitor fields. If I'm not
>> mistaken it's the mutex you are looking for ;)
>>
>>
>
> Indeed they do, and therefore each object must eat an entire word of
> memory for questionable gain.
>
> Generalized object monitors is the worst idea in programming language
> and virtual machine design, ever.
>

Every fucking things MUST BE AN OBJECT :D So let's lock on ANY OBJECT !
May 29, 2012
Le 29/05/2012 14:26, Alex Rønne Petersen a écrit :
>>
>> shared isn't working properly ATM, so anyway, things will have to change
>> in regard of shared memory support in the language.
>
> And it never will. ;)
>

It has been successful done in other languages and has proven itself useful. This is a difficult backend problem, but it can be solved.
May 29, 2012
On Monday, 28 May 2012 at 23:55:04 UTC, Alex Rønne Petersen wrote:
> On 29-05-2012 01:46, Jonathan M Davis wrote:
>> On Tuesday, May 29, 2012 01:38:25 Alex Rønne Petersen wrote:
>>> I should probably add that Java learned it long ago, and yet we adopted
>>> it anyway... blergh.
>>
>> The "lesson learned" from Java that TDPL enumerates is the mistake of having
>> synchronized on functions rather than entire classes, but clearly even that is
>> currently TDPL-only and not actually properly implemented yet.
>>
>> - Jonathan M Davis
>
> But synchronized on entire classes is exactly equally flawed... the fundamental problem is still that they synchronize on a public resource.

Sorry, I don't quite follow...

1) locking on a public resource
=> BAD, high risk.

2) Adding GC.callLocked(), allowing a generic delegate to claim the GC lock
https://github.com/D-Programming-Language/druntime/pull/213
=> no-brainer, i.e. no risk?

May 29, 2012
On 29-05-2012 17:52, deadalnix wrote:
> Le 29/05/2012 14:26, Alex Rønne Petersen a écrit :
>>>
>>> shared isn't working properly ATM, so anyway, things will have to change
>>> in regard of shared memory support in the language.
>>
>> And it never will. ;)
>>
>
> It has been successful done in other languages and has proven itself
> useful. This is a difficult backend problem, but it can be solved.

The problem is not in the compiler back end, the problem is that shared is completely useless as it is. There's no bridge from shared to unshared, making it impossible to work with any real world code base.

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
May 29, 2012
On 29-05-2012 18:41, Jess wrote:
> On Monday, 28 May 2012 at 23:55:04 UTC, Alex Rønne Petersen wrote:
>> On 29-05-2012 01:46, Jonathan M Davis wrote:
>>> On Tuesday, May 29, 2012 01:38:25 Alex Rønne Petersen wrote:
>>>> I should probably add that Java learned it long ago, and yet we adopted
>>>> it anyway... blergh.
>>>
>>> The "lesson learned" from Java that TDPL enumerates is the mistake of
>>> having
>>> synchronized on functions rather than entire classes, but clearly
>>> even that is
>>> currently TDPL-only and not actually properly implemented yet.
>>>
>>> - Jonathan M Davis
>>
>> But synchronized on entire classes is exactly equally flawed... the
>> fundamental problem is still that they synchronize on a public resource.
>
> Sorry, I don't quite follow...
>
> 1) locking on a public resource
> => BAD, high risk.
>
> 2) Adding GC.callLocked(), allowing a generic delegate to claim the GC lock
> https://github.com/D-Programming-Language/druntime/pull/213
> => no-brainer, i.e. no risk?
>

druntime is the low-level runtime library of D. This discussion is about high-level class design.

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
May 29, 2012
On 29-05-2012 18:57, Alex Rønne Petersen wrote:
> On 29-05-2012 18:41, Jess wrote:
>> On Monday, 28 May 2012 at 23:55:04 UTC, Alex Rønne Petersen wrote:
>>> On 29-05-2012 01:46, Jonathan M Davis wrote:
>>>> On Tuesday, May 29, 2012 01:38:25 Alex Rønne Petersen wrote:
>>>>> I should probably add that Java learned it long ago, and yet we
>>>>> adopted
>>>>> it anyway... blergh.
>>>>
>>>> The "lesson learned" from Java that TDPL enumerates is the mistake of
>>>> having
>>>> synchronized on functions rather than entire classes, but clearly
>>>> even that is
>>>> currently TDPL-only and not actually properly implemented yet.
>>>>
>>>> - Jonathan M Davis
>>>
>>> But synchronized on entire classes is exactly equally flawed... the
>>> fundamental problem is still that they synchronize on a public resource.
>>
>> Sorry, I don't quite follow...
>>
>> 1) locking on a public resource
>> => BAD, high risk.
>>
>> 2) Adding GC.callLocked(), allowing a generic delegate to claim the GC
>> lock
>> https://github.com/D-Programming-Language/druntime/pull/213
>> => no-brainer, i.e. no risk?
>>
>
> druntime is the low-level runtime library of D. This discussion is about
> high-level class design.
>

I should also add that the reason I started this thread was to prevent common locking errors induced by the anti-patterns synchronized causes. If you're calling *anything* in the core.memory module, I sure hope you know what you're doing in general.

I really don't think these two issues are connected at all.

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org