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/