DitsActionTransIdWait - Blocks the current action and waits for a message to be received.

Function

Blocks the current action and waits for a message to be received.

Description

The current action is blocked and a message receive loop entered. Other actions can be processed as normal. When a message concerning this action is received, the action is unblocked and will continue. The current entry details (DitsGetArgument() DitsGetEntInfo() etc) will then be for the first message received for this action. The count variable will return the number of other messages still remaining to be processed.

The outstanding messages can be processed by calling this routine repeatly. The action (not the task) will block if the last call returned a count of 0, except if the DONT_BLOCK flag is set.

Note that if after this call is invoke, another action is invoked and calls DitsActionWait/DitsActionTransIdWait/DitsUfaceWait/DitsUfaceTransIdWait, then second action must be unblocked and end/reschedule before control will return to the first action.

If messages received while the action was blocked have not been processed when the action completes, they are lost (a message is output to stderr). To ensure these messages are handled, you should continue calling this routine until count is returned as 0 or reschedule and handle them in the normal reschedule event process.

The action is NOT unblocked when a KICK is received for the action which invokes it, but the Kick handler will be invoked may cause the action to be rescheduled and the action will then be unblocked when the reschedule occurs. An except to this is if the KICK handler causes the action to end. In that case, this routine will return with either the status of the KICK handler (if not STATUS__OK) or with the a STATUS of DITS__WAIT_ABORTED.

If the transaction id argument is non-zero, then will only return if that transaction completes.

This routine may be invoked from either Obey or Kick context of an action, but not both at the same time (status = DITS__WAITALRDY will be returned). If invoked from a Kick handler, the obey handler may stage. If the obey handler causes the action to end, then this routine will return with either the status of the Obey handler (if not STATUS__OK) or with the a STATUS of DITS__WAIT_ABORTED.

If an action which has invoked this routine is killed using DitsKillByName(3)/DitsKillByIndex(3), then this routine will return with a status of DITS__WAIT_ACT_KILLED or the status supplied to the kill routine. The caller should return immediately - whist it could ignore this bad status and cause an allow the action to continue - this is considered rude as the kill routines should cause the action to die.

If after doing a call to DitsActionWait() which returned with count>0, you then reschedule your action (using DitsPutRequest()) with a request of DITS_REQ_STAGE, DITS_REQ_WAIT, DITS_REQ_MESSAGE or DITS_REQ_SLEEP, then DRAMA will commence processing your list of outstanding transactions, as normal reschedule events - i.e. your obey handler is invoked for each message on the list.

During this processing

1.
You are free to send other messages.

2.
If you want to continue processing items from the list in this fashion - you must call DitsPutRequest() with a request of DITS_REQ_STAGE, DITS_REQ_WAIT, DITS_REQ_MESSAGE or DITS_REQ_SLEEP before returning.

3.
You are free to call DitsActionWait() or DitsActionTransIdWait(). These calls will process the next relevant message on the list and can cause the list of messages to be processed.

4.
If your handler returns with bad status, or a request of DITS_REQ_END (the default) or DITS_REQ_EXIT, then the action ends immediately without processing the rest of the list. The messages are lost (with a warning output to stderr).

5.
The only way to process any new messages for your action/task during this processing is to call DitsActionWait() or DitsActionTransIdWait(). Otherwise they will be processed when processing of the list completes.

6.
If the reschedule that started all this requested a delay triggered entry to your action (i.e. specified a delay with a request is DITS_REQ_MESSAGE/DITS_REQ_SLEEP or specified DITS_REQ_WAIT or DITS_REA_STAGE) then that delay is set up after all items on the list have been processed - including new items added to the list by calls to DitsActionWait() or DitsActionTransIdWait().

7.
If a kick message for your action arrives whilst processing this list, presuming you have called DitsActionWait() or DitsActionTransIdWait(), it will be delivered. But any attempt by the kick message to cause the obey to reschedule (say the kick does a DitsPutRequest() with DITS_REQ_STAGE or DITS_REQ_WAIT, or it invokes DitsSignal() to itself) will result in a new message at the END of the list. It won't be proceessed until all other messages on the list are processed. If the kick causes the action to end at this point, the behaviour is the normal behaviour for DitsActionWait() or DitsActionTransIdWait() (see above).

Language

C

Call

(void) = DitsActionTransIdWait (flags, timeout, transId, count, status)

Parameters

(">" input, "!" modified, "W" workspace, "<" output)

>flagsintA bit mask of flags. The possiblities are any or-ed combination of-

DITS_M_AW_FORGET Forget any remaining messages from previous calls to this routine for this action.
DITS_M_AW_DONT_BLOCK Always return immediatley. We will only read a message if there was one outstanding from a previous call.

If there are no outstanding messages or DITS_M_FORGET flag has been set, then no message will be read and count will be set to -1. Action details, such as DitsGetArgument etc., will then be as per prior to the call.

DITS_M_AW_NO_LIST Don't take an entry from the list. If combined with DONT_BLOCK we simply get the count of outstanding messages. Otherwise we block waiting for a message. When the call returns, it will be as per the first item on the list. It is not clear if this flag is usefull to users without the DONT_BLOCK flag.

>timeoutDitsDeltaTimeType *If non-zero, the address of a reschedule delay.
>transIdDitsTransIdTypeIF non-zero, the ID of a transaction to wait for. This must be a transaction ID of a message sent (or to be delivered to) this action.
<countint *Set to the number of messages remaining to be processed. The message which caused the routine to be unblocked is not included. If the DITS_M_DONT_BLOCK flag was set, then count will be -1 if no messages were available. Count is always non-negative in other cases.
!statusStatusType *Modified status. WARNING - status of message receiving code, not the message status. To get the status of the received message, fetch the value from DitsGetEntStatus(). Also - a timeout does not set the status bad, it sets DitsGetEntReason() to DITS_REA_RESCHED.

Include files

DitsInteraction.h

External functions used

ImpClearReminderImp Clear outstanding reminders
ImpQueueReminderImp Queue reminders
ImpReadEndImp Indicate completion of a read by pointer
SdsDeleteSds Delete a structure
SdsFreeIdSds Free a id
DitsMsgReceiveDits Received a dits message.

External values used

DitsTask - Details of the current task

Prior requirements

Can only be invoked in an action's obey or kick context.

See Also

The Dits Specification Document, DitsPutEventWaitHandler(3), DitsUfaceDits(3).

Support

Tony Farrell, AAO

Click here for the DRAMA home page and here for the AAO home page.

 For more information, contact tony.farrell@mq.edu.au