Declarations
LockRef: TYPE = REF LockRecord;
LockRecord:
TYPE = MONITORED
RECORD [
waitingForWrite: INTEGER ← 0, -- number of processes waiting for write access to this document
count, maxCount: [0..255] ← 0, -- number of times have entered this lock
process: PROCESS ← NIL, -- the unique process which has write access to this document
whoLast, whoFirst: Rope.ROPE, -- provided by the lockers
unlocked: CONDITION -- raised when the lock is freed
];
Access: TYPE = { read, write };
Procedures
Lock:
PROC [doc: RefBranchNode, who: Rope.
ROPE, access: Access ← write]
RETURNS [LockRef];
Can only lock a document if
(1) it is unlocked, or
(2) current process has a write lock on it already
If neither holds, then waits until it can lock it.
Note that cannot convert a read lock into a write lock. (Implementation limitation.)
Many processes can have read locks; only one can have a write lock.
When a write lock is released, all viewers for the document have their tdd.dirty bit set true.
LockBoth:
PROC [
doc1, doc2: RefBranchNode, who: Rope.ROPE, access1, access2: Access ← write]
RETURNS [lock1, lock2: LockRef];
Like two calls on Lock, but orders the calls according to LockOrder.
LockOrder:
PROC [doc1, doc2: RefBranchNode]
RETURNS [
BOOL] =
INLINE {
RETURN [LOOPHOLE[doc1, INT] <= LOOPHOLE[doc2, INT]] };
Returns true if ok to lock doc1 before doc2.
Unlock:
PROC [doc: RefBranchNode];
Reduces the lock count for the document.
WaitingForWrite:
PROC [lock: LockRef]
RETURNS [
BOOL] =
INLINE
{ RETURN [lock.waitingForWrite > 0] };
Returns true iff some process is waiting to get a write lock for the document.
RegisterForCallAfterReleaseWriteLock:
PROC [proc:
PROC [doc: RefBranchNode]];
Registered procedure will be called as soon as the write lock is released.
The display update routines use this.
UnregisterForCallAfterReleaseWriteLock: PROC [proc: PROC [doc: RefBranchNode]];