Symbian3/SDK/Source/GUID-2F4B2A69-9B92-52BE-9A1A-FDA501579CE5.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Tue, 20 Jul 2010 12:00:49 +0100
changeset 13 48780e181b38
parent 0 89d6a7a84779
permissions -rw-r--r--
Week 28 contribution of SDK documentation content. See release notes for details. Fixes bugs Bug 1897 and Bug 1522.

<?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-2F4B2A69-9B92-52BE-9A1A-FDA501579CE5" xml:lang="en"><title>Using
Message Queue</title><shortdesc>This topic explains the operations that can be performed using
message queue.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
<ul>
<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 &amp; opening a queue</xref> </p> </li>
<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>
<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>
<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>
<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>
<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>
</ul>
<section id="GUID-D08DB507-7AFD-5ADD-B785-03BF01BE758D"><title>Creating &amp;
opening a queue</title> <p>A global queue is created by calling <codeph>CreateGlobal()</codeph> on
a handle object, while a local queue is created by calling <codeph>CreateLocal()</codeph>.</p> <p>A
global queue is opened by calling <codeph>OpenGlobal()</codeph> on a handle
object, passing a queue name.</p> <p>All the memory used by the queue is allocated
when the queue is created, so it is possible for the call that creates a queue
to fail with out of memory. The queue is deleted when the last open handle
on it is closed.</p> <p><b> Creating
a global named queue</b> </p> <codeblock id="GUID-C70F3600-6198-5DFE-AFA9-2A9366472ED9" xml:space="preserve">_LIT(KGLobalName, "GlobalMessageQueue");
const TInt KNumberOfSlots = 5;
const TInt KMessageLength = 16;
RMsgQueueBase queue;
TInt ret = queue.CreateGlobal(KGLobalName, KNumberOfSlots, KMessageLength, EOwnerProcess);
        </codeblock> <p>This code fragment creates a global named message
queue called <codeph>GlobalMessageQueue</codeph> with 5 slots, each capable
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
practice</i>, you would use the template class <xref href="GUID-5195B8D1-851E-3BEE-A72D-1841C0937300.dita"><apiname>RMsgQueue</apiname></xref>.
For example:</p> <codeblock id="GUID-79040227-DE95-58AB-BC2E-105085AF89F3" xml:space="preserve">class TMyClass
    {
public:
    TInt iA;
    TInt iB;
    TInt iC;
    TInt iD;
    }

_LIT(KGLobalName, "GlobalMessageQueue");
const TInt KNumberOfSlots = 5;
RMsgQueue&lt;TMyClass&gt; queue;
TInt ret = queue.CreateGlobal(KGLobalName, KNumberOfSlots, EOwnerProcess);
        </codeblock> <p>The length of the message is the length of the templated
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;
RMsgQueueBase queue;
TInt ret = queue.CreateLocal(KNumberOfSlots, RMsgQueueBase::KMaxLength);
        </codeblock> <p>This creates a local queue with 2 message slots that
have the maximum possible message size. <i>In practice</i>, you would use
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");
RMsgQueueBase queue;
TInt messageSize = 0;
TInt ret = queue.OpenGlobal(KGLobalName1);
If (ret == KErrNone)
    {
    messageSize = queue.MessageSize();
    }
        </codeblock> <p>This opens the global named message queue called <codeph>GlobalMessageQueue</codeph>.
The message size used within this queue is queried by calling <codeph>MessageSize()</codeph>.
If the queue does not exist <codeph>OpenGlobal()</codeph> returns <codeph>KErrNotFound</codeph>.</p> <p>Note
that using an illegal message size when writing to, or reading from, a queue
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
than the base class <xref href="GUID-2DCEE7F5-9EA3-3546-8779-7299318176E2.dita"><apiname>RMsgQueueBase</apiname></xref> to avoid this problem.</p> </section>
<section id="GUID-2C05D532-9353-5E83-A8D8-1EACB9D44662"><title>Sending a message
to the queue</title> <p>A message is sent to a message queue by calling <codeph>Send()</codeph> or <codeph>SendBlocking()</codeph> on
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
the queue is full, <codeph>SendBlocking()</codeph> waits until there is space
in the queue.</p> <p>The following example creates a global named queue, and
sends 2 integer to values to it. The first call to <codeph>Send()</codeph> returns
an error if the queue is full, the call to <codeph>SendBlocking()</codeph> waits
until there is space in the queue. Although the example code uses the base
class <xref href="GUID-2DCEE7F5-9EA3-3546-8779-7299318176E2.dita"><apiname>RMsgQueueBase</apiname></xref>, <i>in practice</i> you would use the
templated class <xref href="GUID-5195B8D1-851E-3BEE-A72D-1841C0937300.dita"><apiname>RMsgQueue</apiname></xref>, to avoid the risk of passing
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");
RMsgQueueBase mqueue;

