May 31, 2012
On 5/31/12 12:28 AM, Jacob Carlborg wrote:
> On 2012-05-30 21:58, Andrei Alexandrescu wrote:
>> On 5/30/12 12:52 PM, deadalnix wrote:
>>> Ha, this is getting somewhere :D
>>
>> It's getting where I was the whole time.
>>
>> Andrei
>
> No, the original problem was that you can synchronize on ALL objects,
> regardless if they're marked with "synchronized" or not. This it how it
> works today.

I was the whole time where TDPL is, which is not where the implementation is today.

Andrei

May 31, 2012
On 5/30/12 11:47 PM, Jacob Carlborg wrote:
> On 2012-05-30 21:10, Andrei Alexandrescu wrote:
>
>> I see how these can be annoying, but they're not the result of us not
>> designing things. We designed things best we could.
>
> I would say it's not good enough. The whole approach of designing the
> language is wrong.

I understand how frustrating this is. In fact even the way you consider "good" is not nearly good enough. What we need is really more formalization of the language design, something that we're sorely missing. I am sometimes frustrated out of my mind at the lack of rigor and discipline in the process. On the other hand, we march with the troops we have.


Andrei
May 31, 2012
Le 30/05/2012 23:45, Andrei Alexandrescu a écrit :
> On 5/30/12 1:31 PM, Steven Schveighoffer wrote:
>> On Wed, 30 May 2012 15:48:47 -0400, Andrei Alexandrescu
>> <SeeWebsiteForEmail@erdani.org> wrote:
>>> synchronized (object) {
>>> writeln("about to unlock the object");
>>> XXX
>>> writeln("unlocked the object");
>>> }
>>>
>>> Replace "XXX" with a construct that unlocks the object.
>>
>> This is not what we are talking about.
>
> Oh yes it is. "Expose the mutex" means "make the two mutex primitive
> operations lock() and unlock() freely usable against the mutex object".
>

The more I think of it, the more I think it should go throw a @synchrnizable property or something.
May 31, 2012
Le 31/05/2012 07:18, Martin Nowak a écrit :
>>> FWIW, I recently came across the term here:
>>> http://schneide.wordpress.com/tag/liquid-lock/
>>
>> I explained that in another post a few minutes ago, and yes, this is it.
>>
>> Maybe i should write an article on that, I though it was more well known.
>
>> The main problem here is the object the lock is acquired upon: the
>> reference of lastMessage is mutable! We call this a liquid lock,
>> because the lock isn’t as solid as it should be. It’s one of the more
>> hideous multithreading pitfalls as it looks like everything’s fine at
>> first glance.
>
> You should try to name the real root of the bug.
> It's trying to serialize access to a channel by locking the messages.
>
> There is nothing fancy about this, it has nothing to do with mutability
> it's just about locking the wrong resource.

When you lock on a non final resource, you ends up with trouble at some point. A have wasted enough time on that type of problem to know it for sure.
May 31, 2012
Le 31/05/2012 09:49, Andrei Alexandrescu a écrit :
> On 5/31/12 12:28 AM, Jacob Carlborg wrote:
>> On 2012-05-30 21:58, Andrei Alexandrescu wrote:
>>> On 5/30/12 12:52 PM, deadalnix wrote:
>>>> Ha, this is getting somewhere :D
>>>
>>> It's getting where I was the whole time.
>>>
>>> Andrei
>>
>> No, the original problem was that you can synchronize on ALL objects,
>> regardless if they're marked with "synchronized" or not. This it how it
>> works today.
>
> I was the whole time where TDPL is, which is not where the
> implementation is today.
>
> Andrei
>

And which isn't what dlang.org say too. You can agree that this is confusing for everybody.
May 31, 2012
On Thursday, 31 May 2012 at 08:01:14 UTC, Andrei Alexandrescu wrote:
> On 5/30/12 11:47 PM, Jacob Carlborg wrote:
>> On 2012-05-30 21:10, Andrei Alexandrescu wrote:
>>
>>> I see how these can be annoying, but they're not the result of us not
>>> designing things. We designed things best we could.
>>
>> I would say it's not good enough. The whole approach of designing the
>> language is wrong.
>
> I understand how frustrating this is. In fact even the way you consider "good" is not nearly good enough. What we need is really more formalization of the language design, something that we're sorely missing. I am sometimes frustrated out of my mind at the lack of rigor and discipline in the process. On the other hand, we march with the troops we have.
>
>
> Andrei

