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