Issott_Common Design Patterns for Symbian OS-The Foundations of Smartphone Software_0470516356 (779879), страница 24
Текст из файла (страница 24)
In addition, because writing a value into such a propertytriggers a notification to all subscribers, this is known as publishing.StructureDefining a PropertyA property can be defined by either an event generator or an eventconsumer (see Figure 4.5) depending on their relative lifetimes. A uniquecombination of a category UID and an integer key must be used to identifythe property across the system. In addition, the type of the property (suchas whether the property value is an integer, Unicode text, a byte array,etc.) must also be set. Once defined, the property value can change, butthe property type cannot.18 Once defined, a property persists in the kerneluntil the system reboots or the property is explicitly deleted. Its lifetime isnot tied to that of the thread or process that originally defined it.RHandleBaseActs as a handleto a propertyvalue held in thekernelRPropertyEventGeneratorPublishes++++++Attach()Define()Delete()Get()Set()Subscribe()Subscribes toEventConsumerFigure 4.5 Structure of the Publish and Subscribe patternThe RProperty API allows byte-array and Unicode text type properties to be pre-allocated when they are defined.
This means that thetime taken to Set() these values is bounded. However, if the length ofthese property types subsequently increases, then memory allocation may18For some property types, the value can change length provided it does not exceed themaximum value of 512 bytes. This puts a limit on the RAM usage in the kernel due toproperties.PUBLISH AND SUBSCRIBE117take place and no guarantees are made about the time taken to Set()them.When a property is defined you have the opportunity to define thepolicy for the security checks made when it is either written to, byevent generators, or read from, by event consumers.
By using theLIT SECURITY POLICY macros you can specify the Platform Security capabilities, Secure ID or Vendor ID that a process needs to have tosucceed either when writing to or reading from the property.However, there is still a potential risk that some malicious process runsand defines the property with no security policy before you get a chance todefine the property correctly yourself. If this is a problem, you should usethe special category KUidSystemCategory. This works by checkingthat the process defining such a property has the WriteDeviceDataPlatform Security capability. If the secure definition of a property isn’ta worry then you should just use the Secure ID of your process as thecategory for the property since you know this is unique across the device.Note that a process that defines a property does not have automaticrights of access to that property, other than to delete it.
If the definingprocess also wishes to publish or subscribe to that property, then it mustensure that it satisfies the security policies that it has put in place whendefining the property.For more information on Platform Security, see [Heath, 2006].Deleting a PropertyOnly the process that created a property is allowed to delete it.
When youdelete a property, any pending subscriptions for it are completed withKErrNotFound and any new subscription will not complete until theproperty is defined and published again. Any Get() or Set() attemptson a deleted property fail with KErrNotFound.DynamicsOnce a property has been defined it can be used in earnest.SubscribingAn event consumer can subscribe to a property to request notificationof changes in a property’s value (see Figure 4.6). This is achieved by thesubscriber carrying out the following steps:1. Create an RProperty object.2. Attach the RProperty object to a specific property identified by itscategory and key.3.
Call Subscribe() on the RProperty object, passing in a TRequestStatus& in the standard manner for an asynchronous service118EVENT-DRIVEN PROGRAMMINGPublisher threadSubscriber threadSubscriberPublisherKernelpublisherProperty:RPropertyDefine()AllocateStorageForNewProperty()Define()Set()Set()SetPropertyValue()subscriberProperty:RPropertyAttach()Attach()Subscribe()Get()Figure 4.6Subscribe()Get()Attach()SubscribeToValue()At this point,subscriberProperty isassociated with the sameproperty as publisherProperty.This is the crucial stage fromthe viewpoint of event-drivenprogramming: the subscriberregisters as an eventconsumer, the event being achange in the value of theproperty.GetPropertyValue()Dynamics of the Publish and Subscribe pattern (registering a subscriber)function19 to register for notification of the next change to theproperty.4.To actually obtain the current value, you should call one of the Get()overloads depending on the type of the property.
This operation isatomic, which means that it is not possible for your thread to geta garbled value as a result of another thread writing a value partway through your read. Also, since you have already attached to theproperty, a Get() is guaranteed to have bounded execution time,suitable for high-priority, real-time tasks.Note that by calling Subscribe() before Get() there is noopportunity for your component to fail to notice that a new valuehas been published.
In such a situation, when your component callsSubscribe() and waits for it to complete, it’ll find that it completes19 SeeRequest Completion (on page 104).PUBLISH AND SUBSCRIBE119immediately and Get() is called straight away to obtain the newvalue.5. When the property value next changes, the TRequestStatuspassed into the earlier Subscribe() call is completed.206. Go to (3) to subscribe for the next change.PublishingAn event generator can publish a property by doing the following (seeFigure 4.7):1.
Create an RProperty object.2. Optionally attach the RProperty object to a specific propertyidentified by its category and key. This is only needed if you wishSubscriber threadPublisher threadPublisherpublisherProperty:RPropertySubscriberSet()subscriberProperty:RPropertyKemelSet()SetPropertyValue()NotifySubscribers()RequestCompletion()Subscribe()Subscribe()Completes theTRequestStatuspassed to an earlierSubscribe() callGet()Get()Figure 4.7SubscribeToValue()GetPropertyValue()Dynamics of the Publish and Subscribe pattern (publishing a new value)20 If the event consumer doesn’t have sufficient privileges to read the property, the requestis completed immediately with KErrPermissionDenied.120EVENT-DRIVEN PROGRAMMINGthe subsequent Set() operation to be guaranteed to have boundedexecution time,21 suitable for high-priority, real-time tasks.3.Publish the new value by calling one of the Set() overloadsdepending on the type of the property.22 An event signal is thensent to all event consumers subscribing to the property.Once the property has been finished with and is no longer needed, itshould be deleted by the process that created it, to free up the RAM ituses in the kernel.ImplementationShared DefinitionsThis pattern works by the event generators and event consumers accessing the same underlying property in the kernel.
As such there are sometypes that need to be shared between them. At the least, this includesthe category and key of the property along with some indication of thePlatform Security capabilities required to read from it or write to it.The following code is usually defined in its own header file that isshared between the event consumer and event generator.// Some description should be given here about how this category is usedconst TUid KSharedPropertyCategory = {KProcessSid};// Some description should be given for each of these enums about how// the key is used, in particular the type of the property valueenum TSharedPropertyKey{ESharedPropertyKey1,ESharedPropertyKey2,...};// Example showing how to set a security policy to allow anyone to read_LIT_SECURITY_POLICY_PASS(KSharedPropertyReadPolicy);// Example showing how to set a security policy allowing only the// process that defines the property to write to it_LIT_SECURITY_POLICY_S0(KSharedPropertyWritePolicy,KSharedPropertyCategory.iUid);If the property value’s meaning is non-trivial to interpret, you shouldalso provide some means to decode the contents to avoid misinterpretation.
For example, if the property is an eight-bit descriptor type containing21 It is not guaranteed when publishing a variable-length property that requires theallocation of a larger space for the new value.22 This operation is atomic, which means that it is not possible for your thread to write agarbled value as a result of another thread attempting to write at the same time.PUBLISH AND SUBSCRIBE121a packaged class TExample, a predefined TPckgBuf typedef caneasily be provided as follows;typedef TPckgBuf<TPropertyValue> TPropertyValuePckg;Using this kind of typedef to both encode and decode the TExample ensures consistent usage of the value for both the publisher andsubscriber.Event GeneratorA common practice is to encapsulate the publishing of the new propertyvalue within an R class.23 An R class is used because this class doesn’town any data and just contains references.