Please no. This is how C++ is designed and we all know how fucked up that is.

Writing a [rigorous] spec is almost always incorrect since requirements change and unforeseen things come about. Jacob's post illustrates this when the spec is written [in TDPL] before implementing, testing and integrating it.

By making a rigorous spec you exacerbate the problem - it takes more time to write such a spec thus making the time-frame for unforeseen changes larger.
May 31, 2012
On 5/31/12 2:12 AM, foobar wrote:
> On Thursday, 31 May 2012 at 08:01:14 UTC, Andrei Alexandrescu wrote:
>> On 5/30/12 11:47 PM, Jacob Carlborg wrote:
>>> On 2012-05-30 21:10, Andrei Alexandrescu wrote:
>>>
>>>> I see how these can be annoying, but they're not the result of us not
>>>> designing things. We designed things best we could.
>>>
>>> I would say it's not good enough. The whole approach of designing the
>>> language is wrong.
>>
>> I understand how frustrating this is. In fact even the way you
>> consider "good" is not nearly good enough. What we need is really more
>> formalization of the language design, something that we're sorely
>> missing. I am sometimes frustrated out of my mind at the lack of rigor
>> and discipline in the process. On the other hand, we march with the
>> troops we have.
>>
>>
>> Andrei
>
> Please no. This is how C++ is designed and we all know how fucked up
> that is.

Not at all. This is either a misunderstanding, or you lack the faintest idea about the history of C++.

> Writing a [rigorous] spec is almost always incorrect since requirements
> change and unforeseen things come about. Jacob's post illustrates this
> when the spec is written [in TDPL] before implementing, testing and
> integrating it.
>
> By making a rigorous spec you exacerbate the problem - it takes more
> time to write such a spec thus making the time-frame for unforeseen
> changes larger.

No.


Andrei
May 31, 2012
Le 31/05/2012 11:24, Andrei Alexandrescu a écrit :
>> By making a rigorous spec you exacerbate the problem - it takes more
>> time to write such a spec thus making the time-frame for unforeseen
>> changes larger.
>
> No.
>

Can you elaborate on what you are thinking as a process ?
May 31, 2012
On Wed, 30 May 2012 19:29:39 +0100, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> On 5/30/12 10:40 AM, Regan Heath wrote:
>> On Wed, 30 May 2012 18:16:38 +0100, Andrei Alexandrescu
>> <SeeWebsiteForEmail@erdani.org> wrote:
>>> On 5/30/12 9:43 AM, Regan Heath wrote:
>>>> On Wed, 30 May 2012 17:00:43 +0100, Andrei Alexandrescu
>>>> <SeeWebsiteForEmail@erdani.org> wrote:
>>>>
>>>>> On 5/30/12 5:32 AM, Regan Heath wrote:
>>>>>> On Wed, 30 May 2012 10:21:00 +0100, deadalnix <deadalnix@gmail.com>
>>>>>> wrote:
>>>>>>> You don't want to synchronize on ANY object. You want to synchronize
>>>>>>> on explicit mutexes.
>>>>>>
>>>>>> +1 .. this is the key point/issue.
>>>>>
>>>>> TDPL's design only allows for entire synchronized classes (not
>>>>> separate synchronized and unsynchronized methods), which pair mutexes
>>>>> with the data they protect. This is more restrictive than exposing
>>>>> mutexes, but in a good way. We use such a library artifact in C++ at
>>>>> Facebook all the time, to great success.
>>>>
>>>> Can you call pass them to a synchronized statement? i.e.
>>>>
>>>> TDPLStyleSynchClass a = new TDPLStyleSynchClass();
>>>> synchronized(a) {
>>>> }
>>>
>>> Yes. Well I recommend acquiring the text! :o)
>>>
>>>> ... because, if you can, then you're exposing the mutex.
>>>
>>> No.
>>
>> For the purposes of this thread, and the anti-pattern/problem we're
>> discussing, you are.
>
> No. I explained in my previous post that the synchronized statement does not expose locks. This is not a matter of opinion.

