May 30, 2012
On 30.05.2012 3:02, Andrei Alexandrescu wrote:
> On 5/29/12 3:06 PM, Dmitry Olshansky wrote:
>> Again strictly speaking I'm of an opinion that having mutex together
>> with object guarded by it is at least better then 2 separate entities
>> bound together by virtue of code comments :)
>
> Absolutely. I hope you agree that this essentially means you're
> advocating a Java-style approach in which the mutex is implicitly
> present...
>
>> In any case if mutex is desired, object could have had some other base
>> type say SyncObject.
>
> ... albeit not in all objects, only a subhierarchy thereof. I posted the
> same thing. Nice :o).

Great.

>
>> Or use "synchronized class" to that end, what it does now by the way
>> - locks on each method?
>
> TDPL's design of synchronized still hasn't been implemented. The design
> indeed prescribes that all public access to the resource is synchronized.
>

So sad, I recall when I was reading about it it made a lot of sense.

>> More about the actual point is that I've come to believe that there is
>> satisfactory way to implement whatever scheme of polymorphism* we want
>> within the language on top of structs without 'class' and 'interface'
>> keywords, special "flawed" pointer type (i.e. tail-const anyone?), and
>> last but not least without new/delete/finalizes (new/delete are still
>> overridable, hint-hint) madness.
>>
>> Ideally I think it should be possible to lower the whole
>> interface/object/class infrastructure to code that uses structs with
>> direct function pointer tables, etc. Multiple alias this is the key,
>> sadly so, otherwise subtyping to multiple interfaces seem not likely.
>> Then some future compiler may even chose to not provide OOP as built-in
>> but lower to this manual implementation on top of struct(!).
>
> Well all of these are nice thoughts but at some point we must
> acknowledge we're operating within the confines of an already-defined
> language.
>
>> *I like the one in Smalltalk or Obj-C. Also I think exposing type-tag as
>> ordinal (index inside one global master v-table) instead of pointless
>> _hidden_ v-table pointer could be interesting in certain designs.
>> Another idea is to try tackling multi-methods via some form of
>> compressed 2-stage v-table. (my recent work on generalized tries in D
>> sparked some ideas)
>
> Any post that starts with taking an issue against the waste of one word
> and ends advocating Smalltalk and Obj-C is... ho-hum.
>

Well going from practical matters to personal dreams is remarkably easy at 2 AM :)


-- 
Dmitry Olshansky
May 30, 2012
On May 29, 2012, at 4:07 PM, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> On 5/29/12 3:58 PM, Alex Rønne Petersen wrote:
>> On 30-05-2012 00:45, Andrei Alexandrescu wrote:
>>> On 5/29/12 2:57 PM, Alex Rønne Petersen wrote:
>>>> On 29-05-2012 23:33, Andrei Alexandrescu wrote:
>>>>> On 5/29/12 1:37 AM, deadalnix wrote:
>>>>>> I would say that breaking things here, with the right deprecation process, is the way to go.
>>>>> 
>>>>> So what should we use for mutex-based synchronization if we deprecate synchronized classes?
>>>>> 
>>>>> Andrei
>>>> 
>>>> core.sync.mutex
>>> 
>>> That's worse.
>>> 
>>> Andrei
>>> 
>> 
>> I don't agree.
> 
> One simple thing to understand is that core.sync.mutex does everything synchronized objects do, in a much less structured way. So it's tenuous to build an argument that synchronized classes do something wrong but bare, unstructured mutexes do something good.
> 
>> Also, it is faster than object monitors. This was proven
>> by David Simcha recently where he sped up GC allocations by some 40%-ish
>> factor just by changing to a final class derived from core.sync.mutex.
>> And no, that's not a bug in the monitor implementation. It's a
>> limitation of the design.
> 
> We'd need to take a look at that. I recall at a point Bartosz was working on cheap locks using the mutex word as a spin lock in certain circumstances. Anyhow, it's something that would be interesting to look at.

