Wiley.Developing.Software.for.Symbian.OS.2nd.Edition.Dec.2007 (779887), страница 49
Текст из файла (страница 49)
You will need to click through an agreement for thatparticular manufacturer before the request can be submitted.Download the certificateOnce approved you can download the developer certificate from theSymbian Signed website.246PLATFORM SECURITY AND SYMBIAN SIGNED7.7.3 Signing Using the Developer CertificateTo sign your application with a developer certificate, use signsis asdescribed previously. For example:signsis app.sis app_dev.sis devcert.cer devcert.keywhere devcert.cer and devcert.key are the developer certificate’scertificate and private keys, respectively.8Asynchronous Functions and ActiveObjectsAlthough Symbian OS allows you to create pre-emptively scheduledthreads via RThread, as Chapter 9 will describe, you’ll find that in mostprograms you write you rarely need to create threads yourself – evenwhere you would normally do so in another operating system (e.g.,Unix or Linux).
Instead, the preferred option is to have your programrun as a single, event-driven thread using asynchronous functions andactive objects.Most functions are considered synchronous in that they return onlyafter they complete. Asynchronous functions, on the other hand, arefunctions that return immediately and execute in parallel with the callingprogram (they run in separate threads in the background), sending anevent to your calling program when execution is complete. Many ofthe Symbian OS API functions are asynchronous functions, and usingthem provides you with parallel operation in your program, since youcan have multiple asynchronous functions executing at the same time.Active objects are classes used to invoke an asynchronous function, andto handle the completion of the asynchronous function via a callback.Asynchronous functions and active objects are the foundation of theevent-driven operation of Symbian OS, and mastering their use is essentialto becoming a good programmer on this platform.
This chapter looks atasynchronous programming on Symbian OS and describes how to useand implement asynchronous functions and active objects. Let’s start bylooking at what asynchronous functions are, and then describe activeobjects, which is the framework used to take full advantage of them.8.1 Asynchronous FunctionsYou can identify an asynchronous function on Symbian OS by its inclusionof an argument of type TRequestStatus.
TRequestStatus is a type248ASYNCHRONOUS FUNCTIONS AND ACTIVE OBJECTSclass (which encapsulates a simple integer) that represents the status ofthe asynchronous function – that is, whether the function is in progressor has finished and, if it has finished, what its final status is. Many of theSymbian OS API functions come in both synchronous and asynchronousversions.As an example, consider a traditional synchronous function calledMyFunc():TInt MyFunc(TAny *aSomeArg);This function returns after it is completely finished and the return valueindicates the status of the function.An asynchronous version of MyFunc() would look like:void MyFunc(TAny *aSomeArg, TRequestStatus& aStatus);This function may perform the same functionality as the synchronousversion, but instead of returning when it is completed, the function returnsimmediately with aStatus set to KRequestPending to indicate thatMyFunc() is executing in parallel with the calling thread.
When theasynchronous function completes, aStatus changes to the function’sfinal status (KErrNone if successful).At some point you will need to know when the asynchronous functionhas completed. You could wait for the function to complete as follows:TRequestStatus status;MyFunc(anArg, status);// Code may be here which executes in parallel to MyFunc()while (status == KRequestPending) ;but polling the TRequestStatus variable like this is clearly wastefulof processor cycles. A more efficient option is to use User::WaitForRequest(TRequestStatus& aStatus), which will block your calling thread until the asynchronous function has completed (the nameWaitForRequest means that it is waiting for the asynchronous requestto complete), but your thread will yield control to other threads while itis waiting.For example:TRequestStatus status;MyFunc(someArg, status);User::WaitForRequest(status);// MyFunc() is complete, status now contains the function statusINTRODUCING ACTIVE OBJECTS249User::WaitForRequest() waits at a special semaphore owned bythe calling thread, known as the request semaphore (section 9.5 discussessemaphores in Symbian OS).
Each thread has a request semaphoreassociated with it that is created automatically for you by the operatingsystem. When an asynchronous function has completed processing, itfirst sets the TRequestStatus variable that was passed to the functionto its final state, and then signals the calling thread’s request semaphore.User::WaitForRequest(status) returns when the calling thread’srequest semaphore is signaled, and status has a value other thanKRequestPending.User::WaitForRequest() is sometimes the most convenient wayto wait for an asynchronous function to complete.
In effect, it makes anasynchronous function synchronous (sometimes called ‘pseudosynchronous’). For example, you may want to call a function in asynchronous way, yet only an asynchronous version of the functionexists. However, in most cases, User::WaitForRequest() shouldnot be used since it causes your thread to stop executing until the calledfunction is completed, and thus defeats the whole purpose of using anasynchronous function. If your code provides a user interface, it is veryundesirable to block on an asynchronous function, since it isn’t clearhow long it will take to complete, and in the time it is blocked, yourapplication will be unresponsive to user input.The best way of using asynchronous functions (and what they werereally designed for) is through active objects.
Active objects allow you totake full advantage of asynchronous functions by allowing your application to run other code while waiting on the completion of one or moreasynchronous functions.8.2 Introducing Active ObjectsActive objects are classes derived from CActive, which itself derivesfrom CBase, as you’d expect from a C class on Symbian OS. You use anactive object to invoke an asynchronous function (via a method implemented in the CActive derived class).
Then, when the asynchronousfunction completes, a system component known as an active schedulerinvokes the RunL() method of the active object. RunL() is a virtualmethod in CActive that is implemented in the derived active object.You can have more than one active object active at a time, processingasynchronous completion events as they occur.Figure 8.1 shows a high-level view of the functionality of active objects.A thread using active objects consists of one or more active objects andan active scheduler. The active scheduler is an instance of a class calledCActiveScheduler.
Active objects are added to the active schedulerusing CActiveScheduler::Add().250ASYNCHRONOUS FUNCTIONS AND ACTIVE OBJECTSRequestSemaphoreEventsActive Object 1 (CActive)Active Scheduler(CActiveScheduler)EventLoopInvoke asynchronous functionRunL()Active Object 2 (CActive)Invoke asynchronous functionRunL()Other threads running theasynchronous functionsCalling ThreadActive Object N (CActive)Invoke asynchronous functionRunL()Figure 8.1 Active Object High-Level ViewThe active scheduler implements an event loop that waits on thethread’s request semaphore and, when an event is received, invokes theRunL() method of the active object that the event belongs to. RunL()handles the asynchronous function’s completion event and could, in turn,invoke further asynchronous functions.
The active scheduler then waitson the request semaphore for the next event. The event loop is invoked bythe CActiveScheduler::Start() method and, once it is running,everything in the thread is executed through the RunL() functions of theactive objects.Note that the CActiveScheduler::Start() is performed just onetime at the beginning of starting a process. In many cases, such as ina GUI application, the active scheduler is started automatically by theapplication framework.8.2.1 The Non-Pre-Emptive Multitasking ModelThe active scheduler’s event loop, along with its active object’s RunL()invocations, all occur in the same thread, implementing what is knownas non-pre-emptive multitasking. This means that, unlike with threads,INTRODUCING ACTIVE OBJECTS251one active object cannot start running while another one’s RunL() is inprogress, since they are executed as part of a loop in a single thread.
TheRunL() of the currently running active object must completely finishand return before the active scheduler can check for another event andcall another active object’s RunL() method.The important thing to remember from the model just described is thatyou should not spend much time inside your active object’s RunL() function, since it prevents all other active objects in your thread from running.For example, if you called User::After() in one of your active objects,no other active object would be able to run until that one had completed.8.2.2 Creating an Active Object ClassTo create an active object, declare a class and derive it from CActive,as in the following example:class CMyActive : public CActive{public:static CMyActive* NewL();~CMyActive();void InvokeAsyncFunc(); // Some method to invoke the active object’s// associated asynchronous function.protected:CMyActive();void ConstructL();// Overriden from CActivevirtual void RunL(); // handles asynchronous function completionvirtual void DoCancel(); // Cancels an outstanding// asynchronous function callvirtual TInt RunError(TInt aErr); // overridden// to handle a leave that// occurs in RunL()};Then, implement your active object class using the following steps:1.
Implement functions to construct your active object (i.e., the classconstructor, NewL(), and ConstructL()).2. Register the active object with your thread’s active scheduler (usuallydone as part of Step 1).3. Implement one or more requestor functions, each of which invokesan asynchronous function and passes the iStatus member variableof the CActive base class as the TRequestStatus parameter.4.