Well, it seems some people disagree here.  You are exposing the ability to lock and unlock them, which is the cause of more frequent deadlocks (this assertion comes from the M$ article, my experience with them and it seems from other peoples experience of them as well).  You're not exposing the mutex primitive in any other way, but that's irrelevant for this discussion.  Now, you and I have probably done enough multi-threaded programming with mutexes that we no longer fall into this trap easily, but someone just starting in the world of threading/locking is going to, repeatedly.  If we make it impossible to do it "by default", so they have to think about when/where to apply the mutex, and make the code doing the locking more obvious, then I think we'd go a long way to making it much nicer.

>> It is the combination of synchronized
>> classes/methods (implicit locking) and external synchronized statements
>> (explicit locking) which result in the unexpected, accidental, and hard
>> to see deadlocks we're talking about here.
>
> You can have deadlocks but with synchronized you can't leak locks or doubly-unlock them. With free mutexes you have all of the above.

I'm not suggesting using free mutexes.  I'm suggesting keeping the mutex private inside the object.  Private in this case means cannot be locked by external code.  Which basically means synchronized() is a no go "by default".  This will avoid all the careless accidental deadlock cases involving synchronized w/ synchronized classes/methods and make people actually think about when/where to use their mutexes, instead of just throwing synchronized all about the place.  It is sad, because I really like the scopedness of synchronized but I think it encourages lazy programming in this case.  Note that I said "by default" above, we can definitely provide library interfaces, structs, classes, etc to make synchronized work and if we did it would become a conscious choice the programmer makes to use them, and that should hopefully (because I cannot predict the future) mean less accidental deadlocks.

>>>>> People shouldn't create designs that have synchronized classes
>>>>> referring to one another naively. Designing with mutexes (explicit or
>>>>> implicit) will always create the possibility of deadlock, so examples
>>>>> how that could happen are easy to come across.
>>>>
>>>> True. But in my Example 1
>>>
>>> Your example 1 should not compile.
>>
>> o.. k.. I expected you would get my meaning with the simplified example.
>> Here you are:
>
> [snip]
>
>> Runs and deadlocks immediately.
>
> Sure. As I said, synchronized helps with scoping the locks and unlocks, but not with deadlocks. You can rewrite the example with two bare mutexes just as well.

Again, I'm not suggesting using "bare" or "free" mutexes.  I'm suggesting keeping the mutex private, so that it cannot be locked without it being obvious that that's whats happening.  If it were more obvious there would be less chance of an accidental deadlock, and more chance people would actually use an idea like an "atomic lock of multiple sync primitives" (your synchronized with multiple mutexes and lock ordering), where possible.  Sadly even that idea only works when both locks are taken in the same method/function and only if they can and should be taken at the same time .. which I think is a fairly rare case.

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
May 31, 2012
On Wed, 30 May 2012 20:46:17 +0100, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> On 5/30/12 12:25 PM, Alex Rønne Petersen wrote:
>> On 30-05-2012 21:12, Andrei Alexandrescu wrote:
>>> On 5/30/12 12:03 PM, Steven Schveighoffer wrote:
>>>> On Wed, 30 May 2012 14:32:59 -0400, Andrei Alexandrescu
>>>> <SeeWebsiteForEmail@erdani.org> wrote:
>>>>
>>>>> On 5/30/12 10:47 AM, Steven Schveighoffer wrote:
>>>>>> Yes, you can just use a private mutex. But doesn't that just lead to
>>>>>> recommending not using a feature of the language?
>>>>>
>>>>> I don't think so. Synchronized classes are the unit of scoped locking
>>>>> in D. If you want to do all scoped locking internally, make the class
>>>>> private.
>>>>
>>>> Maybe you didn't read thoroughly the first part of my post (the example
>>>> that shows a deadlock that is easily preventable if the mutex isn't
>>>> exposed).
>>>
>>> The mutex is not exposed.
>>
>> I'm trying really hard to not to be rather impolite here, but I don't
>> know how else to put it: You seem to be the only one who subscribes to
>> this definition of "exposed".
>
> I don't care as long as it's the correct one. The mutex is not exposed.

Ok, how about you tell us what term you want to use for the current state of affairs then, because arguing about this is pointless and I'm happy to use whatever term you deem appropriate (because I couldn't care less what the term is - as long as we all know what is meant, which I believe is the case here).

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/