|
Class: BoltLock
Object
|
+--BoltLock
- Package:
- stx:libbasic2
- Category:
- Kernel-Processes
- Version:
- rev:
1.7
date: 2017/02/07 23:43:58
- user: cg
- file: BoltLock.st directory: libbasic2
- module: stx stc-classLibrary: libbasic2
- Author:
- Claus Gittinger
A BoltLock (aka BoltVariable) is a 3-state semaphore,
useful to protect a resource against single writers, while allowing multiple
readers to access the resource simultaneously.
The lock is in one of 3 states:
A; free - can be changed by a writer into the locked state, or by a reader
into the busy state.
B; busy - can only be entered by another reader. left into free by last reader.
C; locked - a single writer has the lock; no other reader or writer is allowed
to acquire it
[notice:]
the original BoltLock was unfair in that new incoming readers could lock up a waiting writer.
This has been fixed by adding a fourth state (wantToLock), which is set by a write-waiter to prevent
new readers from getting the lock.
[instance variables:]
state <Symbol>
numReaders <Integer> number of readers holding onto the lock
waitingProcesses <OrderedCollection> waiting processes - will be served first
come first served when signalled.
name <String> a debugging aid: an optional userFriendly
name; helps to identify a semaphore easier.
Semaphore
SemaphoreSet
RecursionLock
Monitor
SharedQueue
Delay
Process
ProcessorScheduler
class initialization
-
initialize
-
(comment from inherited method)
called only once - initialize signals
instance creation
-
new
-
return an initialized instance
initialization
-
initialize
-
Invoked when a new instance is created.
private
-
addWaitingProcess: aProcess
-
add aProcess to the list of waiting processes.
all processes are ordered first-come-first-serve.
NOTE: must be called with blocked interrupts
-
removeWaitingProcess: aProcess
-
remove aProcess from the list of waiting processes
NO action if it is not in the list.
NOTE: must be called with blocked interrupts
-
wakeupWaiters
-
remove all waiting processes from the list of waiting processes
and resume them.
NOTE: Must be called when known that waitingProcesses is nonNil and
also with blocked interrupts
waiting
-
release
-
release the lock
usage example(s):
Transcript showCR:' release in state ',state.
|
-
waitForRead
-
wait for the lock in order to read
usage example(s):
Transcript showCR:' waitForRead in state ',state.
|
-
waitForWrite
-
wait for the lock in order to read
usage example(s):
Transcript showCR:' waitForWrite in state ',state.
|
many processes synchronizing on a boltLock:
|lock readers readWriters currentWriter processes|
lock := BoltLock new.
readWriters := (1 to:10) collect:[:tNo |
[
10 timesRepeat:[
(Random nextIntegerBetween:1 and:6) == 1 ifTrue:[
Transcript showCR:('thread %1: want to write...' bindWith:tNo).
lock waitForWrite.
currentWriter notNil ifTrue:[Transcript showCR:('ouch %1: writer is %2' bindWith:tNo with:currentWriter).self halt].
currentWriter := tNo.
Transcript showCR:('thread %1: **** write' bindWith:tNo).
Delay waitForSeconds:(Random nextIntegerBetween:1 and:4).
Transcript showCR:('thread %1: done writing.' bindWith:tNo).
currentWriter := nil.
lock release.
Delay waitForSeconds:(Random nextIntegerBetween:1 and:4).
] ifFalse:[
Transcript showCR:('thread %1: want to read...' bindWith:tNo).
lock waitForRead.
currentWriter notNil ifTrue:[Transcript showCR:('ouch %1: writer is %2' bindWith:tNo with:currentWriter).self halt].
Transcript showCR:('thread %1: ---- read' bindWith:tNo).
Delay waitForSeconds:(Random nextIntegerBetween:1 and:4).
Transcript showCR:('thread %1: done reading.' bindWith:tNo).
lock release.
Delay waitForSeconds:(Random nextIntegerBetween:1 and:4).
].
].
Transcript showCR:('thread %1: finished.').
] newProcess name:('rw%1' bindWith:tNo).
].
readers := (11 to:20) collect:[:tNo |
[
10 timesRepeat:[
Transcript showCR:('thread %1: want to read...' bindWith:tNo).
lock waitForRead.
currentWriter notNil ifTrue:[Transcript showCR:('ouch %1: writer is %2' bindWith:tNo with:currentWriter).self halt].
Transcript showCR:('thread %1: ---- read' bindWith:tNo).
Delay waitForSeconds:(Random nextIntegerBetween:1 and:4).
Transcript showCR:('thread %1: done.' bindWith:tNo).
lock release.
Delay waitForSeconds:(Random nextIntegerBetween:1 and:4).
].
Transcript showCR:('thread %1: finished.').
] newProcess name:('r%1' bindWith:tNo).
].
processes := readWriters , readers.
readWriters do:[:t | t resume].
readers do:[:t | t resume].
|
|