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

EXCEPTION HANDLING

163

RThread::ReadL() can be used to transfer data into the currently running thread from the thread represented by a valid RThread handle. ReadL() transfers data from a descriptor in the ”other” thread, identified as a const TAny pointer, into a modifiable descriptor (8- or 16-bit) in the current thread. The function leaves with KErrBadDescriptor if the TAny pointer does not point to what appears to be a valid descriptor. The length of the target descriptor can be determined before reading from it by a call to RThread::GetDesLength().

Inter-thread data transfer uses descriptors because they fully describe their length and maximum allowable length, which means that no extra parameters need to be transferred to indicate this information. If you want to transfer non-descriptor data, you can use the package classes TPckgC and TPckg, described in Chapter 6, which effectively ”descriptorize” the data. Package classes are only valid for transferring a flat data structure such as that found in a T class object; their use in inter-thread data transfer between client and server threads is discussed in Chapter 12.

10.5 Exception Handling

On EKA1, the RThread API supports thread exception management. On the more secure EKA2 platform, this has moved into class User and applies only to the current thread. The signatures of the five functions are the same, however, regardless of the class that implements them.

TExceptionHandler* ExceptionHandler() const;

TInt SetExceptionHandler(TExceptionHandler* aHandler, TUint32 aMask); void ModifyExceptionMask(TUint32 aClearMask, TUint32 aSetMask);

TInt RaiseException(TExcType aType);

TBool IsExceptionHandled(TExcType aType);

SetExceptionHandler() allows you to define an exception handler function for the thread for which the handle is valid. It takes an exception-handling function and a bitmask that allows you to specify the category of exception which will be handled (see e32std.h).

const TUint KExceptionAbort=0x01; const TUint KExceptionKill=0x02;

const TUint KExceptionUserInterrupt=0x04; const TUint KExceptionFpe=0x08;

const TUint KExceptionFault=0x10; const TUint KExceptionInteger=0x20; const TUint KExceptionDebug=0x40;

If an exception is raised on the thread that falls into the category handled, it will be passed to the specified exception handler to be dealt with.

164

SYMBIAN OS THREADS AND PROCESSES

The exception handler function, TExceptionHandler, is a typedef for a function which takes a value of TExcType (an enumeration which further identifies the type of exception) and returns void. Each of the TExcType enumeration values each correspond to one of the categories above but they identify the exception further, for example EExcBoundsCheck, EExcInvalidOpCode and EExcStackFault are all types of the KExceptionFault category.

What should an exception handler function do? Well, you cannot identify where the problem occurred from within the handler, so the only thing you can do is leave from the handler function. Effectively, the handler converts an exception into a leave which can be caught and dealt with. However, by doing this, you require a TRAP around every operation that could generate an exception of that type. This could have a significant impact in terms of code size and speed (as discussed in Chapter 2) and as a result, while this technique might be useful for debugging, it is not recommended for code you intend to release.

Without a handler specified, the exception terminates the thread with a KERN-EXEC 3 panic if it occurs during a kernel executive call, or a USER-EXEC 3 panic if it occurs in a non-system call.

10.6Processes

I introduced processes in Chapter 8 and briefly mentioned them in this chapter when discussing relative thread priorities. The RProcess class can be used to get a handle to a running process, in much the same way as RThread for a running thread. RProcess is defined in e32std.h and a number of the functions look quite similar to those in

RThread.6

You can use the default constructor to create a handle to the current process, the Create() function to start a new, named process and the Open() function to open a handle to a process identified by name or process identity (TProcessId). The Resume() functions and assorted functions to stop the process will also look familiar. Note that there is no Suspend() function because processes are not scheduled; threads form the basic unit of execution and run inside the protected address space of a process.

Chapter 13 discusses the difference between the emulator and target hardware in more detail, but one aspect is particularly relevant here. On Windows, the emulator runs within a single Win32 process, EPOC.exe, and each Symbian OS process runs as a separate thread inside it.

6 The SDK documentation for RThread and RProcess is extensive and should be consulted for further details of both these classes. Like the RThread class, RProcess has been secured in EKA2, resulting in the removal of some functions and the restriction of others to apply only to the currently running process

PROCESSES

165

On EKA1 the emulation of processes on Windows is incomplete and

