|
1 <?xml version="1.0" encoding="utf-8"?> |
|
2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. --> |
|
3 <!-- This component and the accompanying materials are made available under the terms of the License |
|
4 "Eclipse Public License v1.0" which accompanies this distribution, |
|
5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". --> |
|
6 <!-- Initial Contributors: |
|
7 Nokia Corporation - initial contribution. |
|
8 Contributors: |
|
9 --> |
|
10 <!DOCTYPE concept |
|
11 PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd"> |
|
12 <concept id="GUID-2F4B2A69-9B92-52BE-9A1A-FDA501579CE5" xml:lang="en"><title>Using |
|
13 Message Queue</title><shortdesc>This topic explains the operations that can be performed using |
|
14 message queue.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody> |
|
15 <ul> |
|
16 <li id="GUID-47D01156-47CE-5E19-9B0D-222E05851555"><p><xref href="GUID-2F4B2A69-9B92-52BE-9A1A-FDA501579CE5.dita#GUID-2F4B2A69-9B92-52BE-9A1A-FDA501579CE5/GUID-D08DB507-7AFD-5ADD-B785-03BF01BE758D">Creating & opening a queue</xref> </p> </li> |
|
17 <li id="GUID-4CFC9AD9-5303-597D-A339-26064DDA459F"><p><xref href="GUID-2F4B2A69-9B92-52BE-9A1A-FDA501579CE5.dita#GUID-2F4B2A69-9B92-52BE-9A1A-FDA501579CE5/GUID-2C05D532-9353-5E83-A8D8-1EACB9D44662">Sending data to the queue</xref> </p> </li> |
|
18 <li id="GUID-D7A7CB34-16CF-545C-927D-99AF3011C6E7"><p><xref href="GUID-2F4B2A69-9B92-52BE-9A1A-FDA501579CE5.dita#GUID-2F4B2A69-9B92-52BE-9A1A-FDA501579CE5/GUID-683F69D9-CC59-5F8C-A65B-E69D98737A96">Receiving a message from the queue</xref> </p> </li> |
|
19 <li id="GUID-3A517EE0-2B17-5EEF-BFEE-FF98FD1BE9BF"><p><xref href="GUID-2F4B2A69-9B92-52BE-9A1A-FDA501579CE5.dita#GUID-2F4B2A69-9B92-52BE-9A1A-FDA501579CE5/GUID-1647018E-85C2-58DC-A97A-F90580D9D4E2">Waiting for messages or space</xref> </p> </li> |
|
20 <li id="GUID-5379B30A-4E56-5C7E-A7E3-44C8E5592946"><p><xref href="GUID-2F4B2A69-9B92-52BE-9A1A-FDA501579CE5.dita#GUID-2F4B2A69-9B92-52BE-9A1A-FDA501579CE5/GUID-A5EABF21-FB2C-5B91-9007-40B4FBE04269">Querying a Queue’s Size</xref> </p> </li> |
|
21 <li id="GUID-6FD43EA9-4E52-5F60-AD10-314964015F9E"><p><xref href="GUID-2F4B2A69-9B92-52BE-9A1A-FDA501579CE5.dita#GUID-2F4B2A69-9B92-52BE-9A1A-FDA501579CE5/GUID-72033282-9E2F-5E8E-8D78-1B8F6DF42D82">An example of a type specific queue</xref> </p> </li> |
|
22 </ul> |
|
23 <section id="GUID-D08DB507-7AFD-5ADD-B785-03BF01BE758D"><title>Creating & |
|
24 opening a queue</title> <p>A global queue is created by calling <codeph>CreateGlobal()</codeph> on |
|
25 a handle object, while a local queue is created by calling <codeph>CreateLocal()</codeph>.</p> <p>A |
|
26 global queue is opened by calling <codeph>OpenGlobal()</codeph> on a handle |
|
27 object, passing a queue name.</p> <p>All the memory used by the queue is allocated |
|
28 when the queue is created, so it is possible for the call that creates a queue |
|
29 to fail with out of memory. The queue is deleted when the last open handle |
|
30 on it is closed.</p> <p><b> Creating |
|
31 a global named queue</b> </p> <codeblock id="GUID-C70F3600-6198-5DFE-AFA9-2A9366472ED9" xml:space="preserve">_LIT(KGLobalName, "GlobalMessageQueue"); |
|
32 const TInt KNumberOfSlots = 5; |
|
33 const TInt KMessageLength = 16; |
|
34 RMsgQueueBase queue; |
|
35 TInt ret = queue.CreateGlobal(KGLobalName, KNumberOfSlots, KMessageLength, EOwnerProcess); |
|
36 </codeblock> <p>This code fragment creates a global named message |
|
37 queue called <codeph>GlobalMessageQueue</codeph> with 5 slots, each capable |
|
38 of holding a message of size 16 bytes. Note that we have explicitly used <xref href="GUID-2DCEE7F5-9EA3-3546-8779-7299318176E2.dita"><apiname>RMsgQueueBase</apiname></xref>. <i>In |
|
39 practice</i>, you would use the template class <xref href="GUID-5195B8D1-851E-3BEE-A72D-1841C0937300.dita"><apiname>RMsgQueue</apiname></xref>. |
|
40 For example:</p> <codeblock id="GUID-79040227-DE95-58AB-BC2E-105085AF89F3" xml:space="preserve">class TMyClass |
|
41 { |
|
42 public: |
|
43 TInt iA; |
|
44 TInt iB; |
|
45 TInt iC; |
|
46 TInt iD; |
|
47 } |
|
48 |
|
49 _LIT(KGLobalName, "GlobalMessageQueue"); |
|
50 const TInt KNumberOfSlots = 5; |
|
51 RMsgQueue<TMyClass> queue; |
|
52 TInt ret = queue.CreateGlobal(KGLobalName, KNumberOfSlots, EOwnerProcess); |
|
53 </codeblock> <p>The length of the message is the length of the templated |
|
54 class, which in this example is also 16.</p> <p><b>Creating a local message queue</b> </p> <codeblock id="GUID-139E6A88-4F52-5036-AF75-2B3CB91802F0" xml:space="preserve">const TInt KNumberOfSlots = 2; |
|
55 RMsgQueueBase queue; |
|
56 TInt ret = queue.CreateLocal(KNumberOfSlots, RMsgQueueBase::KMaxLength); |
|
57 </codeblock> <p>This creates a local queue with 2 message slots that |
|
58 have the maximum possible message size. <i>In practice</i>, you would use |
|
59 the template class <xref href="GUID-5195B8D1-851E-3BEE-A72D-1841C0937300.dita"><apiname>RMsgQueue</apiname></xref> rather than the base class <xref href="GUID-2DCEE7F5-9EA3-3546-8779-7299318176E2.dita"><apiname>RMsgQueueBase</apiname></xref>.</p> <p><b>Opening a named global queue</b> </p> <codeblock id="GUID-9DCB3D58-0690-50BD-A650-DD78FBFA6447" xml:space="preserve">_LIT(KGLobalName, "GlobalMessageQueue"); |
|
60 RMsgQueueBase queue; |
|
61 TInt messageSize = 0; |
|
62 TInt ret = queue.OpenGlobal(KGLobalName1); |
|
63 If (ret == KErrNone) |
|
64 { |
|
65 messageSize = queue.MessageSize(); |
|
66 } |
|
67 </codeblock> <p>This opens the global named message queue called <codeph>GlobalMessageQueue</codeph>. |
|
68 The message size used within this queue is queried by calling <codeph>MessageSize()</codeph>. |
|
69 If the queue does not exist <codeph>OpenGlobal()</codeph> returns <codeph>KErrNotFound</codeph>.</p> <p>Note |
|
70 that using an illegal message size when writing to, or reading from, a queue |
|
71 is a programming error. <i>In practice</i>, you would use the templated class <xref href="GUID-5195B8D1-851E-3BEE-A72D-1841C0937300.dita"><apiname>RMsgQueue</apiname></xref> rather |
|
72 than the base class <xref href="GUID-2DCEE7F5-9EA3-3546-8779-7299318176E2.dita"><apiname>RMsgQueueBase</apiname></xref> to avoid this problem.</p> </section> |
|
73 <section id="GUID-2C05D532-9353-5E83-A8D8-1EACB9D44662"><title>Sending a message |
|
74 to the queue</title> <p>A message is sent to a message queue by calling <codeph>Send()</codeph> or <codeph>SendBlocking()</codeph> on |
|
75 the message queue handle. <codeph>Send()</codeph> returns the error code <xref href="GUID-F9E0EF8B-4EF5-3E35-811A-00B8F9CCF2FA.dita"><apiname>KErrOverflow</apiname></xref> if |
|
76 the queue is full, <codeph>SendBlocking()</codeph> waits until there is space |
|
77 in the queue.</p> <p>The following example creates a global named queue, and |
|
78 sends 2 integer to values to it. The first call to <codeph>Send()</codeph> returns |
|
79 an error if the queue is full, the call to <codeph>SendBlocking()</codeph> waits |
|
80 until there is space in the queue. Although the example code uses the base |
|
81 class <xref href="GUID-2DCEE7F5-9EA3-3546-8779-7299318176E2.dita"><apiname>RMsgQueueBase</apiname></xref>, <i>in practice</i> you would use the |
|
82 templated class <xref href="GUID-5195B8D1-851E-3BEE-A72D-1841C0937300.dita"><apiname>RMsgQueue</apiname></xref>, to avoid the risk of passing |
|
83 an invalid length, message size, or an invalid data pointer.</p> <codeblock id="GUID-870BFC97-AB6A-5F44-BE3B-BFE2D979CF15" xml:space="preserve">_LIT(KGLobalName, "GlobalMessageQueue"); |
|
84 RMsgQueueBase mqueue; |
|
85 |
|
86 TInt ret = mqueue.CreateGlobal(KGLobalName1, 1, sizeof (TInt)); |
|
87 if (ret == KErrNone) |
|
88 { |
|
89 TInt src = 45; |
|
90 ret = mqueue.Send(&src, sizeof (TInt)); |
|
91 TBool full = (ret == KErrOverflow); |
|
92 |
|
93 //blocking send |
|
94 src = 32; |
|
95 mqueue.SendBlocking(&src, sizeof(TInt)); |
|
96 mqueue.Close(); |
|
97 } |
|
98 </codeblock> </section> |
|
99 <section id="GUID-683F69D9-CC59-5F8C-A65B-E69D98737A96"><title>Receiving a |
|
100 message from the queue</title> <p>A message is received from a message queue |
|
101 by calling <codeph>Receive()</codeph> or <codeph>ReceiveBlocking()</codeph> on |
|
102 the message queue handle. <codeph>Receive()</codeph> returns the error code <xref href="GUID-3673F75F-655F-3561-BD56-F7E1C6980810.dita"><apiname>KErrUnderflow</apiname></xref> if |
|
103 the queue is empty, <codeph>ReceiveBlocking()</codeph> waits until there is |
|
104 data in the queue.</p> <p>The following example opens a global named queue |
|
105 and receives 2 integer values from it. The first call to <codeph>Receive()</codeph> returns |
|
106 an error if the queue is empty, the call to <codeph>ReceiveBlocking()</codeph> waits |
|
107 until there is data available in the queue. Note also that using the base |
|
108 class <xref href="GUID-2DCEE7F5-9EA3-3546-8779-7299318176E2.dita"><apiname>RMsgQueueBase</apiname></xref> rather than the templated class <xref href="GUID-5195B8D1-851E-3BEE-A72D-1841C0937300.dita"><apiname>RMsgQueue</apiname></xref> risks |
|
109 raising panics if the length specified is not the same as the message size |
|
110 specified when the queue was originally created, or if the pointer to the |
|
111 receive buffer is not a valid address.</p> <codeblock id="GUID-9EBE78E0-F7A4-5764-A182-DF7C87E18026" xml:space="preserve">_LIT(KGLobalName, "GlobalMessageQueue"); |
|
112 RMsgQueueBase mqueue; |
|
113 |
|
114 TInt ret = mqueue.OpenGlobal(KGLobalName1); |
|
115 if (ret == KErrNone) |
|
116 { |
|
117 TInt data; |
|
118 ret = mqueue.Receive(&data, sizeof (TInt)); |
|
119 TBool empty = (ret == KErrUnderflow); |
|
120 |
|
121 //blocking receive |
|
122 mqueue.ReceiveBlocking(&data, sizeof(TInt)); |
|
123 mqueue.Close(); |
|
124 } |
|
125 </codeblock> </section> |
|
126 <section id="GUID-1647018E-85C2-58DC-A97A-F90580D9D4E2"><title> Waiting for |
|
127 messages or space</title> <p>It is possible to be notified:</p> <ul> |
|
128 <li id="GUID-C67C5535-12C4-5AA6-9E84-947CF4FABCA9"><p>when a queue has messages, |
|
129 by calling <codeph>NotifyDataAvailable()</codeph> on the base class <xref href="GUID-2DCEE7F5-9EA3-3546-8779-7299318176E2.dita"><apiname>RMsgQueueBase</apiname></xref> </p> </li> |
|
130 <li id="GUID-307D0C2E-CF65-5572-8BE9-9F9A63B331FC"><p>when a queue has space |
|
131 for more messages, by calling <codeph>NotifySpaceAvailable()</codeph> on the |
|
132 base class <xref href="GUID-2DCEE7F5-9EA3-3546-8779-7299318176E2.dita"><apiname>RMsgQueueBase</apiname></xref>.</p> </li> |
|
133 </ul> <p>Note that the calling <codeph>NotifyDataAvailable()</codeph> when |
|
134 such a request is still outstanding or calling <codeph>NotifySpaceAvailable()</codeph> when |
|
135 such a request is already outstanding, results in the calling thread being |
|
136 panicked</p> <p>Notification requests can be cancelled by calling <codeph>CancelDataAvailable()</codeph> or <codeph>CancelDataAvailable()</codeph> respectively.</p> <codeblock id="GUID-960DCF78-0849-59B7-ADF4-95F24EC5B987" xml:space="preserve">TRequestStatus stat; |
|
137 mqueue.NotifyDataAvailable(stat); |
|
138 mqueue.CancelDataAvailable(); |
|
139 User::WaitForRequest(stat); |
|
140 </codeblock> </section> |
|
141 <section id="GUID-A5EABF21-FB2C-5B91-9007-40B4FBE04269"><title>Querying a |
|
142 Queue’s Size</title> <p>The size of the message slot can be queried by calling <codeph>MessageSize()</codeph> on |
|
143 the handle. This is useful when a queue is opened, as the calling thread is |
|
144 panicked if the size is out of range on a <codeph>Send()</codeph> or if the |
|
145 size is not exact on a <codeph>Receive().</codeph> </p> </section> |
|
146 <section id="GUID-72033282-9E2F-5E8E-8D78-1B8F6DF42D82"><title>An example |
|
147 of a type specific queue</title> <p>The size of the message is the size of |
|
148 the type, and has the same restrictions as the base class, namely it must |
|
149 be greater than 0, a multiple of 4 bytes and not greater than <xref href="GUID-2DCEE7F5-9EA3-3546-8779-7299318176E2.dita#GUID-2DCEE7F5-9EA3-3546-8779-7299318176E2/GUID-2E514C07-6917-3DDD-A2E6-CD09A9CD2A6D"><apiname>RMsgQueueBase::KMaxLength</apiname></xref>.</p> <codeblock id="GUID-88F3E2B6-F4B7-53B1-A275-C4AB6BA53448" xml:space="preserve">class TTemplateTestData |
|
150 { |
|
151 public: |
|
152 TTemplateTestData(); |
|
153 TTemplateTestData(TInt a, TUint b, TUint8 c, TBool d, TInt e); |
|
154 |
|
155 public: |
|
156 TInt first; |
|
157 TUint second; |
|
158 TUint8 third; |
|
159 TBool fourth; |
|
160 TInt fifth; |
|
161 }; |
|
162 |
|
163 { |
|
164 .... |
|
165 RMsgQueue<TTemplateTestData> templateQueue; |
|
166 |
|
167 TTemplateTestData ch(1,2,3,ETrue,4); |
|
168 TTemplateTestData ch2; |
|
169 TTemplateTestData ch3; |
|
170 |
|
171 templateQueue.CreateLocal(12); |
|
172 templateQueue.Send(ch); |
|
173 templateQueue.Receive(ch2); |
|
174 .... |
|
175 templateQueue.Close(); |
|
176 ... |
|
177 } |
|
178 </codeblock> <p>Note, the size of the type (i.e. the size of the message) |
|
179 must be a multiple of 4 bytes.</p> </section> |
|
180 </conbody></concept> |