On 01.06.2012 0:39, Dmitry Olshansky wrote:
On 31.05.2012 18:49, Dmitry Olshansky wrote:

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.

It could even go one step forward. Though it require a great deal of
though, here is an initial idea.

So with the above we have synchronized class with monitor that is
eagerly initialized (it's the propose of sync-ed class after all to use
this mutex safely) and ordinary class that don't have it.

Now if we let shared classes to have monitor field lazily initialized
something interesting shows up. For the moment let's skip painful detail
of cast(shared).

It's then possible to introduce a restricted version of ownership
system. Since ever member of shared class is shared or synchronized(?)
it should be OK to access member of any depth in it by following the
chain of monitor locks:
(i.e. I'm assuming composition implies "owns" relationship,
this ownership relation comes only for shared types)

shared class A
{
shared B b;
...
}

shared class B
{
shared C c;
...
}


then:
{
...
A a = ....;
// locks A's monitor, then B's monitor, unlocks A's
// then C's monitor, unlocks B's
// then calls do_smth, then unlocks C's
//all of the above lock/unlock sequence has to be exception proof
a.b.c.do_smth();

}


Grunted assuming compositon == ownership is wrong in general, but could

s/Grunted/Granted

serve as a sensible default. Then weak non-owning references would be
provided via dirty casting in special wrappers like
{
NotOwning!(shared T) x;//shared but doesn't own it, thus if
//calling any resource inside of x, we should keep x.monitor locked
//through out the operation. (unlike in the above case)
}
...

Obviously it's iteration 1 of idea, it needs to deal with possible
atomic modifications, cast(shared), etc.




--
Dmitry Olshansky

Reply via email to