On Thu, 31 May 2012 15:49:52 +0100, Dmitry Olshansky <[email protected]> wrote:
OK let me land you a hand here. My proposal, that I think fits your ideas quite favorably.

I'll enumerate certain assumptions beforehand since it's one of most confusing threads I ever followed.

1. synchronized class means: always allocate hidden monitor mutex, lock it on every public method of this class.

2. synchronized(x,y,z) is lowered to (I use Steven's idea):
auto sorted = total_order(x,y,z);//conceptual, sorted is tuple of x,y,z sorted
        FOR EACH item IN sorted tuple add code in [[ ... ]]
        [[// conceptual
                item.__lock();
                scope(exit) item.__unlock();
        ]]
In other words it works for every object that defines lock/unlock. Multiple object version works only if there is opCmp defined. (by address whatever, any total ordering should work)


Per definition above synchronized classes AS IS can't be *synchronized* on. Instead their public methods are implicitly synchronized.

The end result is:

User can synchronize on various synchronization entities and even plug in custom synchronization primitives (say OS Y provides have this fancy lock type Z). It's explicit in as sense that object supports it via __lock__/unlock. Obviously one still can use __lock/__unlock explicitly just don't forget to wear big HERE BE DRAGONS banner.

Synchronized class encapsulate mutex completely - nobody aside from designer of the class may (a)use it.

Does it makes sense?

Yes, and it's all more intentional/flexible than what we have now, but.. :)

Does it address what I thought was the main "problem" case. That is, as soon as you lock 2 objects, one via a synchronized() statement and the other via a synchronized method you can get a non-obvious deadlock. e.g.

synchronized class A
{
  void foo() {} // implicitly locks instance of A
}

class B
{
  void __lock() {}   // locks instance of B
  void __unlock() {} // unlocks instance of B
}

shared A a;
shared B b;

void main()
{
  a = new shared(A)();
  b = new shared(B)();
  ..start thread which locks a then b..
  synchronized(b)  // locks b 'explicitly'
  {
    a.foo();       // locks a 'implicitly'
  }
}

.. but, hang on, can a thread actually lock a and then b? If 'a' cannot participate in a synchronized statement (which it can't under this proposal) then no, there is no way to lock 'a' except by calling a member. So, provided 'a' does not have a member which locks 'b' - were deadlock safe!

So.. problem solved; by preventing external/public lock/unlock on a synchronized class. (I think the proposal should enforce this restriction; synchronized classes cannot define __lock/__unlock).

R

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

Reply via email to