I bet this is because monitors are lazily initialized, so the cost of acquiring a lock is more than just locking the underlying mutex. The implementation for built-in monitors really isnt great. I've been meaning to do something about that.
May 30, 2012
On 30.05.2012 3:04, Andrei Alexandrescu wrote:
> On 5/29/12 3:56 PM, Alex Rønne Petersen wrote:
>> A mutex can be stored privately.
>
> It can, but that doesn't mean it will.
>
>> Any object can be locked on, meaning no
>> lock is effectively protected or private or... anything.
>
> To paraphrase you, "An object can be stored privately".
>
>> It encourages
>> shared locks, which is seriously the worst deadlock inducing
>> anti-pattern to have ever manifested in multithreaded programming.
>
> I'll ignore the hyperbole and continued posturing. Please understand it
> does absolutely nothing in carrying your point. A technical question I
> have is - what are shared locks, and what are superior alternatives to
> them?
>

I'll intervene. Following famous nerd motto "talk is cheap, show me the code" I strongly suggest discussing concrete scenarios. All "prone to deadlock sentiment" is trivia as in buyer beware.

That being said:

class iMutexed
{//implicit intent, explicit details
	Mutex mutex;
}

vs

class iMutexed
{//implicit intent, implicit details

//implicit mutex
}

Makes little to no difference. EXCEPT that designer of the class has no control what so ever over hidden mutex! Thus I believe the best way to fix it is to (say) require obj be a subclass of Mutex in order to use synchronized(obj). i.e.

class iMutexed: Mutex
{//explicit intent, implicit details

}

-- 
Dmitry Olshansky
May 30, 2012
On Wednesday, 30 May 2012 at 06:31:32 UTC, Dmitry Olshansky wrote:
> I'll intervene. Following famous nerd motto "talk is cheap, show me the code" I strongly suggest discussing concrete scenarios. All "prone to deadlock sentiment" is trivia as in buyer beware.
>
> That being said:
>
> class iMutexed
> {//implicit intent, explicit details
> 	Mutex mutex;
> }
>
> vs
>
> class iMutexed
> {//implicit intent, implicit details
>
> //implicit mutex
> }
>
> Makes little to no difference. EXCEPT that designer of the class has no control what so ever over hidden mutex! Thus I believe the best way to fix it is to (say) require obj be a subclass of Mutex in order to use synchronized(obj). i.e.
>
> class iMutexed: Mutex
> {//explicit intent, implicit details
>
> }

Forcing synchronized classes to extend Mutex would make it impossible to create a synchronized subclass of a pre-existing unsynchronized class, would it not? Unless you want to introduce multiple inheritence. If you want to go this way at least make it an interface that has special meaning to the compiler, instead of a class that must be inherited from.
May 30, 2012
On 30.05.2012 12:17, Thiez wrote:
> On Wednesday, 30 May 2012 at 06:31:32 UTC, Dmitry Olshansky wrote:
>> I'll intervene. Following famous nerd motto "talk is cheap, show me
>> the code" I strongly suggest discussing concrete scenarios. All "prone
>> to deadlock sentiment" is trivia as in buyer beware.
>>
>> That being said:
>>
>> class iMutexed
>> {//implicit intent, explicit details
>> Mutex mutex;
>> }
>>
>> vs
>>
>> class iMutexed
>> {//implicit intent, implicit details
>>
>> //implicit mutex
>> }
>>
>> Makes little to no difference. EXCEPT that designer of the class has
>> no control what so ever over hidden mutex! Thus I believe the best way
>> to fix it is to (say) require obj be a subclass of Mutex in order to
>> use synchronized(obj). i.e.
>>
>> class iMutexed: Mutex
>> {//explicit intent, implicit details
>>
>> }
>
> Forcing synchronized classes to extend Mutex would make it impossible to
> create a synchronized subclass of a pre-existing unsynchronized class,
> would it not?

Composition. Obviously synchronized subclasses of existing class sounds strange. The other way around even worse ;)
Wrapping synchronized classes obviously fine.

 Unless you want to introduce multiple inheritence. If you
> want to go this way at least make it an interface that has special
> meaning to the compiler, instead of a class that must be inherited from.

No thanks, multiple inheritance brings too much "coolness". Interface is no go, locks should be  effective.

