Symbian3/SDK/Source/GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Fri, 13 Aug 2010 16:47:46 +0100
changeset 14 578be2adaf3e
parent 0 89d6a7a84779
permissions -rw-r--r--
Week 32 contribution of PDK documentation content. See release notes for details. Fixes bug Bug 3582

<?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-FE910347-7CC1-5241-B443-88AD3F5A96EF" xml:lang="en"><title>Using
Publish and Subscribe</title><shortdesc>This topic explains the operations that can be performed using
publish and subscribe.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
<ul>
<li id="GUID-AE4CAAA9-9EB2-5AA0-ACB9-073EAAA9D2C1"><p> <xref href="GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF.dita#GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF/GUID-383A6127-FCE0-5B0E-BD54-3AAFEB097AC9">Creating and closing a handle to a property</xref>  </p> </li>
<li id="GUID-3F0622EC-8490-585A-8CA8-09A3925E842E"><p> <xref href="GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF.dita#GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF/GUID-75BCC783-8DA2-519F-9E4A-B597BDC90E79">Defining a property</xref>  </p> </li>
<li id="GUID-D6C38BDD-02CD-5D9F-8872-DD621D58DB85"><p> <xref href="GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF.dita#GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF/GUID-D942B400-37F8-5C02-AC95-2BD195D3348D">Deleting a property</xref>  </p> </li>
<li id="GUID-ED1DE72F-9111-51A5-9AB2-D7112D947465"><p> <xref href="GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF.dita#GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF/GUID-3B2B63B8-EB2A-5845-A738-A10012A7C896">Publishing a property value</xref>  </p> </li>
<li id="GUID-360F7C12-4909-52EE-9468-E40A3ABC944A"><p> <xref href="GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF.dita#GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF/GUID-CD731DD7-E833-5C67-9B90-0357C9552450">Retrieving a property value</xref>  </p> </li>
<li id="GUID-57301501-34C1-5BE1-9AAB-36F97DBCF5C0"><p> <xref href="GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF.dita#GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF/GUID-A17955E9-FC4C-5FF9-8CC4-2425931E1DEB">Subscribing to, and unsubscribing from, a property</xref>  </p> </li>
<li id="GUID-AAA0B4BB-4B01-5F5E-8617-6D02B36DCEF2"><p> <xref href="GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF.dita#GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF/GUID-EF683969-CED9-5986-938D-3D887E3B39BD">Usage patterns</xref>  </p> </li>
<li id="GUID-E2D3A0BE-1FD9-5B56-928A-4265940E0DEA"><p> <xref href="GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF.dita#GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF/GUID-2B022BE9-2004-54E8-962E-5AB38DDC4222">Making efficient use of the user side API</xref>  </p> </li>
</ul>
<section id="GUID-383A6127-FCE0-5B0E-BD54-3AAFEB097AC9"><title>Creating and
closing a handle to a property</title> <p>Some property operations require
a reference to the property to be established first. This is done using the <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita#GUID-C4776034-D190-3FC4-AF45-C7F195093AC3/GUID-3F65DD85-6061-3370-9618-ECC0400323D1"><apiname>RProperty::Attach()</apiname></xref> member
function. After a call to this function, the <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita"><apiname>RProperty</apiname></xref> object
acts like a standard handle to a kernel resource. When this handle is no longer
required, it can be released in the standard way by calling the inherited <xref href="GUID-727D2B62-09A9-3CBC-AB6F-591E52EC68EB.dita#GUID-727D2B62-09A9-3CBC-AB6F-591E52EC68EB/GUID-4B2775FD-AB61-3850-86C5-780CE8C97573"><apiname>RHandleBase::Close()</apiname></xref> member
function. </p> <p>Note that releasing the handle does not cause the property
to disappear. This only happens if the property is deleted. </p> <p>Note also
that it is quite legitimate to attach to a property that has not been defined,
and in this case no error will be returned either. This enables the lazy definition
of properties as used in some of the usage patterns. </p> <codeblock id="GUID-A836D288-8511-5CED-B3F9-42B60569EE27" xml:space="preserve">// attach to the ‘counter’ property
RProperty counter;
TInt r=counter.Attach(KMyPropertyCat,EMyPropertyName,EOwnerThread);
User::LeaveIfError(r);

