Andreas,
I solved this problem in an interesting but very simple way. Our solution was within a database. What we did was commit a lock to the database, then query for the lock, if you get more then one lock back then you remove your lock. In your process you could fail all the way back to the beginning. This has the effect of favoring everyone failing instead of a deadlock. If you can keep the locking time down to a small percentage of overall processing time it should work.
For optimistic locking we did something else that caused a commit failure and eliminated locking altogether. If you are pretty sure that the locking time is small and the chances of a conflict are small and the rework of a commit failure is tolerable by the user then pushing the failure to the commit works well. It doesn't sound like that's what you are asking about so if you want to know more let me know.
Ron Teitelbaum Ron@USMedRec.com
From: Andreas Raab Sent: Monday, June 26, 2006 6:12 PM
Hi Folks -
I have an interesting little problem that can be trivially solved with help from the VM but that I'm curious if there is a way of doing it from Squeak directly. Here is the problem:
Given a set of N locks (semaphores), how can multiple processes acquire subsets of those locks without deadlocking? E.g., it's fairly obvious that if one process attempts to acquire lock A and B and another one lock B and A that this leads to deadlock in a hurry. What's in particular problematic for my use case is that I don't know which semaphores are part of said set of locks and that I can't establish a total order to make sure that lock A always gets acquired before lock B.
What I've been contemplating is to add a primitive which does the following: It attempts to acquire all the locks given as argument and if one of them cannot be acquired it immediately releases all the locks acquired so far and leaves the process suspended on the "failing" lock. The return value will indicate whether all the locks were acquired and therefore one can write a loop like here to acquire all of the locks:
[self primitiveAcquireAll: locks] whileFalse.
In other words, if all the locks can be acquired the code just marches through. If it fails to acquire a lock the process will stay suspended until that particular lock is released and then retry to acquire the locks.
Is it possible to do that without a VM change?
Cheers,
- Andreas