ViewerLocks.mesa
Copyright Ó 1985, 1986, 1991 by Xerox Corporation. All rights reserved.
Edited by McGregor on October 25, 1982 3:13 pm
Last Edited by: Maxwell, January 13, 1983 2:50 pm
Doug Wyatt, April 15, 1985 0:34:24 am PST
DIRECTORY
ViewerClasses USING [Column, Viewer];
ViewerLocks: CEDAR DEFINITIONS
= BEGIN OPEN ViewerClasses;
ViewerLocks is an interlocking mechanism to arbitrate access to the Viewer window tree, viewer columns, as well as individual viewers. A particular viewer may be locked for reading or for writing. A read request implies that the calling code would like to examine values in the ViewerClasses.ViewerRec and insure that these values are invariant for the duration that the read lock is held. Any number of clients can simultaneously hold read locks on a single viewer. A write lock is an exclusive access to a viewer for the implied operation of modifying one or more of the fields in the ViewerClasses.ViewerRec.
Locks are process re-entrant, meaning that a single process may request a lock multiple times without deadlock; i.e. if a process currently has write access to a viewer, it may in addition request read or write access (this obviously doesn't grant any new permissions, but is useful when a client has already locked a viewer and wishes to call code that may attempt a lock). Due to the ordering of the read and write resources, a process holding a read lock may not request a write lock on the same viewer without first releasing the read lock.
The viewer tree as well as the particular columns are another set of resources that may be locked. Locking a column is equivalent to (but not implemented as) locking all of the viewers in that column. Locking the viewer tree is equivalent to locking all of the columns for write in addition to the root pointer for the tree. The viewer tree must be locked by the client any time a top level viewer changes size or position in the tree that crosses column boundaries. Since all painting operations are protected by a read lock on the updated viewer, the viewer tree lock will not be granted until painting activity has subsided.
The hierarchy of locks in the viewers window package, from highest to lowest is: the viewer tree, a write lock on a column, a write lock on a particular viewer, a read lock on a column, and a read lock on a particular viewer. A client may only request a new lock if it is at the same or lower logical level. The documentation in the viewer interfaces has been updated to show which locks the operation requires, so that the client can avoid deadlocks.
A fine point: if a client program needs to lock multiple viewers, it must acquire the lock for each viewer in the proper order. Routines are provided below that correctly sort the parameter list for up to three viewers; otherwise the client must order the lock requests so as to lock the viewers in ref order (treating the viewer ref as a long cardinal and locking the highest first). Columns must be locked in the order {static, left, right, color}.
Users are advised to make use of the call-back operations below when they need to perform locked operations on viewers. The suggested usage is to create a local procedure containing the critical code, which is passed to the routines below. The local procedure will then have full access to all of the variables in the outer procedure.
CallUnderWriteLock: PROC [proc: PROC, viewer: Viewer];
Call a client procedure while holding a write lock on a viewer.
CallUnderWriteLocks: PROC [proc: PROC, v0, v1, v2: Viewer ¬ NIL];
Call a client procedure while holding write locks on a set of viewers.
CallUnderReadLock: PROC [proc: PROC, viewer: Viewer];
Call a client procedure while holding a read lock on a viewer.
CallUnderReadLocks: PROC [proc: PROC, v0, v1, v2: Viewer ¬ NIL];
Call a client procedure while holding read locks on a set of viewers.
CallUnderColumnLock: PROC [proc: PROC, column: Column];
Call a client procedure while holding write locks for a particular column.
CallUnderColumnLocks: PROC [proc: PROC, c0, c1: Column];
Call a client procedure while holding write locks for two columns.
CallUnderViewerTreeLock: PROC [proc: PROC];
Call a client procedure while holding write locks for all columns and viewers.
LockOrder: PROC [v0, v1: Viewer] RETURNS [BOOL];
Returns true if ok to lock v0 before v1.
Wedged: ERROR [column: Column];
An attempt to acquire a column lock may fail if a process currently holding a column lock is caught in the debugger from either an uncaught signal or a breakpoint. In such a case, the signal Wedged is raised by the locking machinery.
END.