// use the counter object...

// when finished, release the handle
counter.Close();
    </codeblock> </section>
<section id="GUID-75BCC783-8DA2-519F-9E4A-B597BDC90E79"><title>Defining a
property</title> <p>A property is defined using the <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita#GUID-C4776034-D190-3FC4-AF45-C7F195093AC3/GUID-58C54D2A-91E0-359B-AA31-69C6C4050173"><apiname>RProperty::Define()</apiname></xref> function,
specifying the attributes of that property. </p> <p>A property does not need
to be defined before it can be accessed. This supports programming patterns
where both publishers and subscribers may define the property. Note, however
that for security reasons, there are restrictions on the category that can
be used when defining a property; see <xref href="GUID-DAF86036-CC40-5F26-9F15-2F2093F59C03.dita">security
issues</xref> for more information. </p> <p>Once defined, a property persists
in the kernel until the system reboots, or the property is explicitly deleted.
Its lifetime is not tied to that of the thread or process that originally
defined it. This means that, when defining a property, it is important to
check the return code from the call <codeph>RProperty::Define()</codeph> to
deal with the possibility that the property has previously been defined, but
not deleted. </p> <p>The following code shows the definition of two properties: </p> <codeblock id="GUID-1F3E05DB-A34B-5D79-8512-52CAD86B0A2D" xml:space="preserve">enum TMyPropertyKeys={EMyPropertyCounter,EMyPropertyName};

static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy);
static _LIT_SECURITY_POLICY_C1(KPowerMgmtPolicy,ECapabilityPowerMgmt);

// define first property to be integer type
TInt r=RProperty::Define(EMyPropertyCounter,RProperty::EInt,KAllowAllPolicy,KPowerMgmtPolicy);
if (r!=KErrAlreadyExists)
    {
    User::LeaveIfError(r);
    }

// define second property to be a byte array, allocating 100 bytes
r=RProperty::Define(EMyPropertyName,RProperty::EByteArray,KAllowAllPolicy,KPowerMgmtPolicy,100);
if (r!=KErrAlreadyExists)
    {
    User::LeaveIfError(r);
    }
. . .
    </codeblock> <p>Once defined, a property value can change, but the property
type cannot. Byte-array type properties can also change length provided the
length does not exceed the maximum value of 512 bytes. The limit on the size
of a property ensures some limit on RAM usage. </p> <p>The API allows byte-array
and Unicode text type properties to be pre-allocated when they are defined.
This means that the time taken to set the values is bounded. However, if the
length of these property types subsequently increases, then memory allocation
may take place, and no guarantees can then be made on the time taken to set
them. </p> <p>There are further <xref href="GUID-DAF86036-CC40-5F26-9F15-2F2093F59C03.dita">security
issues</xref> to be considered when defining a property. You need to provide
two security policies - one to govern which processes can publish the property
value, and the other to govern which processes can retrieve the property value.
Security policies are instances of <xref href="GUID-81A285F6-3F87-3E77-9426-61BB16BC7109.dita"><apiname>TSecurityPolicy</apiname></xref> objects,
although for efficiency reasons, you will almost always use the <codeph>_LIT_SECURITY_POLICY_...</codeph> macros
to generate constant objects that behave like <codeph>TSecurityPolicy</codeph> objects.
The API reference for <xref href="GUID-81A285F6-3F87-3E77-9426-61BB16BC7109.dita"><apiname>TSecurityPolicy</apiname></xref> provides far more
detail on this. </p> <p>In this example, all processes will be allowed to
retrieve the property value, but only those processes having the power management
system capability (<xref href="GUID-76F4383B-4EA5-391A-A271-A8F65ED77EC0.dita"><apiname>ECapabilityPowerMgmt</apiname></xref>) will be allowed
to publish the property value. </p> <p>Note that a process that defines a
property does not have automatic rights of access to that property, other
than to delete it. If the defining process also wishes to publish and/or subscribe
to that property, then it must ensure that it satisfies the security policies
that it itself has put in place when defining the property. </p> </section>
<section id="GUID-D942B400-37F8-5C02-AC95-2BD195D3348D"><title>Deleting a
property</title> <p>A defined property is deleted by calling <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita#GUID-C4776034-D190-3FC4-AF45-C7F195093AC3/GUID-226BC411-A2D2-30D1-BD86-9DDBD855C1E4"><apiname>RProperty::Delete()</apiname></xref>.
Any outstanding subscriptions for this property will complete with <xref href="GUID-5E653C17-372C-32E1-A1B2-9E69A9991C40.dita"><apiname>KErrNotFound</apiname></xref>.
Only the process with the correct secure ID is allowed to delete it. </p> <p>For
example, extending the code fragment introduced above: </p> <codeblock id="GUID-D4CC3017-D17D-5E7C-AC57-0DBD8B789349" xml:space="preserve">enum TMyPropertyKeys={EMyPropertyCounter,EMyPropertyName};

