Adaptation/GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D.dita
changeset 15 307f4279f433
equal deleted inserted replaced
14:578be2adaf3e 15:307f4279f433
       
     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-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D" xml:lang="en"><title>Publish
       
    13 and Subscribe</title><shortdesc>Publish and Subscribe allows global variables to be set and retrieved,
       
    14 and allows subscribers to be notified that variables have changed. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    15 <p>The general pattern for using on the kernel side is almost the same as
       
    16 for the user side. However, different classes are used on the kernel side.
       
    17 It may be useful to compare kernel side usage with user side usage as described
       
    18 in the <xref href="GUID-A81C65CF-CF4E-571C-8080-9D387F46AAD6.dita">Publish and
       
    19 Subscribe</xref> guide for the user-side API. </p>
       
    20 <ul>
       
    21 <li id="GUID-BDAE8BFE-B0F9-5A3D-9E2B-6AC6280195E5"><p> <xref href="GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D.dita#GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D/GUID-AD33A76A-9A27-5D66-B583-64F360EC996E">Properties</xref> </p> </li>
       
    22 <li id="GUID-3D892E85-C506-5FF6-A8E2-3A9458800CBB"><p> <xref href="GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D.dita#GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D/GUID-E2261227-E747-53E0-9EE3-9CEC824C1832">Creating and closing a reference to a property</xref>  </p> </li>
       
    23 <li id="GUID-728CCCEB-8F5F-5CA1-A650-803C94E64194"><p> <xref href="GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D.dita#GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D/GUID-C41886EF-24EC-58C2-A906-C4890CED3F3A">Defining a property</xref>  </p> </li>
       
    24 <li id="GUID-FB0EC3DC-38E1-5701-AF84-47A814238163"><p> <xref href="GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D.dita#GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D/GUID-60F19D41-F9B5-5A21-9654-5D96CA6EE83E">Deleting a property</xref>  </p> </li>
       
    25 <li id="GUID-FAE51C6E-1C39-593C-B2AD-7BEFAA257F72"><p> <xref href="GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D.dita#GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D/GUID-EBAA6B5C-CC73-5AE2-85CA-68B445828608">Publishing a property value</xref>  </p> </li>
       
    26 <li id="GUID-2F1A3E2F-44C8-5532-8FA2-F49A4FC58623"><p> <xref href="GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D.dita#GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D/GUID-CA858A2A-4BF0-565D-8A6D-58AE32FEE304">Retrieving a property value</xref>  </p> </li>
       
    27 <li id="GUID-C39FCE8D-082E-56E8-85B2-137B25B88C61"><p> <xref href="GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D.dita#GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D/GUID-984AB90D-FCCD-5383-B5D9-8D80AA83D989">Subscribing to, and unsubscribing from, a property </xref>  </p> </li>
       
    28 <li id="GUID-E02C9293-56B4-5AC0-9DA8-F47E6796A07D"><p> <xref href="GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D.dita#GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D/GUID-21D8ADCA-9B39-5079-B4AD-FEBFCCB92049">Usage patterns</xref>  </p> </li>
       
    29 </ul>
       
    30 <section id="GUID-AD33A76A-9A27-5D66-B583-64F360EC996E"><title>Properties</title> <p>A
       
    31 property has the two attributes: identity and type. </p> <p><b>Identity</b> </p> <p>A
       
    32 property is identified by a 64-bit integer made up of two 32-bit parts: the
       
    33 category and the key. </p> <p>A property belongs to a category, and a category
       
    34 is identified by a UID. </p> <p>A key is a 32-bit value that identifies a
       
    35 specific property within a category. The meaning applied to the key depends
       
    36 on the kind of enumeration scheme set up for the category. At its simplest,
       
    37 a key can be an index value. It can also be another UID, if the category is
       
    38 designed to be generally extensible. </p> <p><b>Type</b> </p> <p>A property
       
    39 can be: </p> <ul>
       
    40 <li id="GUID-083AF1CA-ACA1-53A3-A251-370DD1D06554"><p>a single 32-bit value </p> </li>
       
    41 <li id="GUID-6EA61CFF-F549-5FA2-A6AA-43683C802B8D"><p>a contiguous set of
       
    42 bytes, referred to as a byte-array, whose length can vary from 0 to 512 bytes </p> </li>
       
    43 </ul><p>Once defined, a property value can change, but the property type cannot.
       
    44 Byte-array type properties can also change length provided the length does
       
    45 not exceed the value <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita#GUID-C4776034-D190-3FC4-AF45-C7F195093AC3/GUID-57E64054-610A-31D1-AD7F-E2F9F9FC1DCB"><apiname>RProperty::KMaxPropertySize</apiname></xref>. The limit
       
    46 on size of property ensures some limit on RAM usage. </p><p>The API allows
       
    47 a byte-array text type property to be pre-allocated when it is defined. This
       
    48 means that the time taken to set the values is bounded. However, if the length
       
    49 of this property type subsequently increases, then memory allocation may take
       
    50 place, and no guarantees can be made on the time taken to set them.</p><p>Note
       
    51 that the <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita#GUID-C4776034-D190-3FC4-AF45-C7F195093AC3/GUID-F8DE443B-B208-353C-A98E-AA52C4FE6530"><apiname>RProperty::ELargeByteArray</apiname></xref> property type can never
       
    52 provide a real-time guarantee. </p><p>For code running kernel side, properties
       
    53 and their values are defined, set and retrieved using a <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita"><apiname>RPropertyRef</apiname></xref> object.</p> </section>
       
    54 <section id="GUID-E2261227-E747-53E0-9EE3-9CEC824C1832"><title>Creating and
       
    55 closing a reference to a property</title> <p>On the kernel side, all accesses
       
    56 to a property <i>must</i> be done through a property reference, an instance
       
    57 of a <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita"><apiname>RPropertyRef</apiname></xref>. </p> <p>You must create a reference
       
    58 to a property, before doing any operation on that property. By operation,
       
    59 we mean defining a property, subscribing to a property, publishing and retrieving
       
    60 a property value. The kernel will fault if you have not first created a reference. </p> <p>Only
       
    61 one property, as uniquely identified by its category and key, can be accessed
       
    62 by an instance of <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita"><apiname>RPropertyRef</apiname></xref>; however a property can
       
    63 be referenced by more than one instance of <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita"><apiname>RPropertyRef</apiname></xref>. </p> <p>Internally,
       
    64 properties are represented by <codeph>TProperty</codeph> objects, and these
       
    65 are reference counted. The act of creating a reference to a property results
       
    66 either in the creation of a <codeph>TProperty</codeph> object or an increase
       
    67 in the reference count of an existing object. The property itself has no attributes
       
    68 or "structure" until it is defined. </p> <p>Please note that the structure
       
    69 and management of <codeph>TProperty</codeph> objects are part of Symbian platform's
       
    70 internal implementation and will not be discussed further. </p> <fig id="GUID-8A0D9C1E-00D7-5369-AD9C-28AA9151612F">
       
    71 <title>Objects internal to Symbian platform</title>
       
    72 <image href="GUID-31CE66F2-B36C-56ED-A399-BA9EFA179DED_d0e75538_href.png" placement="inline"/>
       
    73 </fig> <p>To establish a reference to a property, create an <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita"><apiname>RPropertyRef</apiname></xref> object,
       
    74 and then use one of the following functions: </p> <ul>
       
    75 <li id="GUID-87D76A73-6429-5D4C-8321-A98F756C30F5"><p> <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-DBEDDC3A-AE6F-3CAF-B251-4AA556EAF21C"><apiname>RPropertyRef::Attach()</apiname></xref> -
       
    76 tries to open the property identified by the category and key, if it exists,
       
    77 but creates that property if it does not exist. Creation is simply the act
       
    78 of creating the internal <codeph>TProperty</codeph> object. The object has
       
    79 no type or "structure" associated with it other than the use of the category
       
    80 and key as identification markers. </p> </li>
       
    81 <li id="GUID-7D1AFF17-BB0A-57B9-9782-001E983D9EDE"><p> <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-6F8EB0AB-C01A-3BFD-B334-D9C9FB923865"><apiname>RPropertyRef::Open()</apiname></xref> -
       
    82 tries to open the property identified by the category and key, and assumes
       
    83 that the property already exists; this fails if the property does not exist. </p> </li>
       
    84 </ul> <p>You can call these functions from a user thread running in supervisor
       
    85 mode, from a kernel thread or from a DFC. If calling from a user thread running
       
    86 in supervisor mode, then your thread must be running in a critical section.
       
    87 In debug mode, if a user thread is not in a critical section, then the kernel
       
    88 will fault. </p> <p>On successful return from these functions, the <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita"><apiname>RPropertyRef</apiname></xref> object
       
    89 owns a resource, the property, and this can then be defined and accessed through
       
    90 the <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita"><apiname>RPropertyRef</apiname></xref> object. </p> <p>It is difficult to make
       
    91 firm rules as to which one your code should use, but generally, you use <codeph>Open()</codeph> if
       
    92 you have no responsibility or interest in ensuring that the property exists.
       
    93 You would use <codeph>Attach()</codeph> if you were to have single or <i>joint</i> responsibility
       
    94 for ensuring that the property exists. It depends on the intent of the property
       
    95 and the role of your driver code in the system. </p> <p>Note that responsibility
       
    96 for creating the property does not necessarily align with who can define,
       
    97 delete, publish (write) or retrieve (read) a property value. This is governed
       
    98 by the intent of the property and, for retrieving and publishing, by the security
       
    99 policies in place. </p> <p>When the property is no longer needed, you can
       
   100 release it by calling <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-3465CD78-C107-3AD9-AEAF-F97A94C1C462"><apiname>RPropertyRef::Close()</apiname></xref>. Closing the
       
   101 reference does not cause the property to disappear. This only happens when
       
   102 the <i>final</i> reference to the property is closed. </p> <p>Note that it
       
   103 is quite legitimate to attach to, or to open, a property that has not been
       
   104 defined, and in this case no error will be returned either. This enables the
       
   105 lazy definition of properties as used in some of the usage patterns. </p> <codeblock id="GUID-7F4295E4-F822-5128-B4EC-3AD3E71BD444" xml:space="preserve">const TUid KMyPropertyCat={0x10012345};
       
   106 enum TMyPropertyKeys={EMyPropertyCounter,EMyPropertyName};
       
   107 
       
   108 . . .
       
   109 
       
   110 // Attach to the ‘counter’ property. This creates the property
       
   111 // if it does not already exist.
       
   112 RPropertyRef counter;
       
   113 TInt r;
       
   114 r=counter.Attach(KMyPropertyCat,EMyPropertyCounter);
       
   115 
       
   116 // r should be KErrNone if sucessful or KErrNoMemory if there
       
   117 // is an out of memory failure.
       
   118 if (r != KErrNone)
       
   119     {
       
   120     // Handle the bad return value
       
   121     }
       
   122 
       
   123 // use the counter object...
       
   124 
       
   125 // when finished, release the property
       
   126 counter.Close();
       
   127     </codeblock> </section>
       
   128 <section id="GUID-C41886EF-24EC-58C2-A906-C4890CED3F3A"><title>Defining a
       
   129 property </title> <p>Defining a property gives it "structure" i.e. attributes
       
   130 such as the property type, and the security policies that define the capabilities
       
   131 that a process must have to publish and retrieve the property value. </p> <p>A
       
   132 property is defined using the <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-47F367CB-E663-3F97-AC0C-31A9DD6BD5E5"><apiname>RPropertyRef::Define()</apiname></xref> function.
       
   133 You can call this function from a user thread running in supervisor mode,
       
   134 from a kernel thread or from a DFC. If calling from a user thread running
       
   135 in supervisor mode, then your thread must be running in a critical section.
       
   136 In debug mode, if a user thread is not in a critical section, then the kernel
       
   137 will fault. </p> <p>You can call this function from a user thread running
       
   138 in supervisor mode, from a kernel thread or from a DFC. If calling from a
       
   139 user thread running in supervisor mode, then your thread must be running in
       
   140 a critical section. In debug mode, if a user thread is not in a critical section,
       
   141 then the kernel will fault. </p> <p>The information needed to define the property
       
   142 is passed to <codeph>Define()</codeph>. Note that a reference to the property
       
   143 must already have been established using <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-DBEDDC3A-AE6F-3CAF-B251-4AA556EAF21C"><apiname>RPropertyRef::Attach()</apiname></xref> or <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-6F8EB0AB-C01A-3BFD-B334-D9C9FB923865"><apiname>RPropertyRef::Open()</apiname></xref>. </p> <p>A
       
   144 property does not need to be defined before it can be accessed. This supports
       
   145 programming patterns where both publishers and subscribers may define the
       
   146 property. </p> <p>Once defined, a property persists until the system reboots,
       
   147 or the property is explicitly deleted. Its lifetime is not tied to that of
       
   148 the thread or process that originally defined it. This means that, when defining
       
   149 a property, it is important to check the return code from the call to <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-47F367CB-E663-3F97-AC0C-31A9DD6BD5E5"><apiname>RPropertyRef::Define()</apiname></xref> to
       
   150 deal with the possibility that the property has previously been defined. </p> <p>The
       
   151 following code shows the definition of two properties, which we call: 'name'
       
   152 and 'counter': </p> <codeblock id="GUID-318DC2A6-FFE4-5781-9F78-5D5B4392585F" xml:space="preserve">const TUid KMyPropertyCat={0x10012345};
       
   153 enum TMyPropertyKeys={EMyPropertyCounter,EMyPropertyName};
       
   154 
       
   155 static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy);
       
   156 static _LIT_SECURITY_POLICY_C1(KPowerMgmtPolicy,ECapabilityPowerMgmt);
       
   157 
       
   158 TInt r;
       
   159 
       
   160 // Attaches to the ‘counter’ property. 
       
   161 // If the property already exists, a new reference to it is created.
       
   162 // If the property does not exist, it is created.
       
   163 RPropertyRef counter;
       
   164 r=counter.Attach(KMyPropertyCat,EMyPropertyCounter);
       
   165 if (r != KErrNone)
       
   166     {
       
   167     // Handle the bad return value
       
   168     }
       
   169 
       
   170 // Attaches to the ‘name’ property. 
       
   171 // If the property already exists, a new reference to it is created.
       
   172 // If the property does not exist, it is created.
       
   173 RPropertyRef name;
       
   174 r=name.Attach(KMyPropertyCat,EMyPropertyName);
       
   175 if (r != KErrNone)
       
   176     {
       
   177     // Handle the bad return value
       
   178     }
       
   179 
       
   180 // Now define the 'counter' property:
       
   181 // 1. Integer type
       
   182 // 2. Pre-allocated size has no meaning, and must be zero.
       
   183 // 3. Allow all processes to retrieve (read) the property.
       
   184 // 4. Only processes with power managament capability can write.
       
   185 // 5. Capability checks to be done against client thread's process.
       
   186 
       
   187 r=counter.Define(RProperty::EInt,KAllowAllPolicy,KPowerMgmtPolicy,0,iClientProcess);
       
   188 
       
   189 // You will probably need to check the return value.
       
   190 // It may legitimately by non-KErrNone.
       
   191 
       
   192 ...
       
   193 
       
   194 // Now define the 'name' property:
       
   195 // 1. Byte array
       
   196 // 2. Pre-allocate 100 bytes.
       
   197 // 3. Allow all processes to retrieve (read) the property.
       
   198 // 4. Only processes with power managament capability can write.
       
   199 // 5. Capability checks to be done against client thread's process.
       
   200 
       
   201 r=name.Define(RProperty::EByteArray,KAllowAllPolicy,KPowerMgmtPolicy,100,iClientProcess);
       
   202 
       
   203 // You will probably need to check the return value.
       
   204 // It may legitimately be non-KErrNone.
       
   205 ...</codeblock> <p>Once defined, a property value can change, but the property
       
   206 type cannot. Byte-array type properties can also change length provided the
       
   207 length does not exceed the 512 bytes, for <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita#GUID-C4776034-D190-3FC4-AF45-C7F195093AC3/GUID-19066DA4-B407-3C31-8472-371CA341BDC7"><apiname>RProperty::EByteArray</apiname></xref> types
       
   208 or 65535 bytes or <xref href="GUID-C4776034-D190-3FC4-AF45-C7F195093AC3.dita#GUID-C4776034-D190-3FC4-AF45-C7F195093AC3/GUID-F8DE443B-B208-353C-A98E-AA52C4FE6530"><apiname>RProperty::ELargeByteArray</apiname></xref> types. </p> <p>The
       
   209 API allows byte-array type properties to be pre-allocated when they are defined.
       
   210 This means that the time taken to set the values is bounded. However, if the
       
   211 length of these property types subsequently increases, then memory allocation
       
   212 may take place, and no guarantees can then be made on the time taken to set
       
   213 them. </p> <p> <b>Security notes:</b>  </p> <ul>
       
   214 <li id="GUID-E46B65DD-5D93-5796-8762-D8637947350D"><p>Symbian platform defines
       
   215 a property category known as the system category that is reserved for system
       
   216 services, and is identified by the <xref href="GUID-A85740BD-BC85-345E-B24A-92F68EA56270.dita"><apiname>KUidSystemCategoryValue</apiname></xref> UID.
       
   217 To define a property within this category, then the process on whose behalf
       
   218 your code is doing the define operation must have the <i>writeDeviceData</i> capability, <xref href="GUID-C607209F-6FC5-31DE-8034-E5B799B857A8.dita"><apiname>ECapabilityWriteDeviceData</apiname></xref>. </p> <p>To
       
   219 ensure that this security check is made, you must pass a pointer to the appropriate <codeph>DProcess</codeph> object
       
   220 as the second parameter to <codeph>Define()</codeph>. If you omit this parameter,
       
   221 a null pointer is assumed by default, and <i>the security check is bypassed</i>.
       
   222 This may be legitimate if you are doing this on behalf of the kernel or on
       
   223 behalf of the driver itself. </p> </li>
       
   224 <li id="GUID-18AA5E54-23AE-564F-BCB0-0F9FF70DEFD5"><p>Whether you pass a <codeph>DProcess</codeph> pointer
       
   225 or not, the owner of the property is deemed to be the process that is <i>current</i> when
       
   226 the code runs. It is this, the current process, that you will need to pass
       
   227 to <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-73FB49F1-E9EF-3CE3-A317-8888BAE49403"><apiname>RPropertyRef::Delete()</apiname></xref> at a later time. </p> </li>
       
   228 <li id="GUID-A941BD4F-E288-5A71-9F78-08351665AE73"><p>You also need to define
       
   229 two security policies: one to define the capabilities that will be required
       
   230 to publish (write to) the property, and the other to define the capabilities
       
   231 that will be required to retrieve (read) the property. Security policies are <xref href="GUID-81A285F6-3F87-3E77-9426-61BB16BC7109.dita"><apiname>TSecurityPolicy</apiname></xref> objects
       
   232 or their static equivalents. </p> <p>In the above code fragment, we specify
       
   233 that all processes in the system will be able to read the defined property
       
   234 but only those with power management capability will be able to write to the
       
   235 property - this is an arbitrary choice and is for illustration only. </p> </li>
       
   236 </ul> <p>In the above code fragments, <codeph>iClientProcess</codeph> is a
       
   237 pointer to the client thread's owning process object, and assumes that the
       
   238 driver code is making the request on behalf of a client, although this may
       
   239 not necessarily be so. Typically, if you need to keep this information, you
       
   240 could set this up in the logical channel constructor using the following code: </p> <codeblock id="GUID-33D0D5EA-8BB2-57DB-A327-D17A6A5C2D8E" xml:space="preserve">iClientProcess=&amp;Kern::CurrentProcess();</codeblock> <p>The
       
   241 constructor code runs in the context of the client user thread. Note that <codeph>DProcess</codeph> is
       
   242 internal to Symbian. </p> </section>
       
   243 <section id="GUID-60F19D41-F9B5-5A21-9654-5D96CA6EE83E"><title>Deleting a
       
   244 property </title> <p>Deleting a property is the opposite of defining it. It
       
   245 removes type and security information. It does <i>not</i> remove a reference
       
   246 to the property. </p> <p>A property is deleted using the <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-73FB49F1-E9EF-3CE3-A317-8888BAE49403"><apiname>RPropertyRef::Delete()</apiname></xref> function.
       
   247 You can call this function from a user thread running in supervisor mode,
       
   248 from a kernel thread or from a DFC. If calling from a user thread running
       
   249 in supervisor mode, then your thread must be running in a critical section.
       
   250 In debug mode, if a user thread is not in a critical section, then the kernel
       
   251 will fault. </p> <p>Any outstanding subscriptions for this property complete
       
   252 with <xref href="GUID-5E653C17-372C-32E1-A1B2-9E69A9991C40.dita"><apiname>KErrNotFound</apiname></xref>. </p> <p> <b>Security notes:</b>  </p> <ul>
       
   253 <li id="GUID-1B901363-70E9-560B-9C56-C63BB6D180C0"><p>Only the owning process
       
   254 is allowed to delete the property. This is deemed to be the process that was
       
   255 current when the property was defined. However, to enforce this, you <i>must</i> pass
       
   256 into <xref href="GUID-331FCC3D-B326-37A1-8AF5-381320224BBE.dita#GUID-331FCC3D-B326-37A1-8AF5-381320224BBE/GUID-2838E746-C917-3FB0-B2BA-464C38B5944B"><apiname>RPropertyref::Delete()</apiname></xref> a pointer to the <codeph>DProcess</codeph> object
       
   257 that represents the owning process. If you omit to pass this parameter to <codeph>Delete()</codeph>,
       
   258 a null pointer is assumed by default, and <i>the security check is bypassed.</i>.
       
   259 This may be legitimate if you are doing this on behalf of the kernel or on
       
   260 behalf of the driver itself. </p> </li>
       
   261 </ul> <p>For example, extending the code fragment introduced in defining a
       
   262 property above: </p> <codeblock id="GUID-25FBD12A-4461-5A92-9961-960DB26FE3F8" xml:space="preserve">const TUid KMyPropertyCat={0x10012345};
       
   263 enum TMyPropertyKeys={EMyPropertyCounter,EMyPropertyName};
       
   264 
       
   265 static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy);
       
   266 static _LIT_SECURITY_POLICY_C1(KPowerMgmtPolicy,ECapabilityPowerMgmt);
       
   267 
       
   268 TInt r;
       
   269 
       
   270 // Attaches to the ‘counter’ property. 
       
   271 // If the property already exists, a new reference to it is created.
       
   272 // If the property does not exist, it is created.
       
   273 RPropertyRef counter;
       
   274 r=counter.Attach(KMyPropertyCat,EMyPropertyCounter);
       
   275 if (r != KErrNone)
       
   276     {
       
   277     // Handle the bad return value
       
   278     }
       
   279 
       
   280 // Attaches to the ‘name’ property. 
       
   281 // If the property already exists, a new reference to it is created.
       
   282 // If the property does not exist, it is created.
       
   283 RPropertyRef name;
       
   284 r=name.Attach(KMyPropertyCat,EMyPropertyName);
       
   285 if (r != KErrNone)
       
   286     {
       
   287     // Handle the bad return value
       
   288     }
       
   289 
       
   290 // Now define the 'counter' property:
       
   291 // 1. Integer type
       
   292 // 2. Pre-allocated size has no meaning, and must be zero.
       
   293 // 3. Allow all processes to retrieve (read) the property.
       
   294 // 4. Only processes with power managament capability can write.
       
   295 // 5. Capability checks to be done against client thread's process.
       
   296 
       
   297 r=counter.Define(RProperty::EInt,KAllowAllPolicy,KPowerMgmtPolicy,0,iClientProcess);
       
   298 
       
   299 // You will probably need to check the return value.
       
   300 // It may legitimately by non-KErrNone.
       
   301 
       
   302 ...
       
   303 
       
   304 // Now define the 'name' property:
       
   305 // 1. Byte array
       
   306 // 2. Pre-allocate 100 bytes.
       
   307 // 3. Allow all processes to retrieve (read) the property.
       
   308 // 4. Only processes with power managament capability can write.
       
   309 // 5. Capability checks to be done against client thread's process.
       
   310 
       
   311 r=name.Define(RProperty::EByteArray,KAllowAllPolicy,KPowerMgmtPolicy,100,iClientProcess);
       
   312 
       
   313 // You will probably need to check the return value.
       
   314 // It may legitimately by non-KErrNone.
       
   315 
       
   316 ...
       
   317 
       
   318 // Delete the ‘name’ property.
       
   319 // Assumes that the owning process is iClientProcess. This will be checked
       
   320 // as being the valid owner of the property.
       
   321 r=name.Delete(iClientProcess);
       
   322 if (r != KErrNone)
       
   323     {
       
   324     // deal with a non-KErrNone return value.
       
   325     }
       
   326 
       
   327 // Delete the ‘counter’ property.
       
   328 // Assumes that the owning process is iClientProcess. This will be checked
       
   329 // as being the valid owner of the property.
       
   330 r=name.Delete(iClientProcess);
       
   331 if (r != KErrNone)
       
   332     {
       
   333     // deal with a non-KErrNone return value.
       
   334     }</codeblock> </section>
       
   335 <section id="GUID-EBAA6B5C-CC73-5AE2-85CA-68B445828608"><title>Publishing
       
   336 a property value </title> <p>A property is published (written), using the <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-D4B0220A-EB30-327C-B878-FBC5294A08F6"><apiname>RPropertyRef::Set()</apiname></xref> family
       
   337 of functions. </p> <p>This is guaranteed to have bounded execution time, suitable
       
   338 for high-priority, real-time tasks, except when publishing a byte-array property
       
   339 that requires the allocation of a larger space for the new value, or when
       
   340 publishing a large byte-array property type, as identified by <xref href="GUID-0B4D1D87-8C1B-3AEF-9C3D-3091FBDF3A6B.dita"><apiname>ELargeByteArray</apiname></xref>. </p> <p>Property
       
   341 values are written atomically. This means that it is not possible for threads
       
   342 reading a property to get a garbled value. </p> <p>All outstanding subscriptions
       
   343 for a property are completed when the value is published, even if it is exactly
       
   344 the same as the existing value. This means that a property can be used as
       
   345 a simple broadcast notification service. </p> <p>Publishing a property that
       
   346 is not defined is not necessarily a programming error. The <codeph>Set()</codeph> functions
       
   347 just return an error. If this is not expected for any particular usage, then
       
   348 the error must be checked and processed by the caller. </p> <p> <b>Security
       
   349 notes:</b>  </p> <ul>
       
   350 <li id="GUID-DA84723A-B9F7-525C-908A-BC51AA8B0366"><p>If you pass a pointer
       
   351 to a <codeph>DProcess</codeph> object, then the capabilities of that process
       
   352 will be checked against those contained in the write security policy that
       
   353 was created and passed to <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-47F367CB-E663-3F97-AC0C-31A9DD6BD5E5"><apiname>RPropertyRef::Define()</apiname></xref>. If you
       
   354 omit this <codeph>DProcess</codeph> parameter, a null pointer is assumed by
       
   355 default, and <i>the security check is bypassed</i>. This may be legitimate
       
   356 if you are doing this on behalf of the kernel or on behalf of the driver itself. </p> </li>
       
   357 </ul> <p>See the code fragment in the section <xref href="GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D.dita#GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D/GUID-CA858A2A-4BF0-565D-8A6D-58AE32FEE304">Retrieving
       
   358 a property value</xref>  </p> </section>
       
   359 <section id="GUID-CA858A2A-4BF0-565D-8A6D-58AE32FEE304"><title>Retrieving
       
   360 a property value </title> <p>The current value of a property is retrieved
       
   361 (read) using the <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-745E29E7-A26B-3207-ACA3-F8CC41FC7081"><apiname>RPropertyRef::Get()</apiname></xref> family of functions. </p> <p>This
       
   362 is guaranteed to have bounded execution time, suitable for high-priority,
       
   363 real-time tasks, except when retrieving a large byte-array property type,
       
   364 as identified by <xref href="GUID-0B4D1D87-8C1B-3AEF-9C3D-3091FBDF3A6B.dita"><apiname>ELargeByteArray</apiname></xref>. </p> <p>Property values
       
   365 are read atomically. This means that it is not possible for threads reading
       
   366 a property to get a garbled value. </p> <p>Retrieving a property that is not
       
   367 defined is not necessarily a programming error. The <codeph>Get()</codeph> functions
       
   368 just return an error. If this is not expected for any particular usage, then
       
   369 the error must be checked and processed by the caller. </p> <p>Integer properties
       
   370 must be accessed using the overload that takes an integer reference, whereas
       
   371 a byte-array property is accessed using the overload that takes a descriptor
       
   372 reference. </p> <p>The following code fragment shows publication and retrieval
       
   373 of a property. Note that it contains a race condition, especially if another
       
   374 thread is executing the same sequence to increment the ‘counter’ value. </p> <p> <b>Security
       
   375 notes:</b>  </p> <ul>
       
   376 <li id="GUID-B117308F-416E-5BAE-880C-A162869799AD"><p>If you pass a pointer
       
   377 to a <codeph>DProcess</codeph> object, then the capabilities of that process
       
   378 will be checked against those contained in the read security policy that was
       
   379 created and passed to <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-47F367CB-E663-3F97-AC0C-31A9DD6BD5E5"><apiname>RPropertyRef::Define()</apiname></xref>. If you omit
       
   380 this <codeph>DProcess</codeph> parameter, a null pointer is assumed by default,
       
   381 and <i>the security check is bypassed</i>. This may be legitimate if you are
       
   382 doing this on behalf of the kernel or on behalf of the driver itself. </p> </li>
       
   383 </ul> <codeblock id="GUID-75549D12-A2CA-5039-BB91-2ABF19058DE5" xml:space="preserve">const TUid KMyPropertyCat={0x10012345};
       
   384 enum TMyPropertyKeys={EMyPropertyCounter,EMyPropertyName};
       
   385 
       
   386 TInt r;
       
   387 
       
   388 RPropertyRef counter;
       
   389 RPropertyRef name;
       
   390 
       
   391 
       
   392 // Assume that the 'name' and 'counter' property references have
       
   393 // already been created. They may have been defined.
       
   394 //
       
   395 // Assume that the process to be used for security checking is iClientProcess.
       
   396 
       
   397 ...
       
   398 
       
   399 // publish a new name value. 
       
   400 _LIT8(KSomeExampleName,"My example name");
       
   401 r=name.Set(KSomeExampleName, iClientProcess);
       
   402 if (r != KErrNone)
       
   403     {
       
   404     // Check the return value. KErrNotFound means that the property has not yet been    
       
   405     // defined which may be legitimate.
       
   406     // KErrArgument is a serious problem at this stage.
       
   407     // KErrPermissionDenied is a security violation; the process iClientProcess has 
       
   408     // insufficient capability to do this operation. 
       
   409     }
       
   410 
       
   411 
       
   412 // Retrieve the first 10 characters of the name value.
       
   413 // We are not doing any security checking for this operation, so no DProcess pointer 
       
   414 // is passed to Get(). 
       
   415 TBuf&lt;10&gt; n;
       
   416 r=name.Get(n);
       
   417 
       
   418 if ((r!= KErrNone) &amp;&amp; (r != KErrOverflow))
       
   419     {
       
   420     // Handle error value.
       
   421     }
       
   422 
       
   423 // retrieve and publish a new value using the attached ‘counter’ property
       
   424 TInt count;
       
   425 r=counter.Get(count);
       
   426 if (r==KErrNone)
       
   427     {
       
   428     r=counter.Set(++count);
       
   429     }
       
   430 else
       
   431     {
       
   432     // Handle bad return value
       
   433     }
       
   434 ...
       
   435 
       
   436 // When finised, release the property references.
       
   437 counter.Close();
       
   438 name.Close();</codeblock> </section>
       
   439 <section id="GUID-984AB90D-FCCD-5383-B5D9-8D80AA83D989"><title>Subscribing
       
   440 to, and unsubscribing from, a property </title> <p>Subscribing to a property
       
   441 is the act of making an asynchronous request to be notified of a change to
       
   442 that property. </p> <p>You make a request for notification of a change to
       
   443 a property by calling the <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-6DC06192-78AF-3B3D-8077-8479789AF006"><apiname>RPropertyRef::Subscribe()</apiname></xref> member
       
   444 function on a property reference object. Only one subscription request can
       
   445 be outstanding at any time for a given <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita"><apiname>RPropertyRef</apiname></xref> instance. </p> <p>You
       
   446 can cancel an outstanding subscription request by calling <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-4AFB3074-E523-3404-8F0D-39995C35E045"><apiname>RPropertyRef::Cancel()</apiname></xref>.
       
   447 This is unsubscribing from the property. </p> <p>Subscribing to a property
       
   448 is a single request to be notified when the property is next updated, it does
       
   449 not generate an ongoing sequence of notifications for every change to that
       
   450 property's value. Neither does it provide the caller with the new value. In
       
   451 essence, the act of notification should be interpreted as “Property X has
       
   452 changed” rather than “Property X has changed to Y”. This means that the new
       
   453 value must be explicitly retrieved, if required. As a result, multiple updates
       
   454 may be collapsed into one notification, and subscribers may not have visibility
       
   455 of all intermediate values. </p> <p>This might appear to introduce a window
       
   456 of opportunity for a subscriber to be out of synchronisation with the property
       
   457 value – in particular, if the property is updated again before the subscriber
       
   458 thread has had the chance to process the original notification. However, a
       
   459 simple programming pattern, outlined in the second example below ensures this
       
   460 does not happen. The principle is that, before dealing with a subscription
       
   461 completion event, you should re-issue the subscription request. </p> <p>Note
       
   462 that if the property has not been defined, then a subscription request does
       
   463 not complete until the property is subsequently defined and published. Note
       
   464 that the request will complete with <xref href="GUID-213DE05E-24F7-3E94-9B35-F4A72B3EBFD8.dita"><apiname>KErrPermissionDenied</apiname></xref> if
       
   465 the subscribing process does not have sufficient capability as defined by
       
   466 the <xref href="GUID-81A285F6-3F87-3E77-9426-61BB16BC7109.dita"><apiname>TSecurityPolicy</apiname></xref> object supplied by the process defining
       
   467 the property. </p> <p>If the property is already defined, then the request
       
   468 completes immediately with <xref href="GUID-213DE05E-24F7-3E94-9B35-F4A72B3EBFD8.dita"><apiname>KErrPermissionDenied</apiname></xref> if the
       
   469 subscribing process does not have sufficient capability. </p> <p>The essence
       
   470 of subscribing to a property is that you pass a function into <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-6DC06192-78AF-3B3D-8077-8479789AF006"><apiname>RPropertyRef::Subscribe()</apiname></xref> and
       
   471 that this function is called when the property value is published. You pass
       
   472 the function by wrapping it in <xref href="GUID-8A0F75CD-DC61-37EA-A23A-3A82080F0751.dita"><apiname>TPropertySubsRequest</apiname></xref> object
       
   473 and then pass this into <codeph>Subscribe()</codeph>. What the function does
       
   474 depends on the implementation, but you may want to re-subscribe to the property
       
   475 and then retrieve the property value, or you may want to set some flag. It
       
   476 all depends on the intent of the property and the driver code. </p> <p>The
       
   477 following code fragments show the general idea. </p> <codeblock id="GUID-DF8201DF-7812-5B39-8B0F-3CB664BA00FA" xml:space="preserve">const TUid KMyPropertyCat={0x10012345};
       
   478 enum TMyPropertyKeys={EMyPropertyCounter,EMyPropertyName};</codeblock> <codeblock id="GUID-2162EE7C-B834-50ED-9C84-3CE004C0B7D6" xml:space="preserve">class DMyLogicalChannel : public DLogicalChannel
       
   479     {
       
   480     public :
       
   481         DMyLogicalChannel();
       
   482         void OpenReference();
       
   483         void SetUpSubscription();
       
   484         ...
       
   485     private :
       
   486         static void HandleSubsComplete(TAny* aPtr, TInt aReason);
       
   487         ...
       
   488     private:
       
   489         RCounterRef iName;
       
   490         TBuf&lt;10&gt;    iNameValue;
       
   491         DProcess    iClientProcess;
       
   492         TPropertySubsRequest iSubsRequest;
       
   493         TInt iReason;
       
   494     }</codeblock> <codeblock id="GUID-4A655D83-07CD-5998-A540-16D4A5EABFC5" xml:space="preserve">DMyLogicalChannel::DMyLogicalChannel() : iSubsRequest(&amp;HandleSubsComplete, this)
       
   495     {
       
   496     iClientProcess = &amp;Kern::CurrentProcess();
       
   497     // Other code omitted 
       
   498     }</codeblock> <codeblock id="GUID-DB6F4AF7-8866-50C5-95FD-5BCA1F2B55CE" xml:space="preserve">void DMyLogicalChannel::OpenReference()
       
   499     {
       
   500     // Open a reference to the ‘name’ property, and assume that
       
   501     // the property has already been created and defined.
       
   502   
       
   503     TInt r
       
   504     ...
       
   505     r=iName.Open(KMyPropertyCat,EMyPropertyName);
       
   506     if (r != KErrNone)
       
   507         {
       
   508         // Handle bad return value.
       
   509         }
       
   510     ...
       
   511     }</codeblock> <codeblock id="GUID-217CFAF4-2CA6-588B-B3A2-667EB9A04FCA" xml:space="preserve">void DMyLogicalChannel::SetUpSubscription()
       
   512     {
       
   513     // Now ask to be notified when the 'name' property is updated.
       
   514     // This will eventually result in a call to the function HandleSubsComplete()
       
   515     // at some later time (asynchronously).
       
   516     // When eventually called, the pointer to this DMyLogicalChannel object will
       
   517     // be passed to HandleSubsComplete().
       
   518     //
       
   519     ...
       
   520     iReason = KRequestPending;
       
   521     TInt r = iName.Subscribe(iSubsRequest); // ignoring security issues here.
       
   522     if (r != KErrNone)
       
   523         {
       
   524         // handle bad return code.
       
   525         }
       
   526     return;
       
   527     }</codeblock> <codeblock id="GUID-C2CD229F-F6CE-5EE3-9EBA-A69CED50FA07" xml:space="preserve">void DMyLogicalChannel::CancelSubscription()
       
   528     {
       
   529     if (iReason == KRequestPending)
       
   530         {
       
   531         iName.Cancel(iSubsRequest);
       
   532         }
       
   533     }</codeblock> <codeblock id="GUID-D5E046B5-4D56-5B82-B4B8-D943DC601338" xml:space="preserve">void DMyLogicaChannel::SubsCompleteFn(TAny* aPtr, TInt aReason)
       
   534     {
       
   535     // A static function called when a change to the property occurs.
       
   536     // aPtr will point to the DMyLogicalChannel object 
       
   537     // (see the DMyLogicalChannel constructor)
       
   538     // aReason is the reason for the subscription completing. This may be:
       
   539     //     KErrNone - for a normal completion.
       
   540     //     KErrPermissionDenied - if the security check has failed.
       
   541     //     KErrCancel - if the request was cancelled.
       
   542     // For a normal completion, setup another notification request before
       
   543     // getting the current value of the property.
       
   544     //
       
   545     DMyLogicaChannel* self = (DMyLogicaChannel*) aPtr;
       
   546        self-&gt;iReason = aReason;
       
   547     if (iReason == KErrNone)
       
   548         {
       
   549         self-&gt;SetUpSubscription();
       
   550         self-&gt;Get(iNameValue,iClientProcess);
       
   551         return;
       
   552         }
       
   553     // Investigate the non-zero reason code.
       
   554     }</codeblock> </section>
       
   555 <section id="GUID-21D8ADCA-9B39-5079-B4AD-FEBFCCB92049"><title>Usage patterns</title> <p>There
       
   556 are three usage patterns that can easily be identified, labelled as: standard
       
   557 state, pure event distribution, and speculative publishing. </p> <p id="GUID-98103A8A-10E1-58FE-9613-A616E142AA2A"><b>Standard state</b> </p> <p>This
       
   558 pattern is used for events and state that are known to be used widely in the
       
   559 system. Examples of this might be battery level and signal strength, which
       
   560 are important in every phone. </p> <p>The publisher calls <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-47F367CB-E663-3F97-AC0C-31A9DD6BD5E5"><apiname>RPropertyRef::Define()</apiname></xref> to
       
   561 create the appropriate property. For byte array or text properties, a size
       
   562 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
       
   563 be ignored. The publisher then publishes the property values as, and when,
       
   564 appropriate. If the <codeph>RPropertyRef::Set()</codeph> call fails, this
       
   565 should be treated as a serious error, since it indicates that important system
       
   566 state is not getting through. Appropriate action might include panicking or
       
   567 rebooting the system. Subscribers will use <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-6DC06192-78AF-3B3D-8077-8479789AF006"><apiname>RPropertyRef::Subscribe()</apiname></xref> to
       
   568 request notification, and <codeph>RPropertyRef::Get()</codeph> to retrieve
       
   569 the property value on notification. </p> <p>The memory to store the property
       
   570 value will be permanently allocated, even if it turns out that no-one in the
       
   571 system needs that value. This does ensure that the value can always be published,
       
   572 even if the system is in an out of memory situation. For this reason, this
       
   573 approach should be limited to widely used and important state. The <xref href="GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D.dita#GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D/GUID-8D9E6222-DDBA-55CA-A96F-1DCBD99E3FD3">Speculative publishing</xref> pattern offers an approach for dealing with
       
   574 less important state. </p> <p id="GUID-5C82A92C-168D-5CD2-BE43-EE79AB500B14"><b>Pure event distribution</b> </p> <p>This
       
   575 pattern is used when events need to be distributed, not values. </p> <p>The
       
   576 publisher of the event simply uses an integer property, and calls <codeph>RPropertyRef::Set()</codeph> with
       
   577 any value. Even if the value of the property is not changed by this operation,
       
   578 all subscribers will be notified that a <codeph>Set()</codeph> has occurred,
       
   579 and by implication that the related event has occurred. </p> <p>Subscribers
       
   580 will be able to detect that an event has occurred, but will get no other information.
       
   581 The minimum possible memory is wasted on storage for the dummy value. </p> <p id="GUID-8D9E6222-DDBA-55CA-A96F-1DCBD99E3FD3"><b>Speculative publishing</b> </p> <p>This
       
   582 pattern is used when it is not known whether a value will be of interest to
       
   583 others or not. Unlike the <xref href="GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D.dita#GUID-EBFD653D-6E6A-5F6F-88D7-8CCE07B4002D/GUID-98103A8A-10E1-58FE-9613-A616E142AA2A">standard
       
   584 state</xref> pattern, the publisher of the event does not call <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-47F367CB-E663-3F97-AC0C-31A9DD6BD5E5"><apiname>RPropertyRef::Define()</apiname></xref> to
       
   585 create the property. Instead, it simply calls <codeph>RPropertyRef::Set()</codeph> as
       
   586 appropriate, and ignores any <xref href="GUID-5E653C17-372C-32E1-A1B2-9E69A9991C40.dita"><apiname>KErrNotFound</apiname></xref> error. </p> <p>When
       
   587 other code in the system, i.e. a potential subscriber, is interested in the
       
   588 state, it calls <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-47F367CB-E663-3F97-AC0C-31A9DD6BD5E5"><apiname>RPropertyRef::Define()</apiname></xref> to create the property
       
   589 and allocate the memory for the value. An error of <xref href="GUID-D1D25122-F2B8-3C78-8599-84905BFD47B8.dita"><apiname>KErrAlreadyExists</apiname></xref> should
       
   590 be ignored, as this only indicates that some other code in the system is also
       
   591 interested in the value and has already created the property. </p> <p>The
       
   592 subscriber then calls <xref href="GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2.dita#GUID-39D6B924-3FA3-39E6-A6EA-88E2D1927AC2/GUID-6DC06192-78AF-3B3D-8077-8479789AF006"><apiname>RPropertyRef::Subscribe()</apiname></xref> and <codeph>RPropertyRef::Get()</codeph> as
       
   593 usual to interact with the property. On the first <codeph>Get()</codeph>,
       
   594 the subscriber may retrieve the property default value (zero, or a zero length
       
   595 descriptor). This must be substituted with a sensible default value for the
       
   596 property in question. </p> <p>Using this pattern, no memory is wasted on properties
       
   597 that have no subscribers, while the publisher code is simpler as there is
       
   598 no need for configuration as to which properties to publish. </p> <p>The publisher,
       
   599 however, wastes some time attempting to publish unneeded values, but this
       
   600 should not be an issue unless the value is very frequently updated. </p> <p>Where
       
   601 events are published very infrequently, the subscriber could have a dummy
       
   602 value for a long time, until the next publish event updates the value. Often
       
   603 this is not a problem as a default value can be substituted. For example a
       
   604 full/empty indicator for a battery level, none for signal strength etc. This
       
   605 pattern is unlikely to be useful if there is no suitable default value. </p> </section>
       
   606 </conbody></concept>