diff -r 4816d766a08a -r f345bda72bc4 Symbian3/PDK/Source/GUID-2648B61C-6EBD-4668-AACD-EA4B2C435BB2.dita --- a/Symbian3/PDK/Source/GUID-2648B61C-6EBD-4668-AACD-EA4B2C435BB2.dita Tue Mar 30 11:42:04 2010 +0100 +++ b/Symbian3/PDK/Source/GUID-2648B61C-6EBD-4668-AACD-EA4B2C435BB2.dita Tue Mar 30 11:56:28 2010 +0100 @@ -1,90 +1,90 @@ - - - - - -Message -HandlingThis document describes message queues and message handling. -
Message queues

The -request handling kernel side DFC is managed by a message queue object of the TMessageQueue type. -The message queue consists of a DFC and a doubly linked list of received messages. -The messages are represented by TThreadMessage objects -and are owned by each user thread. Requests are queued as message objects -on the message queue.

The driver framework requires that the driver -sets a DFC queue to use with the message queue. This is done by calling DLogicalChannel::SetDfcQ(). -The message queue must also be enabled to receive incoming messages by calling TMessageQue::Receive().

// Logical Channel Second stage constructor -TInt DExDriverLogicalChannel::DoCreate(TInt /*aUnit*/, const TDesC8* - /*anInfo*/, const TVersion& aVer) - { - ... - // Set up the DFC queue for this driver. Here, the DFC - // queue is created by the PDD dedicated for this driver. - SetDfcQ(Pdd()->DfcQ()); - - // Start receiving the incoming requests on the message queue - iMsgQ.Receive(); - ... - }

The Kernel provides a standard DFC queue, which runs -on a dedicated kernel thread called DFCThread0, for general -use by drivers. However, it is recommended that the driver creates its own -DFC thread to process its requests. The following example shows how a PDD -can implement the DfcQ() function to return a newly created -DFC thread:

// DfcQ - Creates a DFC queue dedicated for the tutorial driver -TDynamicDfcQue* DExUartPhysicalChannelH4::DfcQ() - { - // Create a DFC queue dedicated to the driver with a specified - // priority - TInt r = Kern::DynamicDfcQCreate(pDfcQ,KExUartDfcPriority, - KExUartDfcName); - if (r!=KErrNone) - { - // DfcQ failed, return NULL - return NULL; - } - return iDfcQueue; - }

The DFC thread that is created for the driver must be -destroyed after use. To do this, the driver can create an Exit or Kill DFC -request and queue it to the thread to be destroyed in the logical channel -destructor. This exit DFC function cancels any other requests pending using TDfc::Cancel() and -calls Kern::Exit() to terminate the thread.

The TDynamicDfcQue has -a destroy method that can be run on the channel destructor. The destroy method -destroys the DFC queue, kills the DFC thread and deletes the TDynamicDfcQue object -itself. This avoids the possibilities of memory leaks in the DFC.

-
Message handling

All -synchronous and asynchronous requests are passed to the HandleMsg() function -by the framework, with the message as an argument. A driver should implement -the function to identify the message type and handle the messages accordingly.

The -client thread is blocked until the message is completed, as the request uses -the thread's message object. If the client thread was left free, it would -corrupt the message if another request was issued.

When the driver -has completed handling the message, it notifies the framework by calling TThreadMessage::Complete(). -The client thread is then unblocked, and can either block on the thread semaphore -or issue further requests before blocking.

For synchronous requests, -the message is not completed until the request itself is complete, and the -driver calls the TThreadMessage::Complete() function after -the actual completion of the request. However, for asynchronous requests, -the message is completed after the driver has accepted the request, but not -necessarily after the actual completion of the request, which can happen later. -This means that the driver calls TThreadMessage::Complete() as -soon as it has received the message and initiated the required processing -to complete the request.

