Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Symbian OS Explained - Effective C++ Programming For Smartphones (2005) [eng].pdf
Скачиваний:
60
Добавлен:
16.08.2013
Размер:
2.62 Mб
Скачать

8

Event-Driven Multitasking Using Active

Objects

Light is the task where many share the toil

Homer

Active objects are a fundamental part of Symbian OS. This chapter explains why they are so important, and how they are designed for responsive and efficient event handling. Active objects are intended to make life easy for application programmers, and this chapter alone gives you sufficient knowledge to work with them within an application framework or derive your own simple active object class. Chapter 9 will be of interest if you want to write or work with more complex active objects: it discusses the responsibilities of active objects, asynchronous service providers and the active scheduler in detail, and reviews the best strategies for long-running or low-priority tasks. System-level programmers wishing to understand the Symbian OS client–server architecture and lower-level system design should read both this chapter and the following one.

8.1 Multitasking Basics

First of all, what are active objects for? Well, let’s go back to basics. Consider what happens when program code makes a function call to request a service. The service can be performed either synchronously or asynchronously. When a synchronous function is called, it performs a service to completion and returns directly to its caller, usually returning an indication of its success or failure (or leaving, as discussed in Chapter 2). An asynchronous function submits a request as part of the function call and returns to its caller – but completion of that request occurs some time later. Before the request completes, the caller may perform other processing or it may simply wait, which is often referred to as ”blocking”. Upon completion, the caller receives a signal which indicates the success or failure of the request. This signal is known as an event, and the

112

EVENT-DRIVEN MULTITASKING USING ACTIVE OBJECTS

code can be said to be event-driven. Symbian OS, like other operating systems, uses event-driven code extensively both at a high level, e.g. for user interaction, and at a lower, system level, e.g. for asynchronous communications input and output.

Before considering active objects further, let’s consider how code actually ”runs”. A thread is a fundamental unit of execution, which runs within a process. A process has its own address space and may have one or more threads independently executing code within it. When a process is created, a single primary thread is initialized within it. Other threads may then be created, as described in Chapter 10. Code executing in that process accesses virtual memory addresses which are mapped for that process to physical locations in hardware by the memory management unit. The writable memory of one process is not normally accessible to another process, thus ”protecting” processes from each other. However, multiple threads running in the same process are not isolated from each other 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 be suspended while waiting for a given event to occur and may resume whenever appropriate. The kernel controls thread scheduling, allowing the threads to share the system resources by time-slice division, preempting the running of a thread if another, higher priority thread becomes eligible to run. This constant switching of the running thread is the basis of pre-emptive multitasking, which allows multiple servers and applications to run simultaneously. A context switch occurs when the currently running thread is suspended (for example, if it is blocked, has reached the end of its time-slice, or a higher priority thread becomes ready to run) and another thread is made current by the scheduler. The context switch incurs a runtime overhead in terms of the kernel scheduler and, potentially, the memory management unit and hardware caches, if the original and replacing threads are executing in different processes.

8.2 Event-Driven Multitasking

Moving up a level, let’s look at some typical examples of events and event-driven multitasking. Events can come from external sources, such as user input or hardware peripherals that receive incoming data. They can also be generated by software, for example by timers or completed asynchronous 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, which waits for user input and responds by submitting requests to receive web

EVENT-DRIVEN MULTITASKING

113

pages which it then displays. The web browser may use a system server, which waits to receive requests from its clients, services them and returns to 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 need to 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 another service. This service will later cause another event, or may indicate that the service has completed, which may cause another event in a different part of the system. The operating system must have an efficient eventhandling model to handle each event as soon as possible after it occurs and, if more than one event occurs, in the most appropriate order. It is particularly important that user-driven events are handled rapidly to give feedback and a good user experience. Between events, the system should wait in a low power state. This avoids polling constantly, which can lead to significant power drain and should be avoided on a battery-powered device. Instead the software should allow the operating system to move to an idle mode, while it waits for the next event.

On hardware running Symbian OS, resources are more limited than on a typical desktop PC. Thus, on Symbian OS, besides the requirements to be responsive and handle power consumption carefully, it is also important that the memory used by event-handling code is minimized and that processor resources are used efficiently. Active objects assist with efficient programming by providing a model for lightweight, event-driven multitasking.

Active objects encapsulate the traditional wait loop inside a class. They were designed such that a switch between active objects that run in the same thread incurs a lower overhead than a thread context switch.1 This makes active objects preferable for event-driven multitasking on Symbian OS.

Apart from the runtime expense of a context switch, using pre-emptive multithreading for event handling can be inconvenient because of the need to protect shared objects with synchronization primitives such as mutexes or semaphores. Additionally, resource ownership is threadrelative by default on Symbian OS. If a file is opened by the main thread it will not be possible for a different thread in the process to use it without the handle being explicitly shared through a call to RSessionBase::Share() (and some Symbian OS servers do not support session sharing at all). Because of this restriction, it may be

1 The difference in speed between a context switch between threads and transfer of control between active objects in the same thread can be of a factor of 10 in favor of active objects. In addition, the space overhead for a thread can be around 4 KB kernel-side and 8 KB user-side for the program stack, while the size of an active object may be only a few hundred bytes, or less.

114

EVENT-DRIVEN MULTITASKING USING ACTIVE OBJECTS

very difficult to use multiple threads as a viable method for event-driven multitasking. More detail on threads can be found in Chapter 10, while the 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 shared resources. In addition, because active objects run in the same thread, memory and objects may be shared more readily. Active objects still run independently of each other, despite existing in the same thread, in much the 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 will consist of a single main event-handling thread. A set of active objects run in the thread, each representing a task. Each active object requests an asynchronous service, waits while it is serviced, handles the request completion event and communicates with other tasks as necessary.

Some events require a response within a guaranteed time, regardless of any 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 a sound driver supplied with sound data – a delay in response delays the sound decoding, which results in it breaking up. Other typical real-time requirements may be even more strict, say for low-level telephony. These tasks have, in effect, different requirements for real-time responses, which can be represented by task priorities. Higher-priority tasks must always be able to pre-empt lower-priority tasks in order to guarantee to meet their real-time requirements. The shorter the response time required, the higher the priority that should be assigned to a task.

However, once an active object is handling an event, it may not be pre-empted by the event handler of another active object2, which means that they are not suitable for real-time tasks. On Symbian OS, real-time tasks should be implemented using high-priority threads and processes, with the priorities chosen as appropriate for relative real-time requirements.

Active objects are used on Symbian OS to simplify asynchronous programming and make it easy for you to write code to submit asynchronous requests, manage their completion events and process the result. They are well suited for lightweight event-driven programming, except where a real-time, guaranteed response is required.

2 Note that, although the active objects within a thread run cooperatively without pre-emption, on Symbian OS the thread in which they run is scheduled pre-emptively.