RProcess::Create() returns KErrNotFound. To emulate any code that spawns a separate process, e.g. server startup code, different source code is required for emulator builds, using threads instead of processes in which to launch the server. The EKA2 release has removed this inconvenience. While Symbian OS still runs in a single process on Windows (indeed, that’s what the ”S” in WINS, WINSCW and WINSB stands for), the emulation is enhanced and you can use the same code, calling RProcess::Create() on both platforms. Symbian OS, for emulator builds, translates this call to creation of a new Win32 thread within EPOC.exe.

I’ll conclude this chapter with a brief description of the most fundamental process within Symbian OS, the kernel server process, and the threads which run within it. I’ll restrict the discussion to Symbian OS EKA1 – you will be able to find more detail of the changes introduced by EKA2 from the relevant system documentation (www.symbian.com/technology/ product descriptions.html). On EKA1, the kernel server process is a special process that contains two threads which run at supervisor privilege level:

the kernel server thread

This is the first thread to run in the system and has the highest priority of all threads. It implements all kernel functions requiring allocation or deallocation on the kernel heap and manages hardware resources. Device drivers run in the kernel thread and use interrupt service routines and delayed function calls to service events from the hardware.

the ”Null” or ”Idle” thread

This has the lowest priority in the system and therefore runs when no other threads are ready to run. It switches the processor into idle mode to save power, by calling a callback function to shut down part of the hardware. This allows Symbian OS to conserve power most efficiently, thus maximizing the battery life. To allow the Null thread to run, your code should wait on events (typically using active objects or kernel signaling primitives such as mutexes) rather than polling constantly. A polling thread prevents the Null thread from running and stops Symbian OS from entering its idle, power-saving, mode.

The other threads in the system are known as user threads and run in an unprivileged state. User threads can access kernel services, such as other threads or processes, using the APIs in the user library (EUser.dll). When a user thread requires a kernel service, EUser either switches to the kernel executive, which runs kernel-privileged code in the context of the running thread, or makes a call via the executive into the kernel server process.

166

SYMBIAN OS THREADS AND PROCESSES

10.7Summary

This chapter compared the use of pre-emptively scheduled threads on Symbian OS with cooperatively scheduled active objects. Active objects are preferred for most multitasking code because they have lower runtime overheads. However, threads are sometimes necessary, for example if priority-based pre-emption is required or to perform a long-running background task asynchronously where it cannot be split into increments.

The chapter reviewed the RThread class, which represents a handle to a thread on Symbian OS. It identified the differences in the RThread API between EKA1 and EKA2 releases, because EKA2 has removed the facility for one thread to affect any other thread running in a separate process. The RThread API allows a thread handle to rename a thread, modify its priority and suspend, terminate or panic it. It also provides a means by which data may be transferred between threads (inter-thread data transfer is discussed in more detail in Chapters 11 and 12).

The chapter concluded by discussing Symbian OS processes in brief, and included a short description of the threads running with the EKA1 kernel server process.

The use of active objects for multitasking on Symbian OS is discussed in Chapters 8 and 9.

11

The Client–Server Framework

in Theory

In theory there is no difference between theory and practice. In practice there is

Yogi Berra

This chapter examines the client–server framework model on Symbian OS. I’ll be discussing the theory, such as why client–server is used on Symbian OS, how it works and the implementation classes involved. There’s a lot of information, so I’ll use a question and answer structure to break the chapter down clearly into logical sections.

When programming for Symbian OS, it is likely that you will often use system servers transparently, via classes that wrap the actual details of client–server communication. It’s less common to implement your own server or write client-side code that accesses a server directly. So in this chapter, I’ll make it clear which information you can skip if you really only want to know the basics of the Symbian OS client–server architecture and how to use a server as a typical client. I’ll illustrate the chapter with examples of how to use a typical Symbian OS system server, the file server.

The next chapter works through some example code for a Symbian OS client and server, to illustrate how a typical implementation is put together and explain how to go about writing your own.

This chapter discusses the client–server model for Symbian OS releases up to and including v7.0s (the code samples use the client–server APIs from Symbian OS v7.0). On Symbian OS v8.0, the concepts are generally the same, but some of the APIs have changed. Rather than confuse matters, I’ve decided to concentrate solely on the releases available at the time of going to press. You can find more information about the differences in v8.0 from the relevant v8.0 SDKs when they become available, from other Symbian press books and, I hope, later editions of this book, or from the Symbian website (www.symbian.com/technology.html).