|
Class: RecursionLock
Object
|
+--Semaphore
|
+--RecursionLock
|
+--Dolphin::Mutex
- Package:
- stx:libbasic
- Category:
- Kernel-Processes
- Version:
- rev:
1.54
date: 2019/06/25 05:56:39
- user: cg
- file: RecursionLock.st directory: libbasic
- module: stx stc-classLibrary: libbasic
- Author:
- Claus Gittinger
like a Semaphore for mutual exclusion, but avoids the deadlock
if a critical region is reentered by the same process again.
I.e. allows reentering the critical region IFF the current process
is the one which did the original locking.
WARNING:
for now, recursionLocks are not unlocked when an image is
restarted. You may have to recreate them to avoid a deadLock.
(this may change in the future, but recreating a recursionLock in
the #earlyRestart handling does not hurt)
Semaphore
Process
ProcessorScheduler
instance creation
-
name: aString
-
(comment from inherited method)
create & return a new semaphore which blocks until a signal is sent
-
new
-
(comment from inherited method)
create & return a new semaphore which blocks until a signal is sent
-
new: n
-
(comment from inherited method)
create & return a new semaphore which allows n waits before
blocking
blocked protocol
-
signalForAll
-
(comment from inherited method)
signal the semaphore for all waiters.
This can be used for process synchronization, if multiple processes are
waiting for a common event.
-
signalIf
-
(comment from inherited method)
signal the semaphore, but only if being waited upon.
This can be used for one-shot semaphores (i.e. not remembering
previous signals)
-
signalOnce
-
(comment from inherited method)
wakeup waiters - but only once.
I.e. if the semaphore has already been signaled, this is ignored.
-
waitUncounted
-
(comment from inherited method)
wait for the semaphore; do not consume the resource
(i.e. do not count down)
-
waitUncountedWithTimeoutMs: milliSeconds
-
(comment from inherited method)
wait for the semaphore; do not consume the resource
(i.e. do not count down).
Abort the wait after some time.
return the receiver if the semaphore triggered normal, nil if we return
due to a timeout.
With zero timeout, this can be used to poll a semaphore (returning
the receiver if the semaphore is available, nil if not).
However, polling is not the intended use of semaphores, though.
If milliSecondsOrNil is nil, wait without timeout.
queries
-
owner
-
return the owning processes (or nil)
-
wouldBlock
-
Check if the resource represented by the receiver is
already in use by another process.
Attention: if asked without some global lock (blockedInterrupts),
the returned value may be outdated right away.
signaling
-
signal
-
(comment from inherited method)
waking up the highest prio waiter.
waiting
-
critical: aBlock
-
evaluate aBlock as a critical region, but do not block
if this lock is already held by the current process.
-
critical: aBlock timeoutMs: timeoutMs ifBlocking: blockingBlock
-
like critical:, but do not block if the lock cannot be acquired
within timeoutMs milliseconds.
Instead, return the value of blockingBlock.
-
wait
-
wait, but do not block, if this lock is already held by the current process.
Answer false, if already locked, true if lock has been just acquired.
-
waitWithTimeoutMs: milliSeconds
-
wait, but do not block, if this lock is already held by the current process.
Answer false, if already locked, true if lock has been just acquired,
nil if the lock could not be acquired in time.
example (good):
|lock|
lock := RecursionLock new.
lock critical:[
Transcript showCR:'in lock ...'.
lock critical:[
Transcript showCR:'again ...'
]
]
|
in contrast to (wrong example - deadlocks):
|lock|
lock := Semaphore forMutualExclusion.
lock critical:[
Transcript showCR:'in lock ...'.
lock critical:[
'*** never reached - deadlock because sema is already locked ***'.
' (press CTRL-c and abort in the debugger)'.
Transcript showCR:'again ...'
]
]
|
|