Symbian3/SDK/Source/GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF.dita
changeset 0 89d6a7a84779
equal deleted inserted replaced
-1:000000000000 0:89d6a7a84779
       
     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-FE910347-7CC1-5241-B443-88AD3F5A96EF" xml:lang="en"><title>Using
       
    13 Publish and Subscribe</title><shortdesc>This topic explains the operations that can be performed using
       
    14 publish and subscribe.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    15 <ul>
       
    16 <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>
       
    17 <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>
       
    18 <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>
       
    19 <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>
       
    20 <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>
       
    21 <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>
       
    22 <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>
       
    23 <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>
       
    24 </ul>
       
    25 <section id="GUID-383A6127-FCE0-5B0E-BD54-3AAFEB097AC9"><title>Creating and
       
    26 closing a handle to a property</title> <p>Some property operations require
       
    27 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
       
    28 function. After a call to this function, the <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita"><apiname>RProperty</apiname></xref> object
       
    29 acts like a standard handle to a kernel resource. When this handle is no longer
       
    30 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
       
    31 function. </p> <p>Note that releasing the handle does not cause the property
       
    32 to disappear. This only happens if the property is deleted. </p> <p>Note also
       
    33 that it is quite legitimate to attach to a property that has not been defined,
       
    34 and in this case no error will be returned either. This enables the lazy definition
       
    35 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
       
    36 RProperty counter;
       
    37 TInt r=counter.Attach(KMyPropertyCat,EMyPropertyName,EOwnerThread);
       
    38 User::LeaveIfError(r);
       
    39 
       
    40 // use the counter object...
       
    41 
       
    42 // when finished, release the handle
       
    43 counter.Close();
       
    44     </codeblock> </section>
       
    45 <section id="GUID-75BCC783-8DA2-519F-9E4A-B597BDC90E79"><title>Defining a
       
    46 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,
       
    47 specifying the attributes of that property. </p> <p>A property does not need
       
    48 to be defined before it can be accessed. This supports programming patterns
       
    49 where both publishers and subscribers may define the property. Note, however
       
    50 that for security reasons, there are restrictions on the category that can
       
    51 be used when defining a property; see <xref href="GUID-DAF86036-CC40-5F26-9F15-2F2093F59C03.dita">security
       
    52 issues</xref> for more information. </p> <p>Once defined, a property persists
       
    53 in the kernel until the system reboots, or the property is explicitly deleted.
       
    54 Its lifetime is not tied to that of the thread or process that originally
       
    55 defined it. This means that, when defining a property, it is important to
       
    56 check the return code from the call <codeph>RProperty::Define()</codeph> to
       
    57 deal with the possibility that the property has previously been defined, but
       
    58 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};
       
    59 
       
    60 static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy);
       
    61 static _LIT_SECURITY_POLICY_C1(KPowerMgmtPolicy,ECapabilityPowerMgmt);
       
    62 
       
    63 // define first property to be integer type
       
    64 TInt r=RProperty::Define(EMyPropertyCounter,RProperty::EInt,KAllowAllPolicy,KPowerMgmtPolicy);
       
    65 if (r!=KErrAlreadyExists)
       
    66     {
       
    67     User::LeaveIfError(r);
       
    68     }
       
    69 
       
    70 // define second property to be a byte array, allocating 100 bytes
       
    71 r=RProperty::Define(EMyPropertyName,RProperty::EByteArray,KAllowAllPolicy,KPowerMgmtPolicy,100);
       
    72 if (r!=KErrAlreadyExists)
       
    73     {
       
    74     User::LeaveIfError(r);
       
    75     }
       
    76 . . .
       
    77     </codeblock> <p>Once defined, a property value can change, but the property
       
    78 type cannot. Byte-array type properties can also change length provided the
       
    79 length does not exceed the maximum value of 512 bytes. The limit on the size
       
    80 of a property ensures some limit on RAM usage. </p> <p>The API allows byte-array
       
    81 and Unicode text type properties to be pre-allocated when they are defined.
       
    82 This means that the time taken to set the values is bounded. However, if the
       
    83 length of these property types subsequently increases, then memory allocation
       
    84 may take place, and no guarantees can then be made on the time taken to set
       
    85 them. </p> <p>There are further <xref href="GUID-DAF86036-CC40-5F26-9F15-2F2093F59C03.dita">security
       
    86 issues</xref> to be considered when defining a property. You need to provide
       
    87 two security policies - one to govern which processes can publish the property
       
    88 value, and the other to govern which processes can retrieve the property value.
       
    89 Security policies are instances of <xref href="GUID-81A285F6-3F87-3E77-9426-61BB16BC7109.dita"><apiname>TSecurityPolicy</apiname></xref> objects,
       
    90 although for efficiency reasons, you will almost always use the <codeph>_LIT_SECURITY_POLICY_...</codeph> macros
       
    91 to generate constant objects that behave like <codeph>TSecurityPolicy</codeph> objects.
       
    92 The API reference for <xref href="GUID-81A285F6-3F87-3E77-9426-61BB16BC7109.dita"><apiname>TSecurityPolicy</apiname></xref> provides far more
       
    93 detail on this. </p> <p>In this example, all processes will be allowed to
       
    94 retrieve the property value, but only those processes having the power management
       
    95 system capability (<xref href="GUID-76F4383B-4EA5-391A-A271-A8F65ED77EC0.dita"><apiname>ECapabilityPowerMgmt</apiname></xref>) will be allowed
       
    96 to publish the property value. </p> <p>Note that a process that defines a
       
    97 property does not have automatic rights of access to that property, other
       
    98 than to delete it. If the defining process also wishes to publish and/or subscribe
       
    99 to that property, then it must ensure that it satisfies the security policies
       
   100 that it itself has put in place when defining the property. </p> </section>
       
   101 <section id="GUID-D942B400-37F8-5C02-AC95-2BD195D3348D"><title>Deleting a
       
   102 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>.
       
   103 Any outstanding subscriptions for this property will complete with <xref href="GUID-5E653C17-372C-32E1-A1B2-9E69A9991C40.dita"><apiname>KErrNotFound</apiname></xref>.
       
   104 Only the process with the correct secure ID is allowed to delete it. </p> <p>For
       
   105 example, extending the code fragment introduced above: </p> <codeblock id="GUID-D4CC3017-D17D-5E7C-AC57-0DBD8B789349" xml:space="preserve">enum TMyPropertyKeys={EMyPropertyCounter,EMyPropertyName};
       
   106 
       
   107 // define first property to be integer type
       
   108 TInt r=RProperty::Define(EMyPropertyCounter,RProperty::EInt);
       
   109 if (r!=KErrAlreadyExists)
       
   110     {
       
   111     User::LeaveIfError(r);
       
   112     }
       
   113 
       
   114 // define second property to be a byte array, allocating 100 bytes
       
   115 r=RProperty::Define(EMyPropertyName,RProperty::EByteArray,100);
       
   116 if (r!=KErrAlreadyExists)
       
   117     {
       
   118     User::LeaveIfError(r);
       
   119     }
       
   120 . . .
       
   121 
       
   122 // much later on
       
   123 
       
   124 . . .
       
   125 // delete the ‘name’ property
       
   126 r=RProperty::Delete(EMyPropertyName);
       
   127 if (r!=KErrNotFound)
       
   128     {
       
   129     User::LeaveIfError(r);
       
   130     }
       
   131     </codeblock> </section>
       
   132 <section id="GUID-3B2B63B8-EB2A-5845-A738-A10012A7C896"><title>Publishing
       
   133 a property value</title> <p>A property is published using the <codeph>RProperty::Set()</codeph> family
       
   134 of functions. Properties can be published: </p> <ul>
       
   135 <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>
       
   136 </ul> <p>or </p> <ul>
       
   137 <li id="GUID-126B0DC1-D4FC-520C-9583-50E64CBC7B80"><p>by specifying the property
       
   138 category and key with the new value. </p> </li>
       
   139 </ul> <p>The former mode is guaranteed to have bounded execution time, suitable
       
   140 for high-priority, real-time tasks, except when publishing a byte-array property
       
   141 that requires the allocation of a larger space for the new value. </p> <p>The
       
   142 latter mode offers no real-time guarantees. </p> <p>Property values are written
       
   143 atomically. This means that it is not possible for threads reading a property
       
   144 to get a garbled value. </p> <p>All outstanding subscriptions for a property
       
   145 are completed when the value is published, even if it is exactly the same
       
   146 as the existing value. This means that a property can be used as a simple
       
   147 broadcast notification service. </p> <p>Publishing a property that is not
       
   148 defined is not necessarily a programming error. The <codeph>Set()</codeph> functions
       
   149 just return an error. If this is not expected for any particular usage, then
       
   150 the error must be checked and processed by the caller. </p> <p>See the code
       
   151 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
       
   152 a property value</xref>  </p> </section>
       
   153 <section id="GUID-CD731DD7-E833-5C67-9B90-0357C9552450"><title>Retrieving
       
   154 a property value</title> <p>The current value of a property is read using
       
   155 the <codeph>RProperty::Get()</codeph> family of functions. Properties can
       
   156 be retrieved: </p> <ul>
       
   157 <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>
       
   158 </ul> <p>or </p> <ul>
       
   159 <li id="GUID-1163D9F2-BDEA-55E1-B6FB-D9A353F4D53E"><p>by specifying the property
       
   160 category and key with the new value. </p> </li>
       
   161 </ul> <p>The former mode is guaranteed to have bounded execution time, suitable
       
   162 for high-priority, real-time tasks. </p> <p>The latter mode offers no real-time
       
   163 guarantees. </p> <p>Property values are read atomically. This means that it
       
   164 is not possible for threads reading a property to get a garbled value. </p> <p>Retrieving
       
   165 a property that is not defined is not necessarily a programming error. The <codeph>Get()</codeph> functions
       
   166 just return an error. If this is not expected for any particular usage, then
       
   167 the error must be checked and processed by the caller. </p> <p>Integer properties
       
   168 must be accessed using the overloads that take an integer or integer reference
       
   169 value, whereas byte-array properties can be accessed using the overloads that
       
   170 take a descriptor reference. </p> <p>The following code fragment shows publication
       
   171 and retrieval of a property. Note that it uses the idea of attaching to a
       
   172 property. Note also that it contains a race condition, especially if another
       
   173 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};
       
   174 enum TMyPropertyKeys={EMyPropertyCounter,EMyPropertyName};
       
   175 
       
   176 // attach to the ‘counter’ property
       
   177 RProperty counter;
       
   178 TInt r=counter.Attach(KMyPropertyCat,EMyPropertyCounter,EOwnerThread);
       
   179 User::LeaveIfError(r);
       
   180 
       
   181 // publish a new name value
       
   182 TFileName n;
       
   183 RProcess().Filename(n);
       
   184 r=RProperty::Set(KMyPropertyCat,EMyPropertyName,n);
       
   185 User::LeaveIfError(r);
       
   186 
       
   187 // retrieve the first 10 characters of the name value
       
   188 TBuf&lt;10&gt; name;
       
   189 r=RProperty::Get(KMyPropertyCat,EMyPropertyName,name);
       
   190 if (r!=KErrOverflow)
       
   191     {
       
   192     User::LeaveIfError(r);
       
   193     }
       
   194 
       
   195 // retrieve and publish a new value using the attached ‘counter’ property
       
   196 TInt count;
       
   197 r=counter.Get(count);
       
   198 if (r==KErrNone)
       
   199     {
       
   200     r=counter.Set(++count);
       
   201     }
       
   202 User::LeaveIfError(r);
       
   203 
       
   204 // when finised, release the handle
       
   205 counter.Close();
       
   206     </codeblock> </section>
       
   207 <section id="GUID-A17955E9-FC4C-5FF9-8CC4-2425931E1DEB"><title>Subscribing
       
   208 to, and unsubscribing from, a property</title> <p>Subscribing to a property
       
   209 is the act of making an asynchronous request to be notified of a change to
       
   210 that property. </p> <p>A thread makes a request for notification of a change
       
   211 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
       
   212 function on an already attached property object. Only one subscription request
       
   213 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
       
   214 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
       
   215 function. This is unsubscribing from the property. </p> <p>Subscribing to
       
   216 a property is a single request to be notified when the property is next updated,
       
   217 it does not generate an ongoing sequence of notifications for every change
       
   218 to that property's value. Neither does it provide the caller with the new
       
   219 value. In essence, the act of notification should be interpreted as “Property
       
   220 X has changed” rather than “Property X has changed to Y”. This means that
       
   221 the new value must be explicitly retrieved, if required. As a result, multiple
       
   222 updates may be collapsed into one notification, and subscribers may not have
       
   223 visibility of all intermediate values. </p> <p>This might appear to introduce
       
   224 a window of opportunity for a subscriber to be out of synchronisation with
       
   225 the property value – in particular, if the property is updated again before
       
   226 the subscriber thread has had the chance to process the original notification.
       
   227 However, a simple programming pattern, outlined in the second example below
       
   228 ensures this does not happen. The principle is that, before dealing with a
       
   229 subscription completion event, an active object should re-issue the subscription
       
   230 request. </p> <p>Note that if the property has not been defined, then a subscription
       
   231 request does not complete until the property is subsequently defined and published.
       
   232 Note that the request will complete with <xref href="GUID-213DE05E-24F7-3E94-9B35-F4A72B3EBFD8.dita"><apiname>KErrPermissionDenied</apiname></xref> if
       
   233 the subscribing process does not have sufficient capability as defined by
       
   234 the <xref href="GUID-81A285F6-3F87-3E77-9426-61BB16BC7109.dita"><apiname>TSecurityPolicy</apiname></xref> object supplied by the process defining
       
   235 the property. </p> <p>If the property is already defined, then the request
       
   236 completes immediately with <xref href="GUID-213DE05E-24F7-3E94-9B35-F4A72B3EBFD8.dita"><apiname>KErrPermissionDenied</apiname></xref> if the
       
   237 subscribing process does not have sufficient capability. </p> <codeblock id="GUID-F8AB71E9-1EB4-5EFB-9D1F-38625F782BA6" xml:space="preserve">const TUid KMyPropertyCat={0x10012345};
       
   238 enum TMyPropertyKeys={EMyPropertyCounter,EMyPropertyName};
       
   239 
       
   240 // attach to the ‘counter’ property
       
   241 RProperty counter;
       
   242 TInt r=counter.Attach(KMyPropertyCat,EMyPropertyCounter,EOwnerThread);
       
   243 User::LeaveIfError(r);
       
   244 
       
   245 // wait for the previously attached ‘counter’ property to be updated
       
   246 TRequestStatus s;
       
   247 counter.Subscribe(s);
       
   248 User::WaitForRequest(s);
       
   249 
       
   250 // Notification complete, retrieve the counter value.
       
   251 TInt count;
       
   252 counter.Get(count);
       
   253 . . .
       
   254     </codeblock> <codeblock id="GUID-5E726809-0060-5E76-A0D5-4AE73155724A" xml:space="preserve">const TUid KMyPropertyCat={0x10012345};
       
   255 enum TMyPropertyKeys={EMyPropertyCounter,EMyPropertyName};
       
   256 
       
   257 // Active object that tracks changes to the ‘name’ property
       
   258 class CPropertyWatch : public CActive
       
   259     {
       
   260     enum {EPriority=0};
       
   261 public:
       
   262     static CPropertyWatch* NewL();
       
   263 private:
       
   264     CPropertyWatch();
       
   265     void ConstructL();
       
   266     ~CPropertyWatch();
       
   267     void RunL();
       
   268     void DoCancel();
       
   269 private:
       
   270     RProperty iProperty;
       
   271     };
       
   272 
       
   273 CPropertyWatch* CPropertyWatch::NewL()
       
   274     {
       
   275     CPropertyWatch* me=new(ELeave) CPropertyWatch;
       
   276     CleanupStack::PushL(me);
       
   277     me-&gt;ConstructL();
       
   278     CleanupStack::Pop(me);
       
   279     return me;
       
   280     }
       
   281 
       
   282 CPropertyWatch::CPropertyWatch()
       
   283     :CActive(EPriority)
       
   284     {}
       
   285 
       
   286 void CPropertyWatch::ConstructL()
       
   287     {
       
   288     User::LeaveIfError(iProperty.Attach(KMyPropertyCat,KMyPropertyName));
       
   289     CActiveScheduler::Add(this);
       
   290     // initial subscription and process current property value
       
   291     RunL();
       
   292     }
       
   293 
       
   294 CPropertyWatch::~CPropertyWatch()
       
   295     {
       
   296     Cancel();
       
   297     iProperty.Close();
       
   298     }
       
   299 
       
   300 void CPropertyWatch::DoCancel()
       
   301     {
       
   302     iProperty.Cancel();
       
   303     }
       
   304 
       
   305 void CPropertyWatch::RunL()
       
   306     {
       
   307     // resubscribe before processing new value to prevent missing updates
       
   308     iProperty.Subscribe(iStatus);
       
   309     SetActive();
       
   310 
       
   311     // property updated, get new value
       
   312     TFileName n;
       
   313     if (iProperty.Get(n)==KErrNotFound)
       
   314         {
       
   315         // property deleted, do necessary actions here...
       
   316         NameDeleted();
       
   317         }
       
   318     else
       
   319         {
       
   320         // use new value ...
       
   321         NameChanged(n);
       
   322         }
       
   323     }
       
   324     </codeblock> </section>
       
   325 <section id="GUID-EF683969-CED9-5986-938D-3D887E3B39BD"><title>Usage patterns</title> <p>There
       
   326 are three usage patterns that can easily be identified, labelled as: standard
       
   327 state, pure event distribution, and speculative publishing. </p> <p id="GUID-0DFB902E-FCE1-52CF-8523-C7AE7B6768CE"><b>Standard state</b> </p> <p>This
       
   328 pattern is used for events and state that are known to be used widely in the
       
   329 system. Examples of this might be battery level and signal strength, which
       
   330 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
       
   331 create the appropriate property. For byte array or text properties, a size
       
   332 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
       
   333 be ignored. The publisher then publishes the property values as, and when,
       
   334 appropriate. If the <codeph>RProperty::Set()</codeph> call fails, this should
       
   335 be treated as a serious error, since it indicates that important system state
       
   336 is not getting through. Appropriate action might include panicking or rebooting
       
   337 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
       
   338 request notification, and <codeph>RProperty::Get()</codeph> to retrieve the
       
   339 property value on notification. </p> <p>The memory to store the property value
       
   340 will be permanently allocated, even if it turns out that no-one in the system
       
   341 needs that value. This does ensure that the value can always be published,
       
   342 even if the system is in an out of memory situation. For this reason, this
       
   343 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
       
   344 less important state. </p> <p id="GUID-F2A60E64-C279-5E08-8AA8-52DF1EEA32BD"><b>Pure event distribution</b> </p> <p>This
       
   345 pattern is used when events need to be distributed, not values. </p> <p>The
       
   346 publisher of the event simply uses an integer property, and calls RProperty::Set()
       
   347 with any value. Even if the value of the property is not changed by this operation,
       
   348 all subscribers will be notified that a Set() has occurred, and by implication
       
   349 that the related event has occurred. </p> <p>Subscribers will be able to detect
       
   350 that an event has occurred, but will get no other information. The minimum
       
   351 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
       
   352 pattern is used when it is not known whether a value will be of interest to
       
   353 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
       
   354 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
       
   355 create the property. Instead, it simply calls <codeph>RProperty::Set()</codeph> as
       
   356 appropriate, and ignores any <xref href="GUID-5E653C17-372C-32E1-A1B2-9E69A9991C40.dita"><apiname>KErrNotFound</apiname></xref> error. </p> <p>When
       
   357 other code in the system, i.e. a potential subscriber, is interested in the
       
   358 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
       
   359 and allocate the memory for the value. An error of <xref href="GUID-D1D25122-F2B8-3C78-8599-84905BFD47B8.dita"><apiname>KErrAlreadyExists</apiname></xref> should
       
   360 be ignored, as this only indicates that some other code in the system is also
       
   361 interested in the value and has already created the property. </p> <p>The
       
   362 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
       
   363 usual to interact with the property. On the first <codeph>Get()</codeph>,
       
   364 the subscriber may retrieve the property default value (zero, or a zero length
       
   365 descriptor). This must be substituted with a sensible default value for the
       
   366 property in question. </p> <p>Using this pattern, no memory is wasted on properties
       
   367 that have no subscribers, while the publisher code is simpler as there is
       
   368 no need for configuration as to which properties to publish. </p> <p>The publisher,
       
   369 however, wastes some time attempting to publish unneeded values, but this
       
   370 should not be an issue unless the value is very frequently updated. </p> <p>Where
       
   371 events are published very infrequently, the subscriber could have a dummy
       
   372 value for a long time, until the next publish event updates the value. Often
       
   373 this is not a problem as a default value can be substituted. For example a
       
   374 full/empty indicator for a battery level, none for signal strength etc. This
       
   375 pattern is unlikely to be useful if there is no suitable default value. </p> </section>
       
   376 <section id="GUID-2B022BE9-2004-54E8-962E-5AB38DDC4222"><title>Making efficient
       
   377 use of the user side API</title> <p>While the Publish and Subscribe API, as
       
   378 represented by <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita"><apiname>RProperty</apiname></xref> is designed to be efficient, there
       
   379 are certain usage patterns that can improve performance. </p> <p><b>Use
       
   380 the attached version of the API calls if possible</b> </p> <p>If you intend
       
   381 to call <codeph>Set()</codeph> or <codeph>Get()</codeph> repeatedly, it is
       
   382 preferable to use the attached forms of the calls. The attached forms are
       
   383 the ones that do not take a UID/Key parameter, and that can only be called
       
   384 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
       
   385 are constant time operations, and execute much faster than the corresponding
       
   386 unattached versions. </p> <p><b>Only
       
   387 preallocate space if the publishing is time critical</b> </p> <p>For byte-array
       
   388 and text properties, it is possible to pre-allocate space for the data. Doing
       
   389 this results in <codeph>Set()</codeph> operations that do not exceed the preallocated
       
   390 space, avoiding the need to do a memory allocation. However, if the data is
       
   391 shorter than the reserved space, the excess is wasted. Since <codeph>Set()</codeph> automatically
       
   392 extends the data area if needed, then the only reason to pre-allocate space
       
   393 is if the <codeph>Set()</codeph> operation has to be real-time, i.e. has to
       
   394 have known execution time. </p> <p><b>Always
       
   395 consider using Speculative Publishing</b> </p> <p>Even in situations where
       
   396 the <xref href="GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF.dita#GUID-FE910347-7CC1-5241-B443-88AD3F5A96EF/GUID-0DFB902E-FCE1-52CF-8523-C7AE7B6768CE">Standard
       
   397 State</xref> pattern may seem appropriate, speculative publishing may be a
       
   398 better choice, specially for low-level components that know little about how
       
   399 they are used or what the wider system configuration may be. The onus is then
       
   400 on the UI/Policy layer to ensure that the appropriate properties are defined
       
   401 early on in device boot according to policy rules it can define. This ensures
       
   402 that the policy layers in the system maintain control and can implement a
       
   403 wide variety of policies. </p> <p>Standard state is only relevant for properties
       
   404 that are essential to every Symbian device. Battery level probably falls into
       
   405 this category, signal strength may well not. </p> <p><b>Define the expected update frequency</b> </p> <p>When a property is changed,
       
   406 all subscribers are notified. This leads to their threads running to service
       
   407 the notification. If a property changes value frequently, it would be wasteful
       
   408 for subscribers to perform substantial processing for each notification. </p> <p>Take
       
   409 a property representing signal strength as an example. Potentially, this could
       
   410 be updated several times a second. If a change in value were only used to
       
   411 update the UI signal bar, it would not be harmful. However, if it were used
       
   412 by many entities for serious processing (e.g. polling for email, sending unsent
       
   413 SMSes, re-connecting to the internet), then such frequent updates would have
       
   414 a severe effect on battery life. </p> <p>Nevertheless, it is obviously desirable
       
   415 for many parts of a phone OS to know about the state of network coverage,
       
   416 and to take appropriate action. In cases like this, it may be worth the publisher
       
   417 defining multiple properties with associated update characteristics. For example,
       
   418 raw signal strength (updated &gt; 1 time/sec), periodic signal strength (updated
       
   419 once every 10s) and network coverage (updated only when moving between some
       
   420 signal and none). Each subscriber can then monitor the appropriate notification
       
   421 and so reduce the number of threads that run when the underlying value changes. </p> </section>
       
   422 </conbody></concept>