void DExDriverLogicalChannel::HandleMsg(TMessageBase* aMsg) - { - TThreadMessage& m = *(TThreadMessage*)aMsg; - // obtain the function id value to determine the request nature - TInt id = m.iValue; - ... - if (id>=0) // Synchronous messages - { - // call synchronous message handler function, DoControl() - TInt r = DoControl(id,m.Ptr0(),m.Ptr1()); - m.Complete(r,ETrue); - return; - } - }
+ + + + + +Message +HandlingThis document describes message queues and message handling. +
Message queues

The +request handling kernel side DFC is managed by a message queue object of the TMessageQueue type. +The message queue consists of a DFC and a doubly linked list of received messages. +The messages are represented by TThreadMessage objects +and are owned by each user thread. Requests are queued as message objects +on the message queue.

The driver framework requires that the driver +sets a DFC queue to use with the message queue. This is done by calling DLogicalChannel::SetDfcQ(). +The message queue must also be enabled to receive incoming messages by calling TMessageQue::Receive().

// Logical Channel Second stage constructor +TInt DExDriverLogicalChannel::DoCreate(TInt /*aUnit*/, const TDesC8* + /*anInfo*/, const TVersion& aVer) + { + ... + // Set up the DFC queue for this driver. Here, the DFC + // queue is created by the PDD dedicated for this driver. + SetDfcQ(Pdd()->DfcQ()); + + // Start receiving the incoming requests on the message queue + iMsgQ.Receive(); + ... + }

The Kernel provides a standard DFC queue, which runs +on a dedicated kernel thread called DFCThread0, for general +use by drivers. However, it is recommended that the driver creates its own +DFC thread to process its requests. The following example shows how a PDD +can implement the DfcQ() function to return a newly created +DFC thread:

// DfcQ - Creates a DFC queue dedicated for the tutorial driver +TDynamicDfcQue* DExUartPhysicalChannelH4::DfcQ() + { + // Create a DFC queue dedicated to the driver with a specified + // priority + TInt r = Kern::DynamicDfcQCreate(pDfcQ,KExUartDfcPriority, + KExUartDfcName); + if (r!=KErrNone) + { + // DfcQ failed, return NULL + return NULL; + } + return iDfcQueue; + }

The DFC thread that is created for the driver must be +destroyed after use. To do this, the driver can create an Exit or Kill DFC +request and queue it to the thread to be destroyed in the logical channel +destructor. This exit DFC function cancels any other requests pending using TDfc::Cancel() and +calls Kern::Exit() to terminate the thread.

The TDynamicDfcQue has +a destroy method that can be run on the channel destructor. The destroy method +destroys the DFC queue, kills the DFC thread and deletes the TDynamicDfcQue object +itself. This avoids the possibilities of memory leaks in the DFC.

+
Message handling

All +synchronous and asynchronous requests are passed to the HandleMsg() function +by the framework, with the message as an argument. A driver should implement +the function to identify the message type and handle the messages accordingly.

The +client thread is blocked until the message is completed, as the request uses +the thread's message object. If the client thread was left free, it would +corrupt the message if another request was issued.

When the driver +has completed handling the message, it notifies the framework by calling TThreadMessage::Complete(). +The client thread is then unblocked, and can either block on the thread semaphore +or issue further requests before blocking.

For synchronous requests, +the message is not completed until the request itself is complete, and the +driver calls the TThreadMessage::Complete() function after +the actual completion of the request. However, for asynchronous requests, +the message is completed after the driver has accepted the request, but not +necessarily after the actual completion of the request, which can happen later. +This means that the driver calls TThreadMessage::Complete() as +soon as it has received the message and initiated the required processing +to complete the request.

void DExDriverLogicalChannel::HandleMsg(TMessageBase* aMsg) + { + TThreadMessage& m = *(TThreadMessage*)aMsg; + // obtain the function id value to determine the request nature + TInt id = m.iValue; + ... + if (id>=0) // Synchronous messages + { + // call synchronous message handler function, DoControl() + TInt r = DoControl(id,m.Ptr0(),m.Ptr1()); + m.Complete(r,ETrue); + return; + } + }
\ No newline at end of file