Table of Contents

virtual void AK::StreamMgr::IAkIOHookDeferred::Cancel ( AkFileDesc in_fileDesc,
AkAsyncIOTransferInfo io_transferInfo,
bool &  io_bCancelAllTransfersForThisFile  
) [pure virtual]

Notifies that a transfer request is cancelled. It will be flushed by the streaming device when completed. Cancellation is normal and happens regularly; for example, whenever a sound stops before the end or stops looping. It happens even more frequently when buffering (AkDeviceSettings::fTargetAutoStmBufferLength and AkDeviceSettings::uGranularity) is large and when you low-level IO hook accepts many concurrent requests at the same time.

Remarks:
  • Cancel() simply informs the Low-Level I/O that a specific transfer will be flushed upon reception. The Low-Level I/O may use this information to stop this transfer right away, or not (it is internally tagged by the high-level device as cancelled). Nevertheless, the callback function MUST be called for cancelled transfers to be resolved.
  • When calling the callback function of a cancelled transfer, pass it *AK_Success*. Passing AK_Fail to AkAsyncIOTransfer::pCallback has the effect of killing the stream once and for all. This is not what you want.
  • If io_bCancelAllTransfersForThisFile is set, you may cancel all transfers for this file at once. Leave io_bCancelAllTransfersForThisFile to true if you don't want to be called again. For example, if you don't do anything special in Cancel(), leave it to true. This will reduce the amount of useless calls. If you set it to false, Cancel() will be called again for each remaining pending transfer that need to be cancelled.
  • If io_bCancelAllTransfersForThisFile is not set, Cancel() is only called for a subset of pending transfers for this file. You must not set it to true, as Cancel() needs to be called explicitly for each transfer that should be cancelled.
Warning:
  • The calling thread holds the stream's lock. You may call the callback function directly from here (if you can guarantee that the I/O buffer will not be accessed in the meantime), but you must not wait here for another thread to call the callback function.
  • Likewise, if you resolve transfers with your own thread and use a lock to protect your transfers queue, be careful not to run into a deadlock. Cancel() can be executed by any thread. Thus, if you need to lock your queue in Cancel(), you must never hold this lock when calling back transfers, either from within Cancel() or from your worker thread's routine. Lock your list, dequeue the transfer if you can, unlock, and call pCallback if and only if the transfer was found and dequeued. On the other hand, if you choose not to do anything in Cancel(), the lock only protects your list between Read()/Write() and your worker thread's routine, and since the device I/O thread does not hold the stream's lock while calling Read()/Write(), your worker thread may therefore hold it while calling back transfers.
  • A race condition exists when cancelling all transfers (io_bCancelAllTransfersForThisFile is true) directly from within this hook. If you handle the io_bCancelAllTransfersForThisFile == true case, you need to defer calling the completion callback to later (from your usual I/O completion thread, for example). This will be fixed in a future version of Wwise.
Parameters:
in_fileDesc  File descriptor.
io_transferInfo  Transfer info to cancel.
io_bCancelAllTransfersForThisFile  Flag indicating whether all transfers should be cancelled for this file (see notes in function description).