// define first property to be integer type
TInt r=RProperty::Define(EMyPropertyCounter,RProperty::EInt);
if (r!=KErrAlreadyExists)
    {
    User::LeaveIfError(r);
    }

// define second property to be a byte array, allocating 100 bytes
r=RProperty::Define(EMyPropertyName,RProperty::EByteArray,100);
if (r!=KErrAlreadyExists)
    {
    User::LeaveIfError(r);
    }
. . .

// much later on

. . .
// delete the ‘name’ property
r=RProperty::Delete(EMyPropertyName);
if (r!=KErrNotFound)
    {
    User::LeaveIfError(r);
    }
    </codeblock> </section>
<section id="GUID-3B2B63B8-EB2A-5845-A738-A10012A7C896"><title>Publishing
a property value</title> <p>A property is published using the <codeph>RProperty::Set()</codeph> family
of functions. Properties can be published: </p> <ul>
<li id="GUID-3A136703-587F-55B9-9EE6-EE512845956A"><p>using a previously attached <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita"><apiname>RProperty</apiname></xref> handle, </p> </li>
</ul> <p>or </p> <ul>
<li id="GUID-126B0DC1-D4FC-520C-9583-50E64CBC7B80"><p>by specifying the property
category and key with the new value. </p> </li>
</ul> <p>The former mode is guaranteed to have bounded execution time, suitable
for high-priority, real-time tasks, except when publishing a byte-array property
that requires the allocation of a larger space for the new value. </p> <p>The
latter mode offers no real-time guarantees. </p> <p>Property values are written
atomically. This means that it is not possible for threads reading a property
to get a garbled value. </p> <p>All outstanding subscriptions for a property
are completed when the value is published, even if it is exactly the same
as the existing value. This means that a property can be used as a simple
broadcast notification service. </p> <p>Publishing a property that is not
defined is not necessarily a programming error. The <codeph>Set()</codeph> functions
just return an error. If this is not expected for any particular usage, then
the error must be checked and processed by the caller. </p> <p>See the code
fragment in the section <xref href="GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF.dita#GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF/GUID-CD731DD7-E833-5C67-9B90-0357C9552450">Retrieving
a property value</xref>  </p> </section>
<section id="GUID-CD731DD7-E833-5C67-9B90-0357C9552450"><title>Retrieving
a property value</title> <p>The current value of a property is read using
the <codeph>RProperty::Get()</codeph> family of functions. Properties can
be retrieved: </p> <ul>
<li id="GUID-81AD34BF-9A45-5DEE-AD20-AA908F5BF94A"><p>using a previously attached <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita"><apiname>RProperty</apiname></xref> handle, </p> </li>
</ul> <p>or </p> <ul>
<li id="GUID-1163D9F2-BDEA-55E1-B6FB-D9A353F4D53E"><p>by specifying the property
category and key with the new value. </p> </li>
</ul> <p>The former mode is guaranteed to have bounded execution time, suitable
for high-priority, real-time tasks. </p> <p>The latter mode offers no real-time
guarantees. </p> <p>Property values are read atomically. This means that it
is not possible for threads reading a property to get a garbled value. </p> <p>Retrieving
a property that is not defined is not necessarily a programming error. The <codeph>Get()</codeph> functions
just return an error. If this is not expected for any particular usage, then
the error must be checked and processed by the caller. </p> <p>Integer properties
must be accessed using the overloads that take an integer or integer reference
value, whereas byte-array properties can be accessed using the overloads that
take a descriptor reference. </p> <p>The following code fragment shows publication
and retrieval of a property. Note that it uses the idea of attaching to a
property. Note also that it contains a race condition, especially if another
thread is executing the same sequence to increment the ‘counter’ value. </p> <codeblock id="GUID-27B8D567-DD92-5FD6-B2E3-AF343C1116B1" xml:space="preserve">const TUid KMyPropertyCat={0x10012345};
enum TMyPropertyKeys={EMyPropertyCounter,EMyPropertyName};

