On 31-05-2012 16:49, Dmitry Olshansky wrote:
But this is a protection/visibility issue, which is orthogonal on the
locking capability. It's as if you say "int is not good because anyone
can overflow it." Okay! Make it private inside a CheckedInt class.
Sorry, that's a bad comparison. CheckedInt is to int, what CheckedMutex
is to mutex - but I'm not suggesting anything like a CheckedMutex. I'm
suggesting "mutex" but kept private inside the class /that it locks/.
Yes, it's a visibility issue, the issue is that the mutex used by
synchronized classes/methods is too visible/accessible and this opens it
up for deadlocks which are otherwise impossible.
Sure it's awful comparison.
So where's the mutex that would be used to synchronize objects that
are not synchronizable?
In the wrapper class/struct/object which derives a synchronized
class/struct from the original. My D foo is not strong enough to just
come up with valid D code for the idiom on the fly, but essentially you
wrap the original object in a new object using a template which adds the
mutex member and the interface methods (lock, tryLock, and unlock)
required. No, this doesn't work with "final" classes.. but it shouldn't,
they're final after all. For them you need to add/manage the mutex
manually - the price you pay for "final".
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.
If this means that the monitor field in regular objects goes away, then
I'm all for this, at least.
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?
--
Alex Rønne Petersen
[email protected]
http://lycus.org