It is possible to cancel an action which is in a wait state. Here is a simple example.
interface timer action WAIT obey endobey cancel endcancel endaction endinterface SUBROUTINE TIMER ( STATUS ) IMPLICIT NONE INCLUDE 'SAE_PAR' INCLUDE 'ACT_ERR' INCLUDE 'ADAMDEFNS' INTEGER STATUS INTEGER SEQ INTEGER CONTEXT IF ( STATUS .NE. SAI__OK ) RETURN CALL TASK_GET_CONTEXT ( CONTEXT, STATUS ) IF ( CONTEXT .EQ. OBEY ) THEN CALL TASK_GET_SEQ ( SEQ, STATUS ) IF ( SEQ .EQ. 0 ) THEN CALL TASK_PUT_DELAY ( 10000, STATUS ) CALL TASK_PUT_REQUEST ( ACT__WAIT, STATUS ) ELSE CALL MSG_OUT ( ' ', 'finished', STATUS ) ENDIF ELSE IF ( CONTEXT .EQ. CANCEL ) THEN CALL MSG_OUT ( ' ', 'I was cancelled', STATUS ) CALL TASK_PUT_REQUEST ( ACT__CANCEL, STATUS ) ENDIF END
Note the CANCEL declaration in the interface file. This example is exercised by
ICL> send timer obey wait ICL> send timer cancel wait
It is possible to write the application such that CANCEL modifies the behaviour of the rescheduling action rather than terminating it.
interface timer parameter CANTIME type '_INTEGER' endparameter action WAIT obey endobey cancel needs CANTIME endcancel endaction endinterface SUBROUTINE TIMER ( STATUS ) IMPLICIT NONE INCLUDE 'SAE_PAR' INCLUDE 'ACT_ERR' INCLUDE 'ADAMDEFNS' INTEGER STATUS INTEGER SEQ INTEGER CONTEXT INTEGER STATE SAVE STATE, TIME IF ( STATUS .NE. SAI__OK ) RETURN CALL TASK_GET_CONTEXT ( CONTEXT, STATUS ) IF ( CONTEXT .EQ. OBEY ) THEN CALL TASK_GET_SEQ ( SEQ, STATUS ) IF ( SEQ .EQ. 0 ) THEN STATE = 0 CALL TASK_PUT_DELAY ( 500, STATUS ) CALL TASK_PUT_REQUEST ( ACT__WAIT, STATUS ) ELSE IF ( STATE .EQ. 0 ) THEN * Normal reschedule CALL TASK_PUT_DELAY ( 500, STATUS ) CALL MSG_OUT ( ' ', 'default timer', STATUS ) CALL TASK_PUT_REQUEST ( ACT__WAIT, STATUS ) ELSE * Rescheduling after CANCEL CALL TASK_PUT_DELAY ( TIME, STATUS ) CALL MSG_OUT ( ' ', 'altered timer', STATUS ) CALL TASK_PUT_REQUEST ( ACT__WAIT, STATUS ) ENDIF ENDIF ELSE IF ( CONTEXT .EQ. CANCEL ) THEN STATE = 1 CALL PAR_GET0I ( 'CANTIME', TIME, STATUS ) CALL TASK_PUT_DELAY ( TIME, STATUS ) CALL MSG_OUT ( ' ', 'timer changed', STATUS ) CALL TASK_PUT_REQUEST ( ACT__WAIT, STATUS ) ENDIF END
Then:
ICL> send timer obey wait ICL> send timer cancel wait 10000
will cause the task to start rescheduling at 0.5sec intervals, but then switch to rescheduling at 10sec intervals. In this particular example the action never terminates.
An example of sending a CANCEL to a task which is controlling a
subsidiary task is given in Appendix .
ADAM Guide to Writing Instrumentation Tasks