// attach to the ‘counter’ property
RProperty counter;
TInt r=counter.Attach(KMyPropertyCat,EMyPropertyCounter,EOwnerThread);
User::LeaveIfError(r);

// publish a new name value
TFileName n;
RProcess().Filename(n);
r=RProperty::Set(KMyPropertyCat,EMyPropertyName,n);
User::LeaveIfError(r);

// retrieve the first 10 characters of the name value
TBuf&lt;10&gt; name;
r=RProperty::Get(KMyPropertyCat,EMyPropertyName,name);
if (r!=KErrOverflow)
    {
    User::LeaveIfError(r);
    }

// retrieve and publish a new value using the attached ‘counter’ property
TInt count;
r=counter.Get(count);
if (r==KErrNone)
    {
    r=counter.Set(++count);
    }
User::LeaveIfError(r);

// when finised, release the handle
counter.Close();
    </codeblock> </section>
<section id="GUID-A17955E9-FC4C-5FF9-8CC4-2425931E1DEB"><title>Subscribing
to, and unsubscribing from, a property</title> <p>Subscribing to a property
is the act of making an asynchronous request to be notified of a change to
that property. </p> <p>A thread makes a request for notification of a change
to a property by calling the <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita#GUID-C4776034-D190-3FC4-AF45-C7F195093AC3/GUID-21A2FEB7-AAF1-3AC0-84B9-AB30E6CFFF99"><apiname>RProperty::Subscribe()</apiname></xref> member
function on an already attached property object. Only one subscription request
can be outstanding at any one time for a <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita"><apiname>RProperty</apiname></xref> instance. </p> <p>An
outstanding subscription request can be cancelled by calling the <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita#GUID-C4776034-D190-3FC4-AF45-C7F195093AC3/GUID-326D75D3-9D54-3BD2-8B78-FAD1EEA1A1A5"><apiname>RProperty::Cancel()</apiname></xref> member
function. This is unsubscribing from the property. </p> <p>Subscribing to
a property is a single request to be notified when the property is next updated,
it does not generate an ongoing sequence of notifications for every change
to that property's value. Neither does it provide the caller with the new
value. In essence, the act of notification should be interpreted as “Property
X has changed” rather than “Property X has changed to Y”. This means that
the new value must be explicitly retrieved, if required. As a result, multiple
updates may be collapsed into one notification, and subscribers may not have
visibility of all intermediate values. </p> <p>This might appear to introduce
a window of opportunity for a subscriber to be out of synchronisation with
the property value – in particular, if the property is updated again before
the subscriber thread has had the chance to process the original notification.
However, a simple programming pattern, outlined in the second example below
ensures this does not happen. The principle is that, before dealing with a
subscription completion event, an active object should re-issue the subscription
request. </p> <p>Note that if the property has not been defined, then a subscription
request does not complete until the property is subsequently defined and published.
Note that the request will complete with <xref href="GUID-213DE05E-24F7-3E94-9B35-F4A72B3EBFD8.dita"><apiname>KErrPermissionDenied</apiname></xref> if
the subscribing process does not have sufficient capability as defined by
the <xref href="GUID-81A285F6-3F87-3E77-9426-61BB16BC7109.dita"><apiname>TSecurityPolicy</apiname></xref> object supplied by the process defining
the property. </p> <p>If the property is already defined, then the request
completes immediately with <xref href="GUID-213DE05E-24F7-3E94-9B35-F4A72B3EBFD8.dita"><apiname>KErrPermissionDenied</apiname></xref> if the
subscribing process does not have sufficient capability. </p> <codeblock id="GUID-F8AB71E9-1EB4-5EFB-9D1F-38625F782BA6" xml:space="preserve">const TUid KMyPropertyCat={0x10012345};
enum TMyPropertyKeys={EMyPropertyCounter,EMyPropertyName};