-- 
Dmitry Olshansky
May 30, 2012
On 30.05.2012 12:33, Dmitry Olshansky wrote:
> On 30.05.2012 12:17, Thiez wrote:
>> On Wednesday, 30 May 2012 at 06:31:32 UTC, Dmitry Olshansky wrote:
>>> I'll intervene. Following famous nerd motto "talk is cheap, show me
>>> the code" I strongly suggest discussing concrete scenarios. All "prone
>>> to deadlock sentiment" is trivia as in buyer beware.
>>>
>>> That being said:
>>>
>>> class iMutexed
>>> {//implicit intent, explicit details
>>> Mutex mutex;
>>> }
>>>
>>> vs
>>>
>>> class iMutexed
>>> {//implicit intent, implicit details
>>>
>>> //implicit mutex
>>> }
>>>
>>> Makes little to no difference. EXCEPT that designer of the class has
>>> no control what so ever over hidden mutex! Thus I believe the best way
>>> to fix it is to (say) require obj be a subclass of Mutex in order to
>>> use synchronized(obj). i.e.
>>>
>>> class iMutexed: Mutex
>>> {//explicit intent, implicit details
>>>
>>> }
>>
>> Forcing synchronized classes to extend Mutex would make it impossible to
>> create a synchronized subclass of a pre-existing unsynchronized class,
>> would it not?
>
> Composition. Obviously synchronized subclasses of existing class sounds
> strange. The other way around even worse ;)
> Wrapping synchronized classes obviously fine.
>

Wrapping by synchronized class....



-- 
Dmitry Olshansky
May 30, 2012
Le 29/05/2012 23:54, Andrei Alexandrescu a écrit :
> On 5/29/12 2:49 PM, Alex Rønne Petersen wrote:
>> On 29-05-2012 23:32, Andrei Alexandrescu wrote:
>>> On 5/29/12 1:35 AM, deadalnix wrote:
>>>> Le 29/05/2012 01:38, Alex Rønne Petersen a écrit :
>>>>> I should probably add that Java learned it long ago, and yet we
>>>>> adopted
>>>>> it anyway... blergh.
>>>>>
>>>>
>>>> That is what I was about to say. No point of doing D if it is to repeat
>>>> previously done errors.
>>>
>>> So what is the lesson Java learned, and how does it address
>>> multithreaded programming in wake of that lesson?
>>>
>>> Andrei
>>
>> It learned that allowing locking on arbitrary objects makes controlling
>> locking (and thus reducing the chance for deadlocks) impossible.
>
> And how does Java address multithreading in general, and those issues in
> particular, today?
>
> Andrei
>

In java, you basically have no concurency built-in. Everything is shared by default, you can lock on anything (which is deadlock and liquid lock prone), you have dumb primitive like wait and notify that are perfect to cause race conditions.

Don't get me wrong, I do a lot of java code, and it isn't that bad in general. But for concurrency, this isn't the model we want.

In a more general scope, the problem of java is to believe that everything is OOP, including concurrency, when they are, in fact, different topics.

D already have much better tools that the one java provide (std.concurency, std.parallelism, TLS by default, transitive type qualifiers, . . .) that most these thing taken from java don't make any sense now.

For instance, what is the point of being able to lock on any object when most of them are thread local ??
May 30, 2012
On 2012-05-29 23:48, Andrei Alexandrescu wrote:

> Don't be hatin'. You'd appreciate the matter considerably more after you
> defined your own language and had its users yell at you for changing
> even a small detail.
>
> The situation is at it is, and there's no need to get agitated. We're
> all on the same boat, trying to make things work out best.

It seems more and more that D2 is not a designed language. Instead new features are just slapped on without considering how it would impact the rest of the language.

