Symbian OS Explained - Effective C++ Programming For Smartphones (2005) (779885), страница 26
Текст из файла (страница 26)
This signal is known as an event, and the112EVENT-DRIVEN MULTITASKING USING ACTIVE OBJECTScode can be said to be event-driven. Symbian OS, like other operatingsystems, uses event-driven code extensively both at a high level, e.g.for user interaction, and at a lower, system level, e.g. for asynchronouscommunications input and output.Before considering active objects further, let’s consider how codeactually ”runs”. A thread is a fundamental unit of execution, which runswithin a process. A process has its own address space and may have oneor more threads independently executing code within it. When a processis created, a single primary thread is initialized within it.
Other threadsmay then be created, as described in Chapter 10. Code executing in thatprocess accesses virtual memory addresses which are mapped for thatprocess to physical locations in hardware by the memory managementunit. The writable memory of one process is not normally accessible toanother process, thus ”protecting” processes from each other. However,multiple threads running in the same process are not isolated from eachother in the same way because they share the memory mapped for the process in which they run. This means that they can access each other’s data,which is useful, but they can also accidentally scribble on it, which is not.On Symbian OS, threads are scheduled pre-emptively by the kernel,which runs the highest priority thread eligible.
Each thread may besuspended while waiting for a given event to occur and may resumewhenever appropriate. The kernel controls thread scheduling, allowingthe threads to share the system resources by time-slice division, preempting the running of a thread if another, higher priority thread becomeseligible to run. This constant switching of the running thread is the basis ofpre-emptive multitasking, which allows multiple servers and applicationsto run simultaneously. A context switch occurs when the currentlyrunning thread is suspended (for example, if it is blocked, has reachedthe end of its time-slice, or a higher priority thread becomes ready torun) and another thread is made current by the scheduler.
The contextswitch incurs a runtime overhead in terms of the kernel scheduler and,potentially, the memory management unit and hardware caches, if theoriginal and replacing threads are executing in different processes.8.2 Event-Driven MultitaskingMoving up a level, let’s look at some typical examples of events andevent-driven multitasking. Events can come from external sources, suchas user input or hardware peripherals that receive incoming data.
Theycan also be generated by software, for example by timers or completedasynchronous requests. Events are managed by an event handler, which,as its name suggests, waits for an event and then handles it.An example of an event handler is a web browser application, whichwaits for user input and responds by submitting requests to receive webEVENT-DRIVEN MULTITASKING113pages which it then displays. The web browser may use a system server,which waits to receive requests from its clients, services them and returnsto waiting for another request.
The system server submits requests, e.g.I/O requests, to other servers, which later generate completion events.Each of the software components described is event-driven. They needto be responsive to user input and responsive to requests from the system(for example, from the communications infrastructure).In response to an event, the event handler may request anotherservice. This service will later cause another event, or may indicate thatthe service has completed, which may cause another event in a differentpart of the system. The operating system must have an efficient eventhandling model to handle each event as soon as possible after it occursand, if more than one event occurs, in the most appropriate order.
It isparticularly important that user-driven events are handled rapidly to givefeedback and a good user experience. Between events, the system shouldwait in a low power state. This avoids polling constantly, which can leadto significant power drain and should be avoided on a battery-powereddevice.
Instead the software should allow the operating system to moveto an idle mode, while it waits for the next event.On hardware running Symbian OS, resources are more limited thanon a typical desktop PC. Thus, on Symbian OS, besides the requirementsto be responsive and handle power consumption carefully, it is alsoimportant that the memory used by event-handling code is minimizedand that processor resources are used efficiently. Active objects assist withefficient programming by providing a model for lightweight, event-drivenmultitasking.Active objects encapsulate the traditional wait loop inside a class.They were designed such that a switch between active objects that run inthe same thread incurs a lower overhead than a thread context switch.1This makes active objects preferable for event-driven multitasking onSymbian OS.Apart from the runtime expense of a context switch, using pre-emptivemultithreading for event handling can be inconvenient because of theneed to protect shared objects with synchronization primitives suchas mutexes or semaphores.
Additionally, resource ownership is threadrelative by default on Symbian OS. If a file is opened by the mainthread it will not be possible for a different thread in the process touse it without the handle being explicitly shared through a call toRSessionBase::Share() (and some Symbian OS servers do notsupport session sharing at all). Because of this restriction, it may be1The difference in speed between a context switch between threads and transfer ofcontrol between active objects in the same thread can be of a factor of 10 in favor of activeobjects. In addition, the space overhead for a thread can be around 4 KB kernel-side and8 KB user-side for the program stack, while the size of an active object may be only a fewhundred bytes, or less.114EVENT-DRIVEN MULTITASKING USING ACTIVE OBJECTSvery difficult to use multiple threads as a viable method for event-drivenmultitasking.
More detail on threads can be found in Chapter 10, whilethe client–server model is discussed in Chapters 11 and 12.On Symbian OS, active objects multitask cooperatively and, consequently, there is no need for synchronization protection of sharedresources. In addition, because active objects run in the same thread,memory and objects may be shared more readily. Active objects still runindependently of each other, despite existing in the same thread, in muchthe same way as threads are independent of each other in a process.On Symbian OS, the use of active objects for event-handling multitasking is ideal because they are designed for efficiency and, if used correctly,to be responsive. In general, a Symbian OS application or server willconsist of a single main event-handling thread.
A set of active objectsrun in the thread, each representing a task. Each active object requestsan asynchronous service, waits while it is serviced, handles the requestcompletion event and communicates with other tasks as necessary.Some events require a response within a guaranteed time, regardless ofany other activity in the system. This is called ”real-time” event-handling.For example, a real-time task may be required to keep the buffer of asound driver supplied with sound data – a delay in response delays thesound decoding, which results in it breaking up. Other typical real-timerequirements may be even more strict, say for low-level telephony. Thesetasks have, in effect, different requirements for real-time responses, whichcan be represented by task priorities.
Higher-priority tasks must alwaysbe able to pre-empt lower-priority tasks in order to guarantee to meettheir real-time requirements. The shorter the response time required, thehigher the priority that should be assigned to a task.However, once an active object is handling an event, it may notbe pre-empted by the event handler of another active object2 , whichmeans that they are not suitable for real-time tasks. On Symbian OS,real-time tasks should be implemented using high-priority threads andprocesses, with the priorities chosen as appropriate for relative real-timerequirements.Active objects are used on Symbian OS to simplify asynchronousprogramming and make it easy for you to write code to submit asynchronous requests, manage their completion events and process theresult.
They are well suited for lightweight event-driven programming, except where a real-time, guaranteed response is required.2Note that, although the active objects within a thread run cooperatively withoutpre-emption, on Symbian OS the thread in which they run is scheduled pre-emptively.WORKING WITH ACTIVE OBJECTS1158.3 Working with Active ObjectsLet’s move on now to consider in more detail how active objects work, andhow to use them. A typical Symbian OS application or server consists of asingle event-handling thread running a scheduler (the ”active scheduler”)which coordinates one or more active objects.
Each active object requestsan asynchronous service and handles the resulting completion event sometime after the request. It also provides a way to cancel an outstandingrequest and may provide error handling for exceptional conditions.An active object class must derive from class CActive, which isdefined in e32base.h (shown here with only the relevant methods, forclarity). The next chapter discusses details of the base class further.class CActive : public CBase{public:enum TPriority{EPriorityIdle=-100,EPriorityLow=-20,EPriorityStandard=0,EPriorityUserInput=10,EPriorityHigh=20,};public:IMPORT_C ∼CActive();IMPORT_C void Cancel();...IMPORT_C void SetPriority(TInt aPriority);inline TBool IsActive() const;...protected:IMPORT_C CActive(TInt aPriority);IMPORT_C void SetActive();virtual void DoCancel() =0;virtual void RunL() =0;IMPORT_C virtual TInt RunError(TInt aError);public:TRequestStatus iStatus;...};ConstructionLike threads, active objects have a priority value to determine how theyare scheduled.
Classes deriving from CActive must call the protectedconstructor of the base class, passing in a parameter to set the priority ofthe active object.When the asynchronous service associated with the active objectcompletes, it generates an event. The active scheduler detects events,determines which active object is associated with each event, and calls116EVENT-DRIVEN MULTITASKING USING ACTIVE OBJECTSthe appropriate active object to handle the event. I’ll describe this inmore detail in the later section on event handling. While an active objectis handling an event, it cannot be pre-empted3 until the event handlerfunction has returned back to the active scheduler.It is quite possible that a number of events may complete before controlreturns to the scheduler. The scheduler must resolve which active objectgets to run next; it does this by ordering the active objects using theirpriority values.