// attach to the ‘counter’ property
RProperty counter;
TInt r=counter.Attach(KMyPropertyCat,EMyPropertyCounter,EOwnerThread);
User::LeaveIfError(r);

// wait for the previously attached ‘counter’ property to be updated
TRequestStatus s;
counter.Subscribe(s);
User::WaitForRequest(s);

// Notification complete, retrieve the counter value.
TInt count;
counter.Get(count);
. . .
    </codeblock> <codeblock id="GUID-5E726809-0060-5E76-A0D5-4AE73155724A" xml:space="preserve">const TUid KMyPropertyCat={0x10012345};
enum TMyPropertyKeys={EMyPropertyCounter,EMyPropertyName};

// Active object that tracks changes to the ‘name’ property
class CPropertyWatch : public CActive
    {
    enum {EPriority=0};
public:
    static CPropertyWatch* NewL();
private:
    CPropertyWatch();
    void ConstructL();
    ~CPropertyWatch();
    void RunL();
    void DoCancel();
private:
    RProperty iProperty;
    };

CPropertyWatch* CPropertyWatch::NewL()
    {
    CPropertyWatch* me=new(ELeave) CPropertyWatch;
    CleanupStack::PushL(me);
    me-&gt;ConstructL();
    CleanupStack::Pop(me);
    return me;
    }

CPropertyWatch::CPropertyWatch()
    :CActive(EPriority)
    {}

void CPropertyWatch::ConstructL()
    {
    User::LeaveIfError(iProperty.Attach(KMyPropertyCat,KMyPropertyName));
    CActiveScheduler::Add(this);
    // initial subscription and process current property value
    RunL();
    }

CPropertyWatch::~CPropertyWatch()
    {
    Cancel();
    iProperty.Close();
    }

void CPropertyWatch::DoCancel()
    {
    iProperty.Cancel();
    }

void CPropertyWatch::RunL()
    {
    // resubscribe before processing new value to prevent missing updates
    iProperty.Subscribe(iStatus);
    SetActive();

    // property updated, get new value
    TFileName n;
    if (iProperty.Get(n)==KErrNotFound)
        {
        // property deleted, do necessary actions here...
        NameDeleted();
        }
    else
        {
        // use new value ...
        NameChanged(n);
        }
    }
    </codeblock> </section>
