synchronized (this[.classinfo]) in druntime and phobos

Steven Schveighoffer schveiguy at yahoo.com
Fri Jun 1 05:52:45 PDT 2012


On Fri, 01 Jun 2012 08:38:45 -0400, Dmitry Olshansky  
<dmitry.olsh at gmail.com> wrote:

> On 01.06.2012 16:26, deadalnix wrote:
>>  Here is what I ended up to think is the best
>> solution :
>>
>> synchronized classes exists. By default, they can't be use as parameter
>> for synchronized(something) .
>>
>> synchronized(something) will be valid is something provide
>> opSynchronized(scope delegate void()) or something similar. Think
>> opApply here. The synchronized statement is rewritten in a call to that
>> delegate.
>>
>> Here are the benefit of such an approach :
>> 1/ Lock and unlock are not exposed. You can only use them by pair.
>> 2/ You cannot lock on any object, so you avoid most liquid locks and
>> don't waste memory.
>> 3/ synchronized classes ensure that a class can be shared and it
>> internal are protected from concurrent access.
>> 4/ It is not possible possible by default to lock on synchronized
>> classes's instances. It grant better control over the lock and it is now
>> clear which piece of code is responsible of it.
>> 5/ The design allow the programmer to grant the permission to lock on
>> synchronized classes's instances if he/she want to.
>> 6/ It is now possible to synchronize on a broader range of user defined
>> stuffs.
>>
>> The main drawback is the same as opApply : return (and break/continue
>> but it is less relevant for opSynchronized). Solution to this problem
>> have been proposed in the past using compiler and stack magic.
>>
>> It open door for stuff like :
>> ReadWriteLock rw;
>> synchronized(rw.read) {
>>
>> }
>>
>> synchronized(rw.write) {
>>
>> }
>>
>> And many types of lock : spin lock, interprocesses locks, semaphores, .
>> . . And all can be used with the synchronized syntax, and without
>> exposing locking and unlocking primitives.
>>
>> What do people think ?
>
> +1. Works for me.
>
> It refines what I believe the shadow cabinet (loosely: me, you, Alex,  
> Regan Heath and Steven) propose.

Is this really necessary?  When is opSynchronized going to be written any  
way other than:

_mutex.lock();
scope(exit) _mutex.unlock();
dg();

I'll note that it's easier to forget to lock or unlock if the compiler  
isn't enforcing it.  You might even naively do this:

_mutex.lock();
dg();
_mutex.unlock(); // not called on exception thrown!

I kind of like the __lock() __unlock() pair that the compiler always calls  
both in the right place/way.  Yes, you could just leave those  
implementations blank, but very unlikely.

Plus, we already have issues with inout and delegates for opApply, this  
would have the same issues.

> P.S. Removing monitor from non-synced/shared classes would be good too.  
> As a separate matter.

I think at this point, we should leave it there until we can really figure  
out a detailed plan on how to deal with it.  It currently affects all  
runtime code which does virtual function lookups or interface lookups, and  
alignment.  We would have to change a lot of compiler and runtime code to  
remove it.

I personally don't see it as a huge issue, we are already allocating on  
power-of-two boundaries which can almost double required space.  I feel  
class size is really one of those things you should be oblivious to.  That  
being said, I'm all for performance improvement, even small ones, if they  
are free and someone is willing to do all the leg work :)

-Steve


More information about the Digitalmars-d mailing list