Symbian3/PDK/Source/GUID-B97BAC2E-04E3-4979-BACE-9C46BADE912E.dita
author Graeme Price <GRAEME.PRICE@NOKIA.COM>
Fri, 15 Oct 2010 14:32:18 +0100
changeset 15 307f4279f433
parent 14 578be2adaf3e
permissions -rw-r--r--
Initial contribution of the Adaptation Documentation.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-B97BAC2E-04E3-4979-BACE-9C46BADE912E" xml:lang="en"><title>Deferred
Function Calls</title><shortdesc>This document describes how Deferred Function Calls are used to
implement asynchronous requests.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
<section id="GUID-1F20014A-5F1E-48B3-AEB8-ED1922452A84">   
   <title>Deferred function calls</title> <p>Asynchronous request processing
is normally done in a Deferred Function Call (DFC). The second stage of interrupt
handling is deferred to run as a DFC, which runs in a non-critical context. </p> <p>Different
asynchronous requests can be handled using a single or multiple DFCs. The
number of DFCs to be created must be decided when the driver is designed.
For example, a driver that handles at a time an asynchronous receive request
and a transmit request would create two DFCs each for receive and transmit. </p> 
   </section>
<section id="GUID-5439E26D-754A-46F3-B607-D229BF5B8A8C"><title>Creation</title> <p>DFCs
are created using <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita"><apiname>TDfc</apiname></xref> objects. </p> <p>The DFC is initialised
with a DFC callback function, a pointer to an object to be passed to the callback
function, and a priority. It can also provide the DFC queue to be used by
this DFC at the time of construction. </p> <codeblock id="GUID-B3918CAB-F168-5992-BFA9-868648D07083" xml:space="preserve">TDfc iRxDfc;
iRxDfc(RxDataDfc,this,1); 
    or
iRxDfc(RxDataDfc,this,iDfcQ,1);</codeblock></section>
<section id="GUID-886457DF-0DB5-4447-BC9B-EB43060A5C6B"><title>Queuing</title> <p>To
initiate the process of DFC functionality, the DFC object must be queued to
the DFC queue associated with the Kernel thread. </p> <p>Before adding the
DFC to a DFC queue of the thread, it must be associated with the queue (<xref href="GUID-24B2FEDB-9273-351F-A1C6-6F5F91BF83B7.dita"><apiname>TDfcQue</apiname></xref>)
object. This can be either done at the time of construction, or can be set
later, by calling <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-E3458CD4-7A1C-3FBD-A7FB-488A9C92AE42"><apiname>TDfc::SetDfcQ()</apiname></xref>. </p> <codeblock id="GUID-B57B1C37-A1A5-5C85-AED8-FDD8DBE84280" xml:space="preserve">...
// Associate the Tx and Rx DFCs with the same queue set to receive 
// the client messages for this driver. SetDfcQ() sets up the DFC 
// queue for the DFCs constructed for Tx and Rx
//
iRxDfc.SetDfcQ(iDfcQ);
...</codeblock> <p> <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-18073EBB-D91B-3AC8-87A2-424AEDD4D7A4"><apiname> TDfc::Add()</apiname></xref> or <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-F6F0C858-8EB2-387B-AE1A-F04B51CE4CED"><apiname>TDfc::Enque()</apiname></xref> is
used to add the DFC object to the DFC queue. From an ISR, <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-18073EBB-D91B-3AC8-87A2-424AEDD4D7A4"><apiname>TDfc::Add()</apiname></xref> is
used. From a thread, <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-F6F0C858-8EB2-387B-AE1A-F04B51CE4CED"><apiname>TDfc::Enque()</apiname></xref> is used. If preemption
is disabled, <codeph>TDfc::Add()</codeph> could also be used. </p> <codeblock id="GUID-9FBB6881-4BA9-534E-86C7-3A0167E9159C" xml:space="preserve">// TDfc::Add() will queue an IDFC or a DFC from an ISR. This function 
// is the only way to queue an IDFC and is the only way to queue a 
// DFC from an ISR. To queue a DFC from an IDFC or a thread either 
// TDfc::Enque() or TDfc::DoEnque() should be used. This function 
// does nothing if the IDFC/DFC is already queued.
//
iRxDfc.Add();
</codeblock></section>
<section id="GUID-E0B9073A-1554-4085-BE24-E27633B7EDF2"><title>Callback function</title> <p>The
DFC callback function is a static function called when a DFC is executed.
A pointer to this function is provided at the time of DFC object creation.
This function implements the deferred functionality of an asynchronous request,
such as reading or writing data from or to an I/O peripheral. It would then
either complete the request or start another operation. </p> <codeblock id="GUID-5682EDE1-8397-592D-82CE-78DF11487512" xml:space="preserve">static void RxDataDfc(TAny* aPtr);</codeblock></section>
<section id="GUID-A57C3C99-3032-48CD-A800-E9EE7DCDF4E3"><title>Cancellation</title> <p>A
DFC function must be cancelled while cleaning up resources, for example, when
closing the channel. The function <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-9851B90B-8D05-3C86-B083-44C4564AC140"><apiname>TDfc::Cancel()</apiname></xref> cancels
the DFC if it is already queued. It does nothing if a DFC is not queued. It
must be called to avoid orphaned DFCs. </p> <codeblock id="GUID-CD926E3D-13E8-51C4-B224-8150FD4D70DB" xml:space="preserve">...
// If it is a Transmit request, cancel the Transmit DFC. 
// TDfc::Cancel() cancels the DFC if it is already queued. It 
// does nothing if DFC is not queued.
//
iTxDfc.Cancel();
...</codeblock></section>
</conbody></concept>