-- 
/Jacob Carlborg
May 30, 2012
Le 30/05/2012 01:25, Alex Rønne Petersen a écrit :
> On 30-05-2012 01:22, Andrei Alexandrescu wrote:
>> On 5/29/12 4:17 PM, Alex Rønne Petersen wrote:
>>> On 30-05-2012 01:10, Andrei Alexandrescu wrote:
>>>> On 5/29/12 4:06 PM, Alex Rønne Petersen wrote:
>>>>> Synchronized blocks are good because they
>>>>> operate on an implicit, hidden, global mutex. You can't screw up with
>>>>> that.
>>>>
>>>> I think there's quite some disconnect here. If there's any anti-pattern
>>>> in this discussion, it's operating on an implicit, hidden, global
>>>> mutex.
>>>> Walter agreed to eliminate that from D, but never got around to it.
>>>>
>>>> Andrei
>>>
>>> I'd love to hear why you think this design is problematic as opposed to
>>> one that lets users accidentally expose synchronization issues to
>>> consumers of their API surface, which is what many people end up doing
>>> since synchronized (this) or even synchronized (this.classinfo) are
>>> allowed at all.
>>>
>>> (I've seen countless cases of those two horrible abuses of synchronized
>>> especially from people asking questions on e.g. IRC.)
>>
>> I think the most egregious example is synchronization by global lock
>> done in Python and other languages. It has very nice semantics (stop the
>> world, do something, resume the world), but scales poorly enough to be
>> universally considered a failure. Quite honest I'm shocked that you're
>> advocating it.
>>
>> Andrei
>>
>>
>
> I'm not advocating it. I don't use it myself. I'm just saying that I
> find it to be less of an issue than synchronizing on arbitrary objects,
> because the latter is error-prone.
>
> And yes, Python is a textbook example of synchronization gone completely
> wrong. But that doesn't mean that you don't sometimes have to
> synchronize on some global resource, and in those cases, it can be
> useful syntactic sugar (but certainly not essential).
>

I have to agree with Andrei here. The global mutex isn't the solution either. The mutex should be explicit, and under control (not this).
May 30, 2012
Le 30/05/2012 00:53, Andrei Alexandrescu a écrit :
> On 5/29/12 3:01 PM, Alex Rønne Petersen wrote:
>> On 29-05-2012 23:54, Andrei Alexandrescu wrote:
>>> On 5/29/12 2:49 PM, Alex Rønne Petersen wrote:
>>>> On 29-05-2012 23:32, Andrei Alexandrescu wrote:
>>>>> On 5/29/12 1:35 AM, deadalnix wrote:
>>>>>> Le 29/05/2012 01:38, Alex Rønne Petersen a écrit :
>>>>>>> I should probably add that Java learned it long ago, and yet we
>>>>>>> adopted
>>>>>>> it anyway... blergh.
>>>>>>>
>>>>>>
>>>>>> That is what I was about to say. No point of doing D if it is to
>>>>>> repeat
>>>>>> previously done errors.
>>>>>
>>>>> So what is the lesson Java learned, and how does it address
>>>>> multithreaded programming in wake of that lesson?
>>>>>
>>>>> Andrei
>>>>
>>>> It learned that allowing locking on arbitrary objects makes controlling
>>>> locking (and thus reducing the chance for deadlocks) impossible.
>>>
>>> And how does Java address multithreading in general, and those issues in
>>> particular, today?
>>>
>>> Andrei
>>>
>>
>> It doesn't, and neither does C#. Java still encourages using
>> synchronized, and C# still encourages using lock, but many prominent
>> figures in those programming language communities have written blog
>> posts on why these language constructs are evil and should be avoided.
>
> Some citations (beyond the known fallacies of Java 1.0) would be great.
> Thanks.
>
>> Besides, it seems to me that D can't quite make up its mind. We have TLS
>> by default, and we encourage message-passing (through a library
>> mechanism), and then we have the synchronized statement and attribute.
>> It just seems so incredibly inconsistent. synchronized encourages doing
>> the wrong thing (locks and synchronization).
>
> Each paradigm has its place. Lock-based programming is definitely here
> to stay, and when the paradigm is needed, doing it with synchronized
> objects is better than most alternatives.
>
>
> Andrei

No !

You don't want to synchronize on ANY object. You want to synchronize on explicit mutexes.

See that link for instance : http://msdn.microsoft.com/en-us/library/ms173179.aspx

It is from microsoft, you can't assume it is C# bashing. It says : "Generally, it is best to avoid locking on a public type, or on object instances beyond the control of your application. For example, lock(this) can be problematic if the instance can be accessed publicly, because code beyond your control may lock on the object as well. This could create deadlock situations where two or more threads wait for the release of the same object. Locking on a public data type, as opposed to an object, can cause problems for the same reason."

Given example also create dumb object to lock on them instead of using this/any object.

Time has proven it is the way to go.

I have tracked race condition in large java codebase, and I conclude the same thing as microsoft's guys.