Intel® Fortran Compiler Classic and Intel® Fortran Compiler Developer Guide and Reference

ID 767251
Date 7/13/2023
Public

A newer version of this document is available. Customers should click here to go to the newest version.

Document Table of Contents

LOCK and UNLOCK

Statements: A LOCK statement causes a lock variable to become locked by an image. An UNLOCK statement causes the lock variable to become unlocked. They take the following forms:

LOCK (lock-var [, ACQUIRED_LOCK=log-var] [, STAT=stat-var] [, ERRMSG=err-var])

UNLOCK (lock-var [, STAT=stat-var] [, ERRMSG=err-var])

lock-var

Is a scalar variable of type LOCK_TYPE. For more information, see intrinsic module ISO_FORTRAN_ENV.

log-var

Is a scalar logical variable.

stat-var

Is a scalar integer variable in which the status of the synchronization is stored.

err-var

Is a scalar default character variable in which explanatory text is stored if an error occurs.

ACQUIRED_LOCK=, STAT=, and ERRMSG= can appear in any order, but only once in a LOCK statement.

STAT= and ERRMSG= can appear in either order, but only once in an UNLOCK statement.

Description

A lock variable is unlocked if its value is equal to that of the structure constructor LOCK_TYPE ( ). If it has any other value, it is locked.

A lock variable is locked by an image if it was locked by execution of a LOCK statement on that image and has not been subsequently unlocked by execution of an UNLOCK statement on the same image.

When a LOCK statement is specified without an ACQUIRED_LOCK= specifier, it causes the lock variable to become locked by that image. If the lock variable is already locked by another image, that LOCK statement causes the lock variable to become defined after the other image causes the lock variable to become unlocked.

If the lock variable is unlocked, successful execution of a LOCK statement with an ACQUIRED LOCK= specifier causes the lock variable to become locked by that image and the log-var to become defined with the value TRUE. If the lock variable is already locked by a different image, successful execution of a LOCK statement with an ACQUIRED LOCK= specifier leaves the lock variable unchanged and causes the log-var to become defined with the value FALSE.

During the execution of the program, the value of a lock variable changes through a sequence of locked and unlocked states when LOCK and UNLOCK statements are executed. If a lock variable becomes unlocked by execution of an UNLOCK statement on image M and next becomes locked by execution of a LOCK statement on image T, the segments preceding the UNLOCK statement on image M precede the segments following the LOCK statement on image T. Execution of a LOCK statement that does not cause the lock variable to become locked does not affect segment ordering.

An error condition occurs in the following cases:

  • If the lock variable in a LOCK statement is already locked by the executing image

  • If the lock variable in an UNLOCK statement is not already locked by the executing image

If an error condition occurs during execution of a LOCK or UNLOCK statement, the value of the lock variable is not changed and the value of the ACQUIRED_LOCK variable, if any, is not changed.

Example

The following example shows the use of LOCK and UNLOCK statements to manage a work queue:


USE, INTRINSIC :: ISO_FORTRAN_ENV

TYPE(Task) :: work_queue(50)[*]          ! List of tasks on queue to perform
INTEGER :: work_queue_size[*]
TYPE(LOCK_TYPE) :: work_queue_lock[*]    ! Lock to manage the work queue

TYPE(Task) :: current_task 
INTEGER :: my_image

my_image = THIS_IMAGE()
DO
   ! Process the next task in the work queue
   LOCK (work_queue_lock)              ! Start of new segment A
   ! Segment A is ordered with respect to segment B
   ! executed by image my_image-1 below because of lock exclusion
   IF (work_queue_size>0) THEN
       ! Get the next job from the queue
       current_task = work_queue(work_queue_size)
       work_queue_size = work_queue_size-1
   END IF
   UNLOCK (work_queue_lock) ! Segment ends
...
   ! Process the task

   ! Add a new task on the neighboring queue:
   LOCK(work_queue_lock[my_image+1])      ! Starts segment B
   ! Segment B is ordered with respect to segment A
   ! executed by image my_image+1 above because of lock exclusion
   IF (work_queue_size[my_image+1]<SIZE(work_queue)) THEN
       work_queue_size[my_image+1] = work_queue_size[ti+1]+1
       work_queue(work_queue_size[my_image+1])[my_image+1] = current_task
   END IF
   UNLOCK (work_queue_lock[my_image+1]) ! Ends segment B
END DO