Multitasking for Symbian and Qt

Symbian and Qt both provide typical multitasking functionality in the form of threads, processes, synchronization and inter-thread communication. The Qt Mobility API provides limited access to Symbian's inter-process communication API but otherwise the two approaches are separate. Both also provide different in-thread cooperative multitasking systems.

Multitasking introduction

Multitasking is the ability to perform more than one task at a time. It is important to GUI applications, because it allows them to perform long running or computationally expensive operations while still remaining responsive to user input.

There are two types of multitasking: preemptive and cooperative. In preemptive multitasking (or "multithreading"), the operating system gives each thread of execution some time in which to run - the thread has no control over when it runs or how much time it gets. In cooperative multitasking, a scheduler controls which task is run next, but the current task alone determines when it completes.

Preemptive multitasking is heavier-weight in terms of RAM and execution speed, and is more difficult to program because of the need to mediate access to shared resources (and ensure threads do not dead-lock). Cooperative multitasking is easier - because access to resources is serialized. However individual tasks need to be short running so that the UI remains responsive.

In multitasking operating systems we use the term process to refer to a set of threads that share the same global memory space, and which can therefore directly access each other's variables. All the threads in an application typically run in the same process. However, it is threads, not processes, that are scheduled for execution.

A multitasking operating system may also be multiprocessing. Multiprocessing is where threads can run on more than one processor (CPU).

Multitasking on the Symbian platform

The Symbian platform is a modern preemptive multitasking operating system.

Applications are created in their own process, running in a single main thread. The kernel preemptively schedules all threads in the system, based on their priority. Although it is possible to create secondary threads, Symbian strongly encourages applications to cooperatively multitask using active objects.

Almost all Symbian services are provided by servers (or "daemons") running in other processes (for example, the File Server, Window Server, Font and Bitmap Server, and Location Server). These usually export an asynchronous API that takes a reference to a TRequestStatus object that the server uses to signal completion of the request. Active objects provide a consistent and lightweight way to write code to submit the asynchronous requests and handle their completion.

Active objects are derived from CActive, which either owns or has a handle to an asynchronous server provider. The active object must add the object to the active scheduler in its constructor and provide a method to set itself as active - first calling the asynchronous method (passing in theTRequestStatus iStatus member) and then calling CActive::SetActive(). When the asynchronous service completes, it signals the active object's thread semaphore and changes the status of the object's iStatus to show that it is no longer pending. The active scheduler later calls the object's RunL() method, which you must implement, to handle completion of the service. Note that this is not immediate - active objects are cooperatively multitasked so the scheduler can only run one at a time, and only when the last one has completed. Lastly, you must implement the virtual DoCancel() which cancels the asynchronous request, and ensure that you call Cancel() in the active object's destructor.

The above summary only touches on the nuances possible with active objects. If you're interested in using or implementing services you may also be interested in reading the Client/Server Overview.

Developers that prefer to use threads and processes can of course do so - in some cases this may be necessary. Symbian C++ processes and threads can be created and manipulated using the RProcess and RThread API, respectively. Symbian C++ has the usual synchronization primitives including mutexes (RMutex), semaphores (RSemaphore), Critical Sections (RCriticalSection) etc. All of these classes are discussed in Thread And Process Management and Inter Process Communication.

Threads in the same process can easily share data directly (taking care to serialize access to shared data). Threads in other processes need to communicate using Symbian's inter-process communications mechanisms. These include Client/Server, Publish and Subscribe, and Message Queues.

Symbian adds support for symmetric multiprocessing (SMP) from Symbian Anna.

The Qt Mobility API provides access to Symbian's Publish and Subscribe API.

Multitasking with Qt

Qt applications use both cooperative and preemptive multitasking.

Qt's main application thread runs its own event loop which processes events generated in response to user interaction (key presses, mouse events etc) and from timers and the window system. This event loop is an example of cooperative multitasking - events are queued and handled synchronously. If too much time is spent on one event then the UI can become unresponsive.

If the computationally intensive operation can be broken into a number of steps - for example writing to a file, then you can call QApplication::processEvents() at regular intervals during the operation to give the event loop time to handle other events from the UI. This approach is discussed in chapter 7 of C++ GUI Programming with Qt 4 , Second Edition, Jasmin Blanchette and Mark Summerfield, Prentice Hall (2006) (the first edition is available free online here).

Some Qt APIs, particularly those for networking, have blocking and non-blocking APIs, making it possible to choose between synchronous and asynchronous styles of programming. The non-blocking APIs provide the ability for the developer to call a method, return control to the event loop, and at a later time receive the result of the call in the form of a signal.

Multithreading (preemptive multitasking) offers an alternative approach. The QtConcurrent classes provide the ability to define concurrent functionality without having to write the thread-management code. The QtConcurrent system then handles the thread creation and synchronization and scales the number of threads as appropriate.

For cases where QtConcurrent is not appropriate, low-level thread management is possible by developers subclassing QThread and re-implementing its run() function to execute code in the new thread. Synchronization classes include QMutex to provide mutually exclusive access to a resource, QReadWriteLock which provides unrestricted access for reading but blocks on writing, QSemaphore which generalises QMutex to allow access to a specified number of resources, and QWaitCondition which blocks until some condition comes true. There are also a few helper classes like QMutexLocker, which simplify mixing mutex programming and standard C++ exception handling.

There are a few good examples here: Mandelbrot Example, Semaphores Example, and Wait Conditions Example. C++ GUI Programming with Qt 4 , Second Edition, Jasmin Blanchette and Mark Summerfield, Prentice Hall (2006) contains an excellent discussion of the multithreading (with some duplication of the other links) in chapter 14.

Threads communicate with each other using shared memory and the above synchronization classes. Threads communicate with the main thread using signals and slots. Note however that by default the signals are not synchronous as they are within a single thread.

Applications can also multitask using other processes. For example it is possible to create a QProcess to launch another process, set its command line arguments and to detect its startup, error and completion status.

You can also use standard C++ threads, processes and inter-process communication mechanisms.

Copyright note

Most of the material in this topic is based with permission on a Symbian Foundation wiki article Apps:Using Qt and Symbian C++ Together . The version used was that available at Symbian Foundation on 3 November 2010. The content in this page is licensed under the Creative Commons Attribution-Share Alike 2.0 UK: England & Wales License (http://creativecommons.org/licenses/by-sa/2.0/uk).