The graPHIGS API provides a set of user exits through which your application display data can be distributed and managed by a conference utility. Conference utilities allow multiple users on separate workstations to participate in a single graPHIGS API application. This is very useful when a team of designers, for example, who work in different locations need to discuss changes to a model they are all using. New users of a graPHIGS API application may also benefit when getting assistance from the help desk through a conference utility.
The graPHIGS API can accommodate a conference utility in the following way. The graPHIGS API application runs on a master workstation while a conference utility controller communicates with the participating workstations. This conference controller must be given information about all participating workstations before the application is started. One way to supply this information is through a conference session manager connected to a user interface. The graPHIGS API supports message facilities that allow this information to flow between the controller and the session manager. The session manager, conference controller, and the application must all run on the same node as the master workstation. See Figure 6screen
Figure 6. The graPHIGS API Running with a Typical Conference Utility
As the application renders data to the master workstation, the conference controller renders the same data to each participating workstation, allowing all participants to view the graPHIGS API application. It can also allow control to be passed from the master workstation to any one of the participating workstations for interaction with the application.
In order to render data to the participating workstations, the conference controller must intercept each graPHIGS API function issued by the application. It must then determine which functions to issue to the participating workstations as well as to the master workstation, and which to simply pass along to the master workstation. Further decisions must be made regarding the function parameters: if the controller issues the function to the participating workstations, it may use the same parameters set by the application or it may modify them before issuing them.
The conference controller must define and allocate a separate application anchor block (AAB) for each participating workstation. In this way, the conference controller keeps track of which workstation session has input focus. The conference controller should not allow any session to remain in a state awaiting input, such as a response to a Request Choice (GPRQCH) subroutine. This prevents input focus from being switched among master and participating workstation sessions.
The following sequence of events summarizes the initialization and exchange of data that might be used for a graPHIGS API conference utility: Refer to The graPHIGS Programming Interface: Subroutine Reference for details on the subroutines cited below.
When the application issues the first graPHIGS API subroutine call, the graPHIGS API attempts to load a user exit facility routine when the environment is set up as follows:
For AIX:
For MVS:
The graPHIGS API always attempts to load a module named AFMEXITscreen
For VM:
The conference controller minimally includes the user exit routine and the application intercept exit routine.
Once the user exit routine successfully loads, the address returned by the load service is invoked with the following parameters.
int exit_init (appl_anc, gPFuncListp, exit_anchor) int *appl_anc; void (*gPFuncListp)(); int *exit_anchor; { }
exit_init is invoked immediately after the exit is loaded. It should allocate storage and initialize but make no calls to the graPHIGS API, except to gPSetInterceptExit(C or F) or gPSetPassthruAABscreen
To process the application API call that caused it to be loaded, the user exit routine must make a call to gPSetInterceptExit(C or F) to enable an application intercept exit routine before returning. The graPHIGS API then invokes the specified intercept exit routine prior to returning to the application and on subsequent graPHIGS API subroutine calls.
If exit_init returns non-zero, then the graPHIGS API assumes that the initialization failed. It unloads the exit and proceeds with normal graPHIGS API initialization. If exit_init returns zero, then it loads the application intercept exit routine and processes the API subroutine that caused it to be loaded.
exit_init is also called at termination time. The parameter list is identical for both calls. This makes cleanup symmetrical to initialization.
Due to the possible recursion when error handlers are called, application intercept exit routines must be recursive (no writable statics). For this reason, Fortran is not recommended for a conference controller, although it may work when the application is written in Fortran as well. The only disadvantage to writing all conference controllers in the C programming language is that they require the runtime C library.
An example of how typical declarations might be specified for the initial entry:
/*-----------------------------------------------------------------*/ /* Overlay for function vector (2nd parm on init call). */ /*-----------------------------------------------------------------*/ struct gPfuncv { void (*gPCallThru)(); /* gPCallThru ptr */ void (*gPSetInterceptExitC)(); /* gPSetExit for C exits */ void (*gPSetInterceptExitF)(); /* gPSetExit for F exits */ void (*gPInvApplC)(); /* gPInvAppl for C exits */ void (*gPInvApplF)(); /* gPInvAppl for F exits */ void (*gPSetPassthruAAB)(); /* gPSetPassthruAAB ptr */ }; /*------------------------------------------------------------------*/ /* Main routine for exit. This routine is invoked when the exit is */ /* first loaded. It is invoked only once. */ /*------------------------------------------------------------------*/ int exit_init(appl_anc, funclistp, anchor) int *appl_anc; /* Env anchor (Read/Only) */ struct gPfuncv *funclistp; /* Ptr to function vectors */ int *anchor; /* Anchor for exit storage */ { }
Once the user exit routine has control, it may enable an application intercept exit routine to be given control on the current application request and on subsequent API requests by issuing the gPSetInterceptExit(C or F) function with the address of the intercept exit routine.
If the gPSetInterceptExit(C or F) function is issued with the address of zero in the funcp parameter, then the application intercept exit routine is disabled from being called on each API request. This establishes the environment for the passthru AAB to point to when it replaces the the disabled exit environment. Before disabling an intercept exit, the application must invoke the gPSetPassthruAAB function routine.
A return code of -1 from the application intercept exit routine means that the conference controller will be terminated and replaced by the environment pointed to by the passthru AAB. This allows an exit and its overhead to be removed without terminating an active graPHIGS API application.
For example, for C:
void gPSetInterceptExitC (appl_anc, funcp) int *appl_anc; int (*funcp)(); { }or, for Fortran:
void gPSetInterceptExitF (appl_anc, funcp) int *appl_anc; int (*funcp)(); { }
Any application intercept exit routine that is enabled by the user exit routine through gPSetInterceptExit in response to an API request by the application is invoked as follows:
int intercept_exit(exit_anchor,rcpp,plistp,scbp) int *exit_anchor; int *rcpp; int **plistp; struct scb *scbp; { }
struct scb { char ssid; /* Sub-system id */ /* 'T' = TSO (MVS), */ /* 'V' = VM, 'X' = AIX */ unsigned char iftype; /* 0=non-ren, 1=ren, 2=SPI */ unsigned char binding; /* 0=generic/Fortran, 2=ANSI C */ unsigned char rsvd[1[default] unsigned char rsvd2; void (*erhp)(); /* ANSI default Exit */ }
The application intercept exit routine calls through to the graPHIGS API to process the API request as follows:
void gPCallThru(aab,rcpp,plistp,scbp) int *aab unsigned int *rcpp int **plistp struct scb *scbp { }
Before the application intercept exit routine stops processing the API requests, it issues the following:
void gPSetPassthruAAB(appl_anc,aabp) int *appl_anc int *aabp { }
The gPInvAppl(C or F) routines must be used by the application intercept exit routine when an error handler call from the graPHIGS API is intercepted and is to be passed on to the actual application error handler. gPCallThru does not apply in this case because the application, not the graPHIGS API, is being called.
For example, for C:
void gPInvApplC(appl_anc,routine_addr,parms)or for Fortran:
void gPInvApplF(appl_anc,routine_addr,parms) int *appl_anc void(*routine_addr)() parms { }
Where
These special entry points are necessary because of the great differences in runtime environments among C, Fortran, Pascal, and other programming languages. In order to ensure that a Fortran application with a Fortran error handler runs correctly, graPHIGS API must invoke the error handler with the same register content as when the application last called the graPHIGS APIscreen this process, the graPHIGS API can no longer act directly since the call that generates the error comes from the exit code and not from the application. Exit routines written in a language different from the application must define their own error handlers and pass them on to those of the application using the gPInvAppl(C or F) routine.
The general flow for a conference utility exit routine is shown in Figure 7screen (A) and (B) show the points at which the runtime environment must be the same (that is, the register contents must be very similar).
Figure 7. User Exit Routine Flow