<section id="GUID-EF683969-CED9-5986-938D-3D887E3B39BD"><title>Usage patterns</title> <p>There
are three usage patterns that can easily be identified, labelled as: standard
state, pure event distribution, and speculative publishing. </p> <p id="GUID-0DFB902E-FCE1-52CF-8523-C7AE7B6768CE"><b>Standard state</b> </p> <p>This
pattern is used for events and state that are known to be used widely in the
system. Examples of this might be battery level and signal strength, which
are important in every phone. </p> <p>The publisher calls <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita#GUID-C4776034-D190-3FC4-AF45-C7F195093AC3/GUID-58C54D2A-91E0-359B-AA31-69C6C4050173"><apiname>RProperty::Define()</apiname></xref> to
create the appropriate property. For byte array or text properties, a size
sufficient for all possible values should be reserved. An error of <xref href="GUID-D1D25122-F2B8-3C78-8599-84905BFD47B8.dita"><apiname>KErrAlreadyExists</apiname></xref> should
be ignored. The publisher then publishes the property values as, and when,
appropriate. If the <codeph>RProperty::Set()</codeph> call fails, this should
be treated as a serious error, since it indicates that important system state
is not getting through. Appropriate action might include panicking or rebooting
the system. Subscribers will use <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita#GUID-C4776034-D190-3FC4-AF45-C7F195093AC3/GUID-21A2FEB7-AAF1-3AC0-84B9-AB30E6CFFF99"><apiname>RProperty::Subscribe()</apiname></xref> to
request notification, and <codeph>RProperty::Get()</codeph> to retrieve the
property value on notification. </p> <p>The memory to store the property value
will be permanently allocated, even if it turns out that no-one in the system
needs that value. This does ensure that the value can always be published,
even if the system is in an out of memory situation. For this reason, this
approach should be limited to widely used and important state. The <xref href="GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF.dita#GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF/GUID-01254366-696D-598F-9670-6A178F4E69F7">Speculative publishing</xref> pattern offers an approach for dealing with
less important state. </p> <p id="GUID-F2A60E64-C279-5E08-8AA8-52DF1EEA32BD"><b>Pure event distribution</b> </p> <p>This
pattern is used when events need to be distributed, not values. </p> <p>The
publisher of the event simply uses an integer property, and calls RProperty::Set()
with any value. Even if the value of the property is not changed by this operation,
all subscribers will be notified that a Set() has occurred, and by implication
that the related event has occurred. </p> <p>Subscribers will be able to detect
that an event has occurred, but will get no other information. The minimum
possible memory is wasted on storage for the dummy value. </p> <p id="GUID-01254366-696D-598F-9670-6A178F4E69F7"><b>Speculative publishing</b> </p> <p>This
pattern is used when it is not known whether a value will be of interest to
others or not. Unlike the <xref href="GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF.dita#GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF/GUID-0DFB902E-FCE1-52CF-8523-C7AE7B6768CE">standard
state</xref> pattern, the publisher of the event does not call <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita#GUID-C4776034-D190-3FC4-AF45-C7F195093AC3/GUID-58C54D2A-91E0-359B-AA31-69C6C4050173"><apiname>RProperty::Define()</apiname></xref> to
create the property. Instead, it simply calls <codeph>RProperty::Set()</codeph> as
appropriate, and ignores any <xref href="GUID-5E653C17-372C-32E1-A1B2-9E69A9991C40.dita"><apiname>KErrNotFound</apiname></xref> error. </p> <p>When
other code in the system, i.e. a potential subscriber, is interested in the
state, it calls <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita#GUID-C4776034-D190-3FC4-AF45-C7F195093AC3/GUID-58C54D2A-91E0-359B-AA31-69C6C4050173"><apiname>RProperty::Define()</apiname></xref> to create the property
and allocate the memory for the value. An error of <xref href="GUID-D1D25122-F2B8-3C78-8599-84905BFD47B8.dita"><apiname>KErrAlreadyExists</apiname></xref> should
be ignored, as this only indicates that some other code in the system is also
interested in the value and has already created the property. </p> <p>The
subscriber then calls <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita#GUID-C4776034-D190-3FC4-AF45-C7F195093AC3/GUID-21A2FEB7-AAF1-3AC0-84B9-AB30E6CFFF99"><apiname>RProperty::Subscribe()</apiname></xref> and <codeph>RProperty::Get()</codeph> as
usual to interact with the property. On the first <codeph>Get()</codeph>,
the subscriber may retrieve the property default value (zero, or a zero length
descriptor). This must be substituted with a sensible default value for the
property in question. </p> <p>Using this pattern, no memory is wasted on properties
that have no subscribers, while the publisher code is simpler as there is
no need for configuration as to which properties to publish. </p> <p>The publisher,
however, wastes some time attempting to publish unneeded values, but this
should not be an issue unless the value is very frequently updated. </p> <p>Where
events are published very infrequently, the subscriber could have a dummy
value for a long time, until the next publish event updates the value. Often
this is not a problem as a default value can be substituted. For example a
full/empty indicator for a battery level, none for signal strength etc. This
pattern is unlikely to be useful if there is no suitable default value. </p> </section>
<section id="GUID-2B022BE9-2004-54E8-962E-5AB38DDC4222"><title>Making efficient
use of the user side API</title> <p>While the Publish and Subscribe API, as
represented by <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita"><apiname>RProperty</apiname></xref> is designed to be efficient, there
are certain usage patterns that can improve performance. </p> <p><b>Use
the attached version of the API calls if possible</b> </p> <p>If you intend
to call <codeph>Set()</codeph> or <codeph>Get()</codeph> repeatedly, it is
preferable to use the attached forms of the calls. The attached forms are
the ones that do not take a UID/Key parameter, and that can only be called
after calling <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita#GUID-C4776034-D190-3FC4-AF45-C7F195093AC3/GUID-3F65DD85-6061-3370-9618-ECC0400323D1"><apiname>RProperty::Attach()</apiname></xref>. The attached variants
are constant time operations, and execute much faster than the corresponding
unattached versions. </p> <p><b>Only
preallocate space if the publishing is time critical</b> </p> <p>For byte-array
and text properties, it is possible to pre-allocate space for the data. Doing
this results in <codeph>Set()</codeph> operations that do not exceed the preallocated
space, avoiding the need to do a memory allocation. However, if the data is
shorter than the reserved space, the excess is wasted. Since <codeph>Set()</codeph> automatically
extends the data area if needed, then the only reason to pre-allocate space
is if the <codeph>Set()</codeph> operation has to be real-time, i.e. has to
have known execution time. </p> <p><b>Always
consider using Speculative Publishing</b> </p> <p>Even in situations where
the <xref href="GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF.dita#GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF/GUID-0DFB902E-FCE1-52CF-8523-C7AE7B6768CE">Standard
State</xref> pattern may seem appropriate, speculative publishing may be a
better choice, specially for low-level components that know little about how
they are used or what the wider system configuration may be. The onus is then
on the UI/Policy layer to ensure that the appropriate properties are defined
early on in device boot according to policy rules it can define. This ensures
that the policy layers in the system maintain control and can implement a
wide variety of policies. </p> <p>Standard state is only relevant for properties
that are essential to every Symbian device. Battery level probably falls into
this category, signal strength may well not. </p> <p><b>Define the expected update frequency</b> </p> <p>When a property is changed,
all subscribers are notified. This leads to their threads running to service
the notification. If a property changes value frequently, it would be wasteful
for subscribers to perform substantial processing for each notification. </p> <p>Take
a property representing signal strength as an example. Potentially, this could
be updated several times a second. If a change in value were only used to
update the UI signal bar, it would not be harmful. However, if it were used
by many entities for serious processing (e.g. polling for email, sending unsent
SMSes, re-connecting to the internet), then such frequent updates would have
a severe effect on battery life. </p> <p>Nevertheless, it is obviously desirable
for many parts of a phone OS to know about the state of network coverage,
and to take appropriate action. In cases like this, it may be worth the publisher
defining multiple properties with associated update characteristics. For example,
raw signal strength (updated &gt; 1 time/sec), periodic signal strength (updated
once every 10s) and network coverage (updated only when moving between some
signal and none). Each subscriber can then monitor the appropriate notification
and so reduce the number of threads that run when the underlying value changes. </p> </section>
</conbody></concept>