TInt ret = mqueue.CreateGlobal(KGLobalName1, 1, sizeof (TInt));
if (ret == KErrNone)
    {
    TInt src = 45;
    ret = mqueue.Send(&amp;src, sizeof (TInt));
    TBool full = (ret == KErrOverflow);

    //blocking send
    src = 32;
    mqueue.SendBlocking(&amp;src, sizeof(TInt));
    mqueue.Close();
    }
        </codeblock> </section>
<section id="GUID-683F69D9-CC59-5F8C-A65B-E69D98737A96"><title>Receiving a
message from the queue</title> <p>A message is received from a message queue
by calling <codeph>Receive()</codeph> or <codeph>ReceiveBlocking()</codeph> on
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
the queue is empty, <codeph>ReceiveBlocking()</codeph> waits until there is
data in the queue.</p> <p>The following example opens a global named queue
and receives 2 integer values from it. The first call to <codeph>Receive()</codeph> returns
an error if the queue is empty, the call to <codeph>ReceiveBlocking()</codeph> waits
until there is data available in the queue. Note also that using the base
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
raising panics if the length specified is not the same as the message size
specified when the queue was originally created, or if the pointer to the
receive buffer is not a valid address.</p> <codeblock id="GUID-9EBE78E0-F7A4-5764-A182-DF7C87E18026" xml:space="preserve">_LIT(KGLobalName, "GlobalMessageQueue");
RMsgQueueBase mqueue;

TInt ret = mqueue.OpenGlobal(KGLobalName1);
if (ret == KErrNone)
    {
    TInt data;
    ret = mqueue.Receive(&amp;data, sizeof (TInt));
    TBool empty = (ret == KErrUnderflow);

    //blocking receive
    mqueue.ReceiveBlocking(&amp;data, sizeof(TInt));
    mqueue.Close();
    }
        </codeblock> </section>
<section id="GUID-1647018E-85C2-58DC-A97A-F90580D9D4E2"><title> Waiting for
messages or space</title> <p>It is possible to be notified:</p> <ul>
<li id="GUID-C67C5535-12C4-5AA6-9E84-947CF4FABCA9"><p>when a queue has messages,
by calling <codeph>NotifyDataAvailable()</codeph> on the base class <xref href="GUID-2DCEE7F5-9EA3-3546-8779-7299318176E2.dita"><apiname>RMsgQueueBase</apiname></xref> </p> </li>
<li id="GUID-307D0C2E-CF65-5572-8BE9-9F9A63B331FC"><p>when a queue has space
for more messages, by calling <codeph>NotifySpaceAvailable()</codeph> on the
base class <xref href="GUID-2DCEE7F5-9EA3-3546-8779-7299318176E2.dita"><apiname>RMsgQueueBase</apiname></xref>.</p> </li>
</ul> <p>Note that the calling <codeph>NotifyDataAvailable()</codeph> when
such a request is still outstanding or calling <codeph>NotifySpaceAvailable()</codeph> when
such a request is already outstanding, results in the calling thread being
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;
mqueue.NotifyDataAvailable(stat);
mqueue.CancelDataAvailable();
User::WaitForRequest(stat);
        </codeblock> </section>
<section id="GUID-A5EABF21-FB2C-5B91-9007-40B4FBE04269"><title>Querying a
Queue’s Size</title> <p>The size of the message slot can be queried by calling <codeph>MessageSize()</codeph> on
the handle. This is useful when a queue is opened, as the calling thread is
panicked if the size is out of range on a <codeph>Send()</codeph> or if the
size is not exact on a <codeph>Receive().</codeph> </p> </section>
<section id="GUID-72033282-9E2F-5E8E-8D78-1B8F6DF42D82"><title>An example
of a type specific queue</title> <p>The size of the message is the size of
the type, and has the same restrictions as the base class, namely it must
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
    {
public:
    TTemplateTestData();
    TTemplateTestData(TInt a, TUint b, TUint8 c, TBool d, TInt e);

public:
    TInt first;
    TUint second;
    TUint8 third;
    TBool fourth;
    TInt fifth;
    };

    {
    ....
    RMsgQueue&lt;TTemplateTestData&gt; templateQueue;

    TTemplateTestData ch(1,2,3,ETrue,4);
    TTemplateTestData ch2;
    TTemplateTestData ch3;

    templateQueue.CreateLocal(12); 
    templateQueue.Send(ch);
    templateQueue.Receive(ch2);
    ....
    templateQueue.Close();
    ...
    }
        </codeblock> <p>Note, the size of the type (i.e. the size of the message)
must be a multiple of 4 bytes.</p> </section>
</conbody></concept>