Intel® Fortran Compiler 16.0 User and Reference Guide
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.
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.
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