|
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Symbian Foundation License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // An agent plugin may have to service an asynchronous request, for example when |
|
15 // <code>ContentAccess::CAgentManager::NotifyStatusChange()</code> is called. |
|
16 // If the agent plugin must make an asynchronous SendReceive() call to service the request |
|
17 // then it must be careful to ensure that any memory that is passed as an argument |
|
18 // in the call is still valid when the agent server that receives the call processes |
|
19 // and uses the memory. |
|
20 // There are two ways that this can be achieved: |
|
21 // <hr> |
|
22 // If the agent plugin cannot guarantee that a variable to be passed in the asynchronous |
|
23 // SendReceive() call will still be in scope when the agent server comes to access and use |
|
24 // it then the agent plugin should store a local heap copy of the data and pass this |
|
25 // in the call instead. It is the responsibility of the agent plugin to maintain this heap |
|
26 // memory and delete it when appropriate. Depending on how and when the agent server uses |
|
27 // the memory, it may be safe to delete the memory after the asynchronous call has |
|
28 // been accepted, or not until the asynchronous request has completed. |
|
29 // For example, an agent plugin could implement the API <code>ContentAccess::CAgentManager::NotifyStatusChange()</code> |
|
30 // as illustrated below. Note that for this API the agent plugin can make no assumption about the |
|
31 // scope of the descriptor passed to aURI. |
|
32 // void CTestAgentManager::NotifyStatusChange(const TDesC& aURI, TEventMask aMask, TRequestStatus& aStatus) |
|
33 // HBufC* uri = aURI.Alloc(); |
|
34 // if(uri) |
|
35 // // store the heap variable in a local array |
|
36 // iAsyncDataArray.Append(uri); // takes ownership of uri |
|
37 // SendReceive(EManagerNotifyStatusChange, TIpcArgs(uri,aMask),aStatus); |
|
38 // <hr> |
|
39 // Alternatively, the agent plugin can use the variables that are in scope at the time of the |
|
40 // asynchronous SendReceive() call if it makes a synchronous SendReceive() call afterwards, |
|
41 // within the same function scope, as illustrated below. The synchronous message can |
|
42 // be a 'no operation' in the agent server. |
|
43 // void CTestAgentManager::NotifyStatusChange(const TDesC& aURI, TEventMask aMask, TRequestStatus& aStatus) |
|
44 // SendReceive(EManagerNotifyStatusChange, TIpcArgs(&aURI,aMask),aStatus); |
|
45 // // this call doesn't have to be immediately after the asynchronous call, but within this function |
|
46 // SendReceive(ENoOp,TIpcArgs(NULL)); |
|
47 // The synchronous call causes the message queue to be flushed into the agent server before the thread returns from the |
|
48 // function and unwinds the call stack. The intention is that the agent server will only complete the second (synchronous) |
|
49 // message after receiving and doing initial processing of the first (asynchronous) message, which may include, for |
|
50 // example, reading the uri descriptor. |
|
51 // However, an obvious disadvantage of this pattern is that it incurs a second IPC call, and so may degrade performance.<br> |
|
52 // Moreover, there are several caveats which must hold true in order for the pattern to work: |
|
53 // 1. The kernel delivers messages in the order that they are sent (this is currently true).<br> |
|
54 // 2. The agent server is guaranteed to finish processing the first message before completing the second message.<br> |
|
55 // This requires understanding of the agent server implementation.<br> |
|
56 // 3. After initial processing of the first (asynchronous) message the agent server does not need to |
|
57 // access the memory supplied in the message again. This requires understanding of the agent server implementation.<br> |
|
58 // 4. The synchronous call is a request that has no effect on the state of the agent server - a 'no operation' |
|
59 // may or may not be possible. |
|
60 // <b> |
|
61 // For these reasons, this pattern should only be used as a last resort - for example, if the agent plugin cannot store member data in its class for compatibility reasons. |
|
62 // <b> |
|
63 // |
|
64 // |
|
65 |
|
66 |
|
67 |
|
68 /** |
|
69 @page CAFAsyncSendReceive Making an asynchronous SendReceive() call in an agent plugin |
|
70 - @ref StoreLocalCopy |
|
71 - @ref SyncSendReceive |
|
72 @section StoreLocalCopy Storing a local heap copy of transient data |
|
73 @code |
|
74 @endcode |
|
75 @section SyncSendReceive Following the asynchronous call with a synchronous call |
|
76 @code |
|
77 @endcode |
|
78 */ |