|
HP OpenVMS systems documentation |
Previous | Contents | Index |
The name argument to the Associate Common Event Flag Cluster (SYS$ASCEFC) system service identifies the cluster that the process is creating or associating with. The name argument specifies a descriptor pointing to a character string.
Translation of the name argument proceeds in the following manner:
For example, assume that you have made the following logical name assignment:
$ DEFINE CEF$CLUS_RT CLUS_RT_001 |
Assume also that your program contains the following statements:
#include <ssdef.h> #include <descrip.h> . . . unsigned int status; $DESCRIPTOR(name,"CLUS_RT"); /* Logical name of cluster */ . . . status = SYS$ASCEFC(...,&name,...); |
The following logical name translation takes place:
There are two exceptions to the logical name translation method discussed in this section:
Common event flag clusters are either temporary or permanent. The perm argument to the SYS$ASCEFC system service defines whether the cluster is temporary or permanent.
Temporary clusters require an element of the creating process's quota
for timer queue entries (TQELM quota). They are deleted automatically
when all processes associated with the cluster have disassociated.
Disassociation can
be performed explicitly with the Disassociate Common Event Flag Cluster
(SYS$DACEFC) system service, or implicitly when the image that called
SYS$ASCEFC exits.
6.8.6.3 Permanent Common Event Flag Clusters
If you have the PRMCEB privilege, you can create a permanent common event flag cluster (set the perm argument to 1 when you invoke SYS$ASCEFC). A permanent event flag cluster continues to exist until it is marked explicitly for deletion with the Delete Common Event Flag Cluster (SYS$DLCEFC) system service (requires the PRMCEB privilege). Once a permanent cluster is marked for deletion, it is like a temporary cluster; when the last process that associated with the cluster disassociates from it, the cluster is deleted.
In the following examples, the first program segment associates common event flag cluster 3 with the name CLUSTER and then clears the second event flag in the cluster. The second program segment associates common event flag cluster 2 with the name CLUSTER and then sets the second event flag in the cluster (the flag cleared by the first program segment).
STATUS = SYS$ASCEFC (%VAL(96), 2 'CLUSTER',,) STATUS = SYS$CLREF (%VAL(98)) |
STATUS = SYS$ASCEFC (%VAL(64), 2 'CLUSTER',,) STATUS = SYS$SETEF (%VAL(66)) |
For clearer code, rather than using a specific event flag number, use one variable to contain the bit offset you need and one variable to contain the number of the first bit in the common event flag cluster that you are using. To reference the common event flag, add the offset to the number of the first bit. The following examples accomplish the same result as the preceding two examples:
INTEGER*4 BASE, 2 OFFSET PARAMETER (BASE = 96) OFFSET=2 STATUS = SYS$ASCEFC (%VAL(BASE), 2 'CLUSTER',,) STATUS = SYS$CLREF (%VAL(BASE+OFFSET)) |
INTEGER*4 BASE, 2 OFFSET PARAMETER (BASE = 64) OFFSET=2 STATUS = SYS$ASCEFC (%VAL(BASE), 2 'CLUSTER',,) STATUS = SYS$SETEF (%VAL(BASE+OFFSET)) |
Common event flags are often used for communicating between a parent process and a created subprocess. The following parent process associates the name CLUSTER with a common event flag cluster, creates a subprocess, and then waits for the subprocess to set event flag 64:
INTEGER*4 BASE, 2 OFFSET PARAMETER (BASE = 64, 2 OFFSET = 0) . . . ! Associate common event flag cluster with name STATUS = SYS$ASCEFC (%VAL(BASE), 2 'CLUSTER',,) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) ! Create subprocess to execute concurrently MASK = IBSET (MASK,0) STATUS = LIB$SPAWN ('RUN REPORTSUB', ! Image 2 'INPUT.DAT', ! SYS$INPUT 2 'OUTPUT.DAT', ! SYS$OUTPUT 2 MASK) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) ! Wait for response from subprocess STATUS = SYS$WAITFR (%VAL(BASE+OFFSET)) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) . . . |
REPORTSUB, the program executing in the subprocess, associates the name CLUSTER with a common event flag cluster, performs some set of operations, sets event flag 64 (allowing the parent to continue execution), and continues executing:
INTEGER*4 BASE, 2 OFFSET PARAMETER (BASE = 64, 2 OFFSET = 0) . . . ! Do operations necessary for ! continuation of parent process . . . ! Associate common event flag cluster with name STATUS = SYS$ASCEFC (%VAL(BASE), 2 'CLUSTER',,) IF (.NOT. STATUS) 2 CALL LIB$SIGNAL (%VAL(STATUS)) ! Set flag for parent process to resume STATUS = SYS$SETEF (%VAL(BASE+OFFSET)) . . . |
A wait form system service is a variant of an asynchronous service in which there is a service request and then a wait for the completion of the request. The SYS$SYNCH system service checks the completion status of a system service that completes asynchronously. For reliable operation in most applications, the service whose completion status is to be checked must have been called with the efn and iosb arguments specified. The SYS$SYNCH service uses the event flag and I/O status block of the service to be checked.
HP recommends that only EFN$C_ENF be used for concurrent use of event
flags.
6.8.8 Event Flag Waits
The following three system services place the process or thread in a wait state until an event flag or a group of event flags is set:
Another system service that accepts an event flag number as an argument is the Queue I/O Request (SYS$QIO) system service. The following example shows a program segment that issues two SYS$QIO system service calls and uses the SYS$WFLAND system service to wait until both I/O operations complete before it continues execution:
. . . #include <lib$routines.h> #include <starlet.h> #include <stsdef.h> . . . unsigned int RetStat, Efn1=1, Efn2=2, EFMask; (1) unsigned short int IOSB1[4], IOSB2[4]; (2) unsigned int EFMask = 1L<<Efn1 | 1L<<Efn2; (3) . . . // Issue first I/O request and check for error */ RetStat = sys$qio( Efn1, Chan1, FuncCode1, IOSB1, ...) if (!$VMS_STATUS_SUCCESS( RetStat )) (4) lib$signal(RetStat); // Issue second I/O request and check for error RetStat = sys$qio( Efn2, Chan2, FuncCode2, IOSB2, ...) if (!$VMS_STATUS_SUCCESS( RetStat )) lib$signal(RetStat); // Wait until both complete and check for error RetStat = sys$wfland( Efn1, EFMask ); (5) if (!$VMS_STATUS_SUCCESS( RetStat )) lib$signal(status); // Determine which asynchronous operation has completed. // If set to zero, the particular $qio call has not completed. if ( IOSB1[0] ) (6) CallOneCompleted(); if ( IOSB2[0] ) CallTwoCompleted(); . . . |
System services that use event flags clear the event flag specified in the system service call before they queue the timer or I/O request. This ensures that the process knows the state of the event flag. If you are using event flags in local clusters for other purposes, be sure the flag's initial value is what you want before you use it.
The Set Event Flag (SYS$SETEF) and Clear Event Flag (SYS$CLREF) system services set and clear specific event flags. For example, the following system service call clears event flag 32:
$CLREF_S EFN=#32 |
The SYS$SETEF and SYS$CLREF services return successful status codes that indicate whether the specified flag was set or cleared when the service was called. The caller can thus determine the previous state of the flag, if necessary. The codes returned are SS$_WASSET and SS$_WASCLR.
All event flags in a common event flag cluster are initially clear when
the cluster is created. Section 6.8.10 describes the creation of common
event flag clusters.
6.8.10 Example of Using a Common Event Flag Cluster
The following example shows four cooperating processes that share a common event flag cluster. The processes are named COLUMBIA, ENDEAVOUR, ATLANTIS, and DISCOVERY, and are all in the same UIC group.
/* **** Common Header File **** (1) . . . #define EFC0 0 // EFC 0 (Local) #define EFC1 32 // EFC 1 (Local) #define EFC2 64 // EFC 2 (Common) #define EFC3 96 // EFC 3 (Common) int Efn0 = 0, Efn1 = 1, Efn2 = 2, Efn3 = 3; int EFMask; $DESCRIPTOR(EFCname,"ENTERPRISE"); . . . // **** Process COLUMBIA **** (2) // // The image running within process COLUMBIA creates a common // event flag cluster, associating it with Cluster 2 . . . RetStat = sys$ascefc(EFC2, &EFCname,...); (3) if (!$VMS_STATUS_SUCCESS(RetStat)) lib$signal(RetStat); . . . EFMask = 1L<<Efn1 | 1L<<Efn2 | 1L<<Efn3; (4) // Wait for the specified event flags RetStat = sys$wfland(EFC2, EFMask); (5) if (!$VMS_STATUS_SUCCESS(RetStat)) lib$signal(RetStat); . . . // Disassociate the event flag cluster RetStat = sys$dacefc(EFC2); (6) // **** Process ENDEAVOUR **** // // The image running within process ENDEAVOUR associates with the // specified event flag cluster, specifically associating it with // the common event flag cluster 3. . . . // Associate the event flag cluster, using Cluster 3 RetStat = sys$ascefc(EFC3,&EFCname,...); (7) if (!$VMS_STATUS_SUCCESS(RetStat)) lib$signal(RetStat); // Set the event flag, and check for errors RetStat = sys$setef(Efn2+EFC3); (8) if (!$VMS_STATUS_SUCCESS(RetStat)) lib$signal(RetStat); . . . RetStat = sys$dacefc(EFC3); // **** Process ATLANTIS **** // // The image running within process ATLANTIS associates with the // specified event flag cluster, specifically associating it with // the common event flag cluster 2. // Associate the event flag cluster, using Cluster 2 RetStat = sys$ascefc(EFC2, &EFCname); if (!$VMS_STATUS_SUCCESS(RetStat)) lib$signal(RetStat); // Set the event flag, and check for errors RetStat = sys$setef(Efn2+EFC2); if (!$VMS_STATUS_SUCCESS(RetStat)) lib$signal(RetStat); . . . retstat = sys$dacefc(EFC2); // **** Process DISCOVERY **** (9) // The image running within process DISCOVERY associates with the // specified event flag cluster, specifically associating it with // the common event flag cluster 3. RetStat = sys$ascefc(EFC3, &EFCname); if (!$VMS_STATUS_SUCCESS(RetStat)) lib$signal(RetStat); // Wait for the flag, and check for errors RetStat = sys$waitfr(Efn2+EFC3); if (!$VMS_STATUS_SUCCESS(RetStat)) lib$signal(RetStat); // Set event flag 2, and check for errors RetStat = sys$setef(Efn2+EFC3); if (!$VMS_STATUS_SUCCESS(RetStat)) lib$signal(RetStat); . . . RetStat = sys$dacefc(EFC2); |
This section contains an example of how to use event flag services.
Common event flags are often used for communicating between a parent process and a created subprocess. In the following example, REPORT.FOR creates a subprocess to execute REPORTSUB.FOR, which performs a number of operations.After REPORTSUB.FOR performs its first operation, the two processes can perform in parallel. REPORT.FOR and REPORTSUB.FOR use the common event flag cluster named JESSIER to communicate.
REPORT.FOR associates the cluster name with a common event flag cluster, creates a subprocess to execute REPORTSUB.FOR and then waits for REPORTSUB.FOR to set the first event flag in the cluster. REPORTSUB.FOR performs its first operation, associates the cluster name JESSIER with a common event flag cluster, and sets the first flag. From then on, the processes execute concurrently.
REPORT.FOR . . . ! Associate common event flag cluster STATUS = SYS$ASCEFC (%VAL(64), 2 'JESSIER',,) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) ! Create subprocess to execute concurrently MASK = IBSET (MASK,0) STATUS = LIB$SPAWN ('RUN REPORTSUB', ! Image 2 'INPUT.DAT', ! SYS$INPUT 2 'OUTPUT.DAT', ! SYS$OUTPUT 2 MASK IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) ! Wait for response from subprocess. STATUS = SYS$WAITFR (%VAL(64)) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) . . . REPORTSUB.FOR . . . ! Do operations necessary for ! continuation of parent process. . . . ! Associate common event flag cluster STATUS = SYS$ASCEFC (%VAL(64), 2 'JESSIER',,) IF (.NOT. STATUS) 2 CALL LIB$SIGNAL (%VAL(STATUS)) ! Set flag for parent process to resume STATUS = SYS$SETEF (%VAL(64)) . . .
Previous | Next | Contents | Index |