M[UMPS] Commands

L[OCK]

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

Approved for addition in a future ANSI M[UMPS] language standard.

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.