Symbian OS Explained - Effective C++ Programming For Smartphones (2005) (779885), страница 28
Текст из файла (страница 28)
Here’show a client of class CExampleTimer can expect to use the active object,which it stores as a member variable called iExampleTimer, illustratingthe transparency of active object classes from a client’s perspective:// Class CClient has a member variable CExampleTimer* iExampleTimervoid CClient::StartRepeatingTimerL(){iExampleTimer = CExampleTimer::NewL();APPLICATION CODE AND ACTIVE OBJECTS123iExampleTimer->After(1000000);}void CClient::StopRepeatingTimer(){iExampleTimer->Cancel();delete iExampleTimer;iExampleTimer = NULL; // Prevents re-use or double deletion}8.5 Threads Without an Active SchedulerMost threads running on Symbian OS have an active scheduler, whichis usually created implicitly by a framework (e.g.
CONE for the GUIframework). However, if you are implementing a server, you have tocreate and start an active scheduler explicitly before you can use activeobjects. Likewise, console-based test code may not use active objectsdirectly itself, but must create an active scheduler in its main thread if itdepends on components which do use active objects.There are a few threads in Symbian OS which intentionally do not havean active scheduler and thus cannot use active objects or componentsthat use them:• The Java implementation does not support an active scheduler andnative Java methods may not use active objects.
It is permissible tomake calls in code to C++ servers which do use them, since these runin a separate thread which has a supporting active scheduler.• The C Standard Library, STDLIB, thread has no active schedulerand thus standard library code cannot use active objects. Functionsprovided by the Standard Library may however be used in activeobject code, for example in an initialization or a RunL() method.The functions should be synchronous and return quickly, as requiredby all active object implementations.• OPL does not provide an active scheduler and C++ extensions toOPL (OPXs) must not use active objects or any component whichuses them.8.6 Application Code and Active ObjectsThe active object model is very easy to use without needing a full understanding of how it works.
In this chapter, I’ve described how to handleevents resulting from the completion of asynchronous functions on Symbian OS. This involves defining CActive-derived classes, and providing124EVENT-DRIVEN MULTITASKING USING ACTIVE OBJECTSthe event handler and additional code for construction, destruction,error-handling and cancellation. However, application code requiressome understanding of active objects and requires implementation ofactive object code that is incidental to the purpose of the application. Inaddition, many other operating systems do not encapsulate event handling in the same way. This means that Symbian OS code is not directlyportable to other operating systems.For this reason, Symbian OS provides frameworks to hide active objectcode from high-level application code by defining handler interfaces(often mixin classes as described in Chapter 1) which a client implements.The frameworks hide the active objects, implementing initialization,cleanup and error handling, and performing generic event processing inthe RunL() method.
In RunL() the framework calls methods on theclient-implemented interface to respond to the completed event. Theappropriate client object receives the call, having ”registered” with theframework by passing a reference or pointer to its implementation ofthe interface. The one rule the client should be aware of is that theinterface methods should be implemented to complete quickly so thatthe framework can handle other events without delay.An example of this may be seen when application code runs withinthe GUI framework (CONE), which uses active objects to handle eventsassociated with user input and system requests such as window redrawrequests, originating from the window server. The framework implementsthe RunL() method to process each event, and calls an appropriate virtualfunction such as OfferKeyEventL() or HandlePointerEventL()in the associated control.
As an application programmer, all you have todo is implement the functions defined by the framework and it takes careof the mechanics of event handling.Likewise, server code runs inside the Symbian OS system serverframework and handles requests from client messages. Server codeoften implements its own additional set of internal active objects, tomake requests to asynchronous service providers while still remainingresponsive to incoming client requests. The client–server architecture isdiscussed in detail in Chapters 11 and 12.8.7 SummarySymbian OS makes it very easy to write event-driven code without gettingtoo involved in the implementation of the active objects which handlethe events.
This chapter set out to explain the basics of how activeobjects work, why you should prefer them to threads for multitasking andhow to implement a basic active object class. If you are likely to writeserver code, implement an asynchronous service provider or performmore advanced GUI programming, you will probably be interested in theSUMMARY125next chapter, which goes deeper into the responsibilities and roles of themain components – active objects, asynchronous service providers andthe active scheduler.This chapter explained that:• Active objects were designed for lightweight, responsive, powerefficient event-handling and are used by most applications and servers,generally in a single thread.• Active objects are scheduled cooperatively in a single thread and,in consequence, are easy to program because there is no needto use synchronization primitives to prevent concurrent access toshared resources.• The kernel schedules threads pre-emptively but these are not generallyused for event-driven multitasking.• The active object framework on Symbian OS has a modular designthat decouples event completion processing, performed by the activescheduler, from individual event handling, performed by activeobjects.• The constructor of the active object class should set its priorityand add it to the active scheduler.
Any initialization required by theasynchronous service provider should be performed in a second-phaseconstructor.• Active objects encapsulate an asynchronous service provider and theevent handling necessary when a request to that service providercompletes.• Active objects provide request initiation functions. These usuallyconform to a pattern: performing a check for no previous outstandingrequests, submitting the request with its iStatus member variableas a parameter, and setting the state of the active object to indicatethat a request has been issued.• Event handling is performed by implementing the pure virtual RunL()method defined in the CActive base class; RunL() is called by theactive scheduler some time after the request completes.• Because active objects cannot pre-empt each other, RunL() shouldcomplete as quickly as possible so that other active object events canbe handled without delay.• The pure virtual DoCancel() method must also be implementedby deriving classes and should call an appropriate method on theasynchronous service provider to cancel the request.126EVENT-DRIVEN MULTITASKING USING ACTIVE OBJECTS• The default ”do nothing” implementation of the virtual RunError()method on the base class should be overridden if the derived class canreasonably handle leaves which occur within its RunL() function.• Symbian OS uses framework code to conceal the active object idiom.For example, the GUI framework dispatches incoming events to behandled by functions implemented by an associated control, whichmay be extended by individual applications as required.The next chapter looks ”under the hood” at active objects, discussesthe responsibilities of active objects, asynchronous service providersand the active scheduler, and illustrates best practice when writing andusing active objects.
Chapter 10 has more information about Symbian OSthreads and processes, while Chapters 11 and 12 build on an understanding of active objects, threads and processes, to describe the Symbian OSclient–server architecture in detail.9Active Objects under the HoodDo not hack me as you did my Lord RussellThe last words of the Duke of Monmouth (1649–1685) addressed to hisexecutionerThe previous chapter introduced active objects and described the basics,such as how to use them, how to derive a simple active object classand why active objects are used by Symbian OS as a lightweight alternative to threads for event-driven multitasking. This chapter considersactive objects in more detail and discusses some commonly used activeobject idioms.First of all, let’s examine in detail the responsibilities of active objects,asynchronous service providers and the active scheduler and walkthrough how they fit together.
The previous chapter made the followingmain points:• Symbian OS event-handling is usually managed in one thread, whichruns a single active scheduler• the active scheduler holds a set of active objects for that thread, eachof which encapsulates an associated asynchronous service provider• each thread has an associated request semaphore; when an asynchronous function completes, it generates an event by callingRequestComplete() on the requesting thread, which signals itssemaphore and is detected by the active scheduler• the active scheduler calls the RunL() event handler method of theactive object associated with the completion event.In the previous chapter, I used example code for an active objectwrapper over an RTimer to illustrate the main points.
You may find ituseful to refer to that example throughout this chapter.128ACTIVE OBJECTS UNDER THE HOOD9.1 Active Object BasicsAll active objects must derive from class CActive. On construction,each active object is assigned a priority value, which is set through acall to the base class constructor. In its constructor, the active objectmust also be added to the active scheduler through a call to CActiveScheduler::Add().
The active scheduler maintains a doubly-linkedlist of the active objects added to it, ordered by priority. When an activeobject is added to the active scheduler, it is added to that list in theappropriate position, according to its priority value.As I described in Chapter 8, the active object encapsulates asynchronous functions (those that return immediately and complete at somelater stage rather than returning only when the request has completed).On Symbian OS, asynchronous functions can be identified as those takinga TRequestStatus reference parameter into which the request completion status is posted.