Acquiring multiple locks
nicolas cellier
ncellier at ifrance.com
Tue Jun 27 00:33:58 UTC 2006
Hi Andreas,
Why using a primitive ? Because you are sure that processes are mutually
excluded ?
In this case, why not using a GlobalMutex to get similar protection
Of course MutexSet cannot work due to deadlock... but this LockSet might:
Object subclass: #LockSet
instanceVariableNames: 'array'
classVariableNames: 'GlobalMutex'
poolDictionaries: ''
category: 'Kernel-Processes'
LockSet>>initialize
array := Array new
LockSet>>withAll: locks
array := locks
LockSet>>mutex
"a global mutex with lazy initialization"
GlobalMutex ifNil: [GlobalMutex := Mutex new].
GlobalMutex
LockSet>>critical: aBlock
"evaluate aBlock if we can acquire all locks"
| indexFailed |
[indexFailed := self mutex critical:
[(1 to: array size) detect: [:i | (array at: iLock)
acquireNoWait = false] ifNone:
[aBlock value.
1 to: array size do: [:i | (array at: i) signal].
0]]].
indexFailed = 0] whileFalse:
[(1 to: indexFailed -1) do: [:i | (array at: i) signal].
(array at: indexFailed) wait; signal].
Semaphore>>acquireNoWait
| waitingProcess wakeupProcess ok |
waitingProcess := Processor activeProcess.
ok := true.
wakeupProcess :=
[Processor yield.
ok := false.
self resumeProcess: waitingProcess] fork.
self wait.
wakeupProcess terminate.
^ok
You can replace wait by acquireLock, signal by releaseLock and acquireNoWait
by acquireLockNoWait and replace Semaphore with your own Lock class...
I did not try it cause it's late but maybe you will.
Nicolas
Le Mardi 27 Juin 2006 00:12, Andreas Raab a écrit :
> 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
More information about the Squeak-dev
mailing list
|