Introduced in the 1977 ANSI M[UMPS] language standard.
LOCK A,B,C
Unlock all, LOCK C
Well... actually, when anybody else has either A or B
locked, this sequence of commands would wait first for these to be
unlocked...
LOCK (A,B,C)
Unlock all, LOCK A, B and C
LOCK X:TIME
Unlock all, LOCK X with time-out of TIME
seconds.
LOCK
Unlock all
IF '$DATA(^PATIENT(ID)) DO
. LOCK +^PATIENT(ID):5
. ; create patient record
. LOCK -^PATIENT(ID)
. QUIT
Assume that two processes execute this program segment
simultaneously, and that the chronology of the actions between
the jobs is as follows:
One process | Other process |
---|---|
IF '$DATA(^PATIENT(123)) | |
- swap out - | |
IF '$DATA(^PATIENT(123)) | |
DO | |
LOCK +^PATIENT(123) | |
; create patient record | |
LOCK -^PATIENT(123) | |
- swap in - | |
DO | |
LOCK +^PATIENT(123) | |
create patient record |
... Well, that's what we just wanted to avoid by using the LOCK command, wasn't it...
Correct usage of the LOCK command in this context would
be:
LOCK +^PATIENT(ID):TIME
ELSE WRITE "Cannot create record."
QUIT
QUIT:$DATA(^PATIENT(ID))
; create patient record
LOCK -^PATIENT(ID)
Always LOCK before a reference is made; that is the only
way to synchronize processes.
Added in the 1990 ANSI M[UMPS] language standard:
LOCK +D
Add D to the LOCK list.
LOCK -A
Remove A from the LOCK list.
Assume that
A="KLM(1)"
KLM(2,3,4)="PQR"
LOCK @A@(3,4) would be equivalent to
LOCK "PQR", which is an error, and
LOCK @@A@(3,4) would be equivalent to LOCK
PQR.
The ANSI standard behavior is defined as follows:
LOCK (without a plus)
LOCK with a plus
LOCK with a minus
Hence, the behavior should be:
LOCK +^GLO(1,2) | Adds one instance of the name ^GLO(1,2) to the lock table; may need to wait until another job relinquishes its lock on this name. |
LOCK +^GLO(1,2,3) | Adds one instance of the name ^GLO(1,2,3) to the lock table; will always succeed immediately because the a name governing a superset is already owned. |
LOCK -^GLO(1,2,3) | Removes one instance of the name ^GLO(1,2,3) from the lock table |
LOCK +GLO(1) | Adds one instance of the name ^GLO(1) to the lock table; may need to wait, e.g. if someone else owns lock on ^GLO(1,5). |
LOCK +GLO(2) | Adds one instance of the name ^GLO(2) to the lock table; may need to wait until another job relinquishes its lock on this name. |
LOCK -^GLO | If there is an occurrence of ^GLO for the current job, one instance will be removed from the lock table, othewise no effect |
So, assuming that the lock table is empty, and the number of the current job is 1, the sequence of events will be:
Command | Name | Count | Owner |
---|---|---|---|
LOCK +^GLO(1,2) | ^GLO(1,2) | 1 | 1 |
Command | Name | Count | Owner |
LOCK +^GLO(1,2) | ^GLO(1,2) | 2 | 1 |
Command | Name | Count | Owner |
LOCK +^GLO(1,2,3) | ^GLO(1,2) | 2 | 1 |
^GLO(1,2,3) | 1 | 1 | |
Command | Name | Count | Owner |
LOCK -^GLO(1,2,3) | ^GLO(1,2) | 2 | 1 |
Command | Name | Count | Owner |
LOCK +GLO(1) | ^GLO(1,2) | 2 | 1 |
^GLO(1) | 1 | 1 | |
Command | Name | Count | Owner |
LOCK +GLO(2) | ^GLO(1,2) | 2 | 1 |
^GLO(2) | 1 | 1 | |
Command | Name | Count | Owner |
LOCK -^GLO(1,2) | ^GLO(1,2) | 1 | 1 |
Command | Name | Count | Owner |
LOCK -^GLO | ^GLO(1,2) | 1 | 1 |
Assuming that the lock table has the depicted initial content, and the number of the current job is 1, and assuming that job number 3 would relinquish the locks that are requested by job number 1, the sequence of events would be:
Name | Count | Owner | Comment | |
---|---|---|---|---|
^GLO | 1 | 3 | ||
^GLO(1,2) | 1 | 3 | ||
^GLO(5) | 1 | 3 | ||
^GLO(7) | 1 | 3 | ||
Command | Name | Count | Owner | Comment |
LOCK +^GLO(1,2) | ^GLO | 1 | 3 | |
^GLO(1,2) | 1 | 1 | Added after other job relinquishes its lock | |
^GLO(5) | 1 | 3 | ||
^GLO(7) | 1 | 3 | ||
Command | Name | Count | Owner | Comment |
LOCK +^GLO(1,2) | ^GLO | 1 | 3 | |
^GLO(1,2) | 2 | 1 | Count increases by 1 | |
^GLO(5) | 1 | 3 | ||
^GLO(7) | 1 | 3 | ||
Command | Name | Count | Owner | Comment |
LOCK +^GLO(1,2,3) | ^GLO | 1 | 3 | |
^GLO(1,2) | 2 | 1 | ||
^GLO(1,2,3) | 1 | 1 | Can always be added immediately | |
^GLO(5) | 1 | 3 | ||
^GLO(7) | 1 | 3 | ||
Command | Name | Count | Owner | Comment |
LOCK -^GLO(1,2,3) | ^GLO | 1 | 3 | |
^GLO(1,2) | 2 | 1 | ||
Entry is removed when count reaches zero | ||||
^GLO(5) | 1 | 3 | ||
^GLO(7) | 1 | 3 | ||
Command | Name | Count | Owner | Comment |
LOCK +GLO(1) | ^GLO | 1 | 3 | |
^GLO(1) | 1 | 1 | Can be added as long a no-one else owns it | |
^GLO(1,2) | 2 | 1 | ||
^GLO(5) | 1 | 3 | ||
^GLO(7) | 1 | 3 | ||
Command | Name | Count | Owner | Comment |
LOCK +GLO(2) | ^GLO | 1 | 3 | |
^GLO(1) | 1 | 1 | ||
^GLO(1,2) | 2 | 1 | ||
^GLO(2) | 1 | 1 | Can be added as long a no-one else owns it | |
^GLO(5) | 1 | 3 | ||
^GLO(7) | 1 | 3 | ||
Command | Name | Count | Owner | Comment |
LOCK -^GLO(1,2) | ^GLO | 1 | 3 | |
^GLO(1) | 1 | 1 | ||
^GLO(1,2) | 1 | 1 | Count decreases by 1 | |
^GLO(2) | 1 | 1 | ||
^GLO(5) | 1 | 3 | ||
^GLO(7) | 1 | 3 | ||
Command | Name | Count | Owner | Comment |
LOCK -^GLO | ^GLO | 1 | 3 | Since the requesting job doesn't own this entry, no change |
^GLO(1) | 1 | 1 | ||
^GLO(1,2) | 1 | 1 | ||
^GLO(2) | 1 | 1 | ||
^GLO(5) | 1 | 3 | ||
^GLO(7) | 1 | 3 |
The option has been added to use "subscript indirection" in name references that occur in arguments of LOCK commands.
SET Root="^DIC(19)"
LOCK +@Root@(42,0)
is now equivalent with LOCK +^DIC(19,42,0)
Examples with naked references:
LOCK NAME
SET ^ABC(1,2)="reset naked indicator"
; Naked indicator is now ^ABC(1,
LOCK ^(3,4)
; Error occurs (invalid nref in LOCK argument)
; This is a general syntactical error; no M... error code has
been assigned.
; Naked indicator is unchanged
LOCK NAME
SET ^ABC(1,2)="reset naked indicator"
; Naked indicator is now ^ABC(1,
LOCK ^(3,^(4,5))
; fetch ^(4,5) = ^ABC(1,4,5)
; Naked indicator is now ^ABC(1,4,
; Error occurs (invalid nref in LOCK argument)
; Note that the naked indicator may change while evaluating
subscripts,
; but not as a side-effect of the LOCK command itself.
This document is © Ed de Moel, 1995-2005.
It is part of a book by Ed de Moel that is published under
the title "M[UMPS] by Example" (ISBN 0-918118-42-5).
Printed copies of the book are no longer available.
This document describes the various commands that are defined in the M[UMPS] language standard (ANSI X11.1, ISO 11756).
The information in this document is NOT authoritative
and subject to be modified at any moment.
Please consult the appropriate (draft) language standard for an
authoritative definition.
In this document, information is included that will
appear in
future standards.
The MDC cannot guarantee that these 'next'
standards will indeed appear.