Symbian OS - Active Objects


Published on

Active Objects are one of the most important concepts of Symbian OS. You will get in touch with them for nearly all real-world applications. This tutorial will tell you how they work and how to use them. In the challenge you will write an own Active Object to execute a delayed task.


* Concepts of asynchronous processing
* Threads vs. Active Objects
* Using AOs in Symbian OS

Published in: Technology
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Symbian OS - Active Objects

  1. 1. Symbian OS<br />Active Objects and Threads<br />v2.0b – 21 May 2008<br />1<br />Andreas Jakl, 2008<br />
  2. 2. Disclaimer<br />These slides are provided free of charge at and are used during Symbian OS courses at the University of Applied Sciences in Hagenberg, Austria( )<br />Respecting the copyright laws, you are allowed to use them:<br />for your own, personal, non-commercial use<br />in the academic environment<br />In all other cases (e.g. for commercial training), please contact<br />The correctness of the contents of these materials cannot be guaranteed. Andreas Jakl is not liable for incorrect information or damage that may arise from using the materials.<br />Parts of these materials are based on information from Symbian Press-books published by John Wiley & Sons, Ltd. This document contains copyright materials which are proprietary to Symbian, UIQ, Nokia and SonyEricsson. “S60™” is a trademark of Nokia. “UIQ™” is a trademark of UIQ Technology. Pictures of mobile phones or applications are copyright their respective manufacturers / developers. “Symbian ™”, “Symbian OS ™” and all other Symbian-based marks and logos are trademarks of Symbian Software Limited and are used under license. © Symbian Software Limited 2006. <br />Andreas Jakl, 2008<br />2<br />
  3. 3. Contents<br />Concepts of asynchronous processing<br />Threads vs. Active Objects<br />Using AOs in Symbian OS<br />Long-running background tasks<br />Andreas Jakl, 2008<br />3<br />
  4. 4. Asynchronous Processing<br />Overview and motivation<br />Andreas Jakl, 2008<br />4<br />
  5. 5. Synchronous / Asynchronous<br />Andreas Jakl, 2008<br />5<br />Synchronous<br />function call<br />Asynchronous<br />(Blocking)<br />Asynchronous<br />F1<br />F2<br />F1<br />F2<br />F1<br />F2<br />Call<br />Request<br />Request<br />wait<br />Return<br />Request completed<br />Request completed<br />e.g.:RBufbuf;buf.CreateL(10);<br />e.g.:iSocket.Read( iBuffer, iStatus );<br />
  6. 6. Motivation – Event Handling<br />Andreas Jakl, 2008<br />6<br />Event (Key press)<br />Keyboard<br />ISR / DFC*<br />Kernel / Driver<br />Key event handling<br />Window update<br />Window Server<br />Key event handling<br />Application<br />ISR = Interrupt Service Handler, DFC = Delayed Function Call<br />
  7. 7. Process<br />Contains 1+ threads<br />New process: creates 1 primary thread<br />Process: each has its own virtual memory<br />Thread: shared memory. Generally a good thing, but negative aspects as well (overwriting data)<br />Andreas Jakl, 2008<br />7<br />Physical Memory<br />Virtual address space<br />Virtual address space<br />Process 1<br />Process 2<br />Thread(s)<br />Thread(s)<br />Memory access<br />
  8. 8. Multitasking<br />Pre-emptive:<br />Threads run as long as they live or until they are interrupted by the scheduler (e.g. because of a thread with higher priority)<br />e.g.: Windows XP, Symbian OS<br />Cooperative:<br />Task runs until it is finished or it gives time to other tasks<br />e.g.: Windows 3.11<br />Non-Preemptive:<br />Task runs until it is finished and is not interrupted until then (in its own process)<br />e.g.: Symbian OS (Active Objects)<br />Andreas Jakl, 2008<br />8<br />
  9. 9. Multitasking – Disadvantages<br />Overheads for a context switch to another process:<br />Runtime overhead (through kernel scheduler)<br />Memory Management Unit<br />Hardware caches<br />Complexity:<br />Protect shared objects(e.g. mutex, semaphore)<br />Resources (files, …) are owned by only 1 thread (by default) – requires session sharing<br />Andreas Jakl, 2008<br />9<br />
  10. 10. Event Handling<br />Active Objects<br />Andreas Jakl, 2008<br />10<br />
  11. 11. What is an Active Object?<br />Requestsasynchronous service<br />provided by Asynchronous Service Provider<br />Receives call-back when finished / error<br />message handling by Active Scheduler<br /> Active Object ≈ Listener!<br />Andreas Jakl, 2008<br />11<br />
  12. 12. Event Handling<br />Andreas Jakl, 2008<br />12<br />Asynchronous Service Providers<br />Asynchronous Service Providers<br />Event 1<br />Event 2<br />Event 1<br />Event 2<br />Event 3<br />Event 3<br />Application (Possibly an extra thread)<br />Application (thread)<br />ActiveScheduler (in app. thread)<br />Event Handler (Thread)<br />Event Handler (Thread)<br />Event Handler (Thread)<br />Event Handler (AO)<br />Event Handler (AO)<br />Event Handler (AO)<br />all executed at the same time<br />(pre-emptive scheduling)<br />executed one after another<br />Traditional Event-Handling<br />ActiveObjects(Symbian OS)<br />
  13. 13. Active Objects<br />Asynchronous Service Provider (ASP)<br />Executes asynchronous task<br />e.g. timer, socket-related request, take a camera picture, load and prepare a sound file, ...<br />Application-side:<br />AOs encapsulate ASP and event handling (after the request to the ASP has finished)<br />Modular separation:<br />Active Scheduler (AS): event completion processing for all ASPs<br />Active Object (AO): individual event handling<br />Andreas Jakl, 2008<br />13<br />
  14. 14. Multiple Applications<br />System overview with multiple applications / threads<br />Andreas Jakl, 2008<br />14<br />Single event handling thread<br />Kernel scheduler<br />(preemptive)<br />Active Scheduler (non-preemptive)<br />Active Obj.(Priority)<br />AOPrio.<br />AOPrio.<br />…<br />Asynchronous Service Provider (RTimer, …)<br />ASP<br />ASP<br />Thread<br />Thread<br />Active Scheduler<br />… not all threads require an AS<br />
  15. 15. Application Overview<br />Andreas Jakl, 2008<br />15<br />Callback(completition / error)<br />Application (Thread)<br />Active Scheduler<br />Asynchronous Service Provider (ASP)<br />Active Object 2<br />Active Object 3<br />Active Object 4<br />Active Object 1<br />Issuerequest<br />ACTIVE<br />iStatus = KErrNone<br />NOT ACTIVE<br />ACTIVE<br />iStatus = KErrNotFound<br />ACTIVE<br />iStatus = KRequestPending<br />List of registered AOs:<br />ASP<br />ASP<br />AO 1: Issued request, waiting for completition<br />AO 2: Request completed, call-back not yet handled<br />AO 3: No request is active<br />AO 4: Request completed, call-back not yet handled,<br />error during ASP execution<br />ASP<br />
  16. 16. Scheduling<br />Andreas Jakl, 2008<br />16<br />AO1: EPriorityStandard () AO2: EPriorityLow () AO3: EPriorityUserInput ()<br />Event 1<br />Event 2<br />Event 3<br />AO 1RunL()<br />AO 2RunL()<br />AO 3RunL()<br />1.<br />Event 1<br />Event 2<br />Event 3<br />AO 2RunL()<br />AO 3RunL()<br />AO 1RunL()<br />2.<br />Event 1<br />Event 2<br />Event 3<br />AO 2RunL()<br />AO 3RunL()<br />AO 1RunL()<br />3.<br />
  17. 17. Structure of an AO<br />Andreas Jakl, 2008<br />17<br />
  18. 18. Active Object Class<br />Tasks of an Active Object<br />Request asynchronous service<br />Handle completion event<br />Provide a way to cancel the outstanding request<br />(optional) Error handling<br />To create it<br />Derive a class from CActive<br />Override two virtual functions: RunL() and DoCancel()<br />Andreas Jakl, 2008<br />18<br />
  19. 19. AOs – Classes<br />Andreas Jakl, 2008<br />19<br />You only have to create this class<br />
  20. 20. Example – Overview<br />Timer example<br />Creates continuous events, writes to RDebug-log<br />Our Active Object: CExampleTimer<br />Interface to the Asynchronous Service Provider<br />Symbian OS RTimer-object<br />Asynchronous Service Provider<br />Generates call-back after a specified amount of time<br />Note: A behaviour like this is actually pre-implemented in Symbian OS (class CTimer)<br />Andreas Jakl, 2008<br />20<br />
  21. 21. CExampleTimer – Definition<br />Andreas Jakl, 2008<br />21<br />class CExampleTimer : public CActive {<br />public:<br /> ~CExampleTimer();<br />// Standard Symbian OS two-phased construction<br /> // Note: AOs usually created as instance variables -&gt; NewLC() normally not necessary<br /> static CExampleTimer* NewL();<br />// Function called by our own application to initiate regular call-backs<br /> void After(TTimeIntervalMicroSeconds32& aInterval);<br />protected:<br />CExampleTimer();<br /> void ConstructL();<br />protected:// Inherited from CActive …<br /> virtual void RunL(); // Handle the timer event<br /> virtual void DoCancel(); // Cancel the timer<br /> virtual TIntRunError(TIntaError); // Leave occurred during RunL()<br />private:<br />RTimeriTimer; // Symbian OS Asynchronous Service Provider<br /> TTimeIntervalMicroSeconds32 iInterval; // Save interval for regular call-backs<br />};<br />
  22. 22. Create an AO<br />CActive-derived class has to call constructor of base class with desired priority<br />Add to the ActiveSchedulerer<br />Andreas Jakl, 2008<br />22<br />CExampleTimer::CExampleTimer()<br />: CActive(EPriorityStandard)<br />{<br />CActiveScheduler::Add(this);<br />}<br />CExampleTimer::ConstructL() {<br />// Create the timer object (= Asynch. Service Provider)<br />User::LeaveIfError(iTimer.CreateLocal());<br />}<br />1<br />2<br />
  23. 23. Send out a new Request<br />Test if a previousrequest is still active (only 1 Request / AO). If yes, either:<br />Trigger a Panic if this can only happen because of a programming error<br />Decline the new request (if allowed by the logical structure)<br />Cancel and discard currently active request, send new request<br />Send request to ASP, pass AO’s own iStatus as TRequestStatus&-parameter<br />ASP will set iStatus to KErrNone when the request was finished successfully, otherwise to an error code<br />Call SetActive()of the CActive-Base class<br />... to inform the Active Scheduler that we’re waiting for a request<br />Andreas Jakl, 2008<br />23<br />
  24. 24. New Request – Example<br />Andreas Jakl, 2008<br />24<br />void CExampleTimer::After(TTimeIntervalMicroSeconds32& aInterval)<br />{<br /> // Only allow 1 active timer request at a time<br /> // Here: caller (= app.) has to cancel the previous request himself – would also be // be possible to cancel the request here or to ignore the new one<br /> if (IsActive()) {<br /> _LIT(KExampleTimerPanic, “CExampleTimer”);<br />User::Panic(KExampleTimerPanic, KErrInUse));<br /> }<br />iInterval = aInterval; // Save the interval for regular callbacks<br />// Submit the request to the Asynchronous Service Provider  start the timer!<br />iTimer.After(iStatus, aInterval);<br />// Mark this object active, so that the Active Scheduler knows we expect a callback<br />SetActive();<br />}<br />
  25. 25. Event Handling<br />AO has to implement RunL() – called by ASP when request has been processed<br />What RunL() usually does:checks completion code (iStatus)<br />Depending on iStatus:<br />Send out another request<br />Notify other objects in the system / application<br />Can not be pre-empted by other AOs  make the processing time as short as possible!<br />Andreas Jakl, 2008<br />25<br />
  26. 26. Event Handling – Example <br />Andreas Jakl, 2008<br />26<br />void CExampleTimer::RunL()<br />{<br />// If an error occurred, deal with the problem in RunError()<br /> // (not very likely in the case of an RTimer)<br />User::LeaveIfError(iStatus.Int());<br />// No error: Log the timer completion (or do any processing you like)<br /> __LIT(KTimerExpired, “Timer Expired ”);<br />RDebug::Print(KTimerExpired);<br />// Resubmit a new timer request, to provide continuous call-backs<br />iTimer.After(iStatus, iInterval);<br />SetActive();<br />}<br />
  27. 27. Cancelling<br />AO must be able to cancel every asynch. process<br />e.g. when application is closed<br />Implement DoCancel()<br />Call ASP cancellation<br />Do necessary Cleanup<br />Must not cause a leave (no L!)<br />Application should only call Cancel()from CActive, not DoCancel() directly!(Cancel() checks if the AO is currently active at all and only calls DoCancel() if necessary)<br />Andreas Jakl, 2008<br />27<br />
  28. 28. Cancelling – Example <br />Andreas Jakl, 2008<br />28<br />void CExampleTimer::DoCancel()<br />{<br /> // CActive::Cancel() checks if the AO is active and only calls DoCancel() if it is. <br /> // Therefore, we don’t have to check if the AO is active before cancelling the ASP.<br />iTimer.Cancel();<br />}<br />
  29. 29. Error handling<br />If there’s a leave in RunL() Active Scheduler calls RunError() of your AO<br />Parameter: Leave code.Return: Taken care of leave?<br />Yes: return KErrNone<br />No: ActiveSchedulerer calls own Error()  no context information is available anymore  problematic<br />Andreas Jakl, 2008<br />29<br />
  30. 30. Error Handling – Example <br />Andreas Jakl, 2008<br />30<br />TIntCExampleTimer::RunError(TIntaError)<br />{<br />// Called by the Active Scheduler if RunL() leaves<br /> // The parameter aError contains the error code<br /> _LIT(KErrorLog, “Timer Error %d”);<br />// Log the error<br />RDebug::Print(KErrorLog, aError);<br />// Tell the Active Scheduler that the error has been handled<br /> return KErrNone;<br />}<br />
  31. 31. Destructor<br />Call Cancel() in the AO-destructor!<br />Cancel active requests<br />Remember: Cancel() only calls DoCancel() if the AO is active!<br />Release resources of the object<br />Deleting AO without cancelling request:<br />causes a „stray signal“ (E32USER-CBASE 46)<br />Andreas Jakl, 2008<br />31<br />
  32. 32. Destructor – Example <br />Andreas Jakl, 2008<br />32<br />CExampleTimer::~CExampleTimer()<br />{<br />// Don’t call DoCancel() directly! AObject::Cancel() will only call DoCancel()<br /> // if the AO is active and waits for the ASP to actually cancel the request<br /> // to avoid stray signals<br />Cancel();<br /> // Do normal cleanup after cancelling the AO!<br />iTimer.Close();<br />}<br />
  33. 33. Stray Signals<br /><ul><li>Active Scheduler receives completion event, but can’t find corresponding Active Object to handle it</li></ul> “Stray Signal”-panic (E32USER-CBASE 46)<br />Possible reasons:<br />CActiveScheduler::Add() missing in AO-construction<br />SetActive() not called after submitting request<br />More than 1 call-back from ASP (due to programming error or multiple requests from the same AO)<br />Andreas Jakl, 2008<br />33<br />
  34. 34. AOs – Events and Sequence<br />Andreas Jakl, 2008<br />34<br />Executable<br />Active Object<br />Active Scheduler<br />Asynch. Service Prov.<br />Create Active Scheduler<br />Wait for AOs<br />Create AO<br />Register with Active Scheduler<br />Issue request to AO<br />Request to ASP,AO::SetActive()<br />Set status of AO and start serviceAO::iStatus = KRequestPending<br />WaitForAnyRequest()<br />Start Active Scheduler(only after first AO)<br />iActive=ETrueiStatus=KRequestPending<br />Run asynch.service<br /><br />Service CompletesAS::RequestComplete()<br />Call RunL() of AOAO::iStatus=KErrNone<br />AO::RunL()Handle event. Resubmit new request or stop AS.<br />(optional)<br />Cleanup, exit program<br />Process orthread boundary<br />
  35. 35. Active Objects vs. Threads<br />Active Objects:<br />Less runtime overhead<br />Easier to implement: no mutexes, semaphores, ...<br />You have to split up long processes into smaller, individual steps<br />Threads:<br />Large overhead for a context switch<br />If you need them: use RThread Thread with pre-emptive multitasking<br />Andreas Jakl, 2008<br />35<br />
  36. 36. Background Tasks<br />Long running<br />Andreas Jakl, 2008<br />36<br />
  37. 37. Background Task<br />Usual solution:<br />low-priority thread<br />If you want to use AOs:<br />Split task into multiple short increments( short RunL() as it cannot be pre-empted)<br />Assign low priority (EPriorityIdle)<br />Instead of using a timer, the AO instantly completes itself<br />Andreas Jakl, 2008<br />37<br />AO::Activate()<br />AO::RunL()Background task<br />(when the system is idle)<br />Active Scheduler<br />User::RequestComplete()<br />
  38. 38. Instant Completition<br />AO tells Active Scheduler that its request has finished<br />AS calls RunL() only when the system is idle due to the low priority of the AO<br />Andreas Jakl, 2008<br />38<br />Call this code when initiating the background processing and after every increment of the RunL()-function:<br />TRequestStatus* status = &iStatus;<br /> // Generates event on itself<br /> User::RequestComplete(status, KErrNone);<br /> // Important to set the AO as active so that the AS can call our RunL()<br />SetActive();<br />... Symbian’s wrapper class CIdle can also do that for you!<br />
  39. 39. ASD-like Question – Easy <br />Which of the following statements about active objects are incorrect?<br />A.SetActive() should be called on an active object by the calling client, after it has called the function which submits a request to an asynchronous service provider. <br />B. An active object class should implement RunL() and DoCancel() methods.<br />C. The active object framework allows an active object to have multiple outstanding asynchronous requests.<br />D. An active object should always derive from CActive.<br />E. The active object should implement RunError() if a leave can occur in the RunL() function.<br />Andreas Jakl, 2008<br />39<br />Copyright Meme Education, 2006<br /><br />
  40. 40. Solution<br />A. Incorrect. The Active Object sets itself active right after it has submitted the request to the Asynchronous Service Provider (ASP).<br />B. Correct. <br />C. Incorrect. Each Active Object (AO) can only have one pending request at the same time. If a second one should be issued, the AO can either Panic, ignore the new request or stop the previous request first.<br />D. Correct. <br />E. Correct. <br />Andreas Jakl, 2008<br />40<br />
  41. 41. ASD-like Question – Medium<br />Which of the following statements regarding an active object used for a long-running background task are correct?<br />A. It should have a high priority to ensure that it gets a chance to run to completion.<br />B. It should maintain an internal state machine to track the different stages of the task.<br />C. It should split the long-running task into small processing “slices”, with each execution of RunL() performing one such slice only.<br />D. It should contain no accesses to data that would cause problems if the RunL() was preempted.<br />E. It should use a timer to generate events that invoke RunL().<br />Andreas Jakl, 2008<br />41<br />Copyright Meme Education, 2006<br /><br />
  42. 42. Solution<br />A. Incorrect. Long running background tasks should have a low priority, so that high priority events (e.g. user input) can be handled instantly.<br />B. Correct. <br />C. Correct.<br />D. Incorrect. Active Objects are not pre-empted when they are in RunL(), therefore the RunL()-method should be rather short.<br />E. Incorrect. Background-tasks instantly set themselves to be complete, so that the Active Scheduler calls them again right away if no higher priority AO is waiting.<br />Andreas Jakl, 2008<br />42<br />
  43. 43. ASD-like Question – Hard<br />The active scheduler causes a &quot;stray signal&quot; panic (E32USER-CBASE 46) when the scheduler receives a request completion and cannot find an active object associated with it.Which of the following errors in the implementation of an active object class could cause this problem?<br />A. Not calling SetActive() after submitting a request to an asynchronous service provider.<br />B. Not checking whether there is an outstanding request in the implementation of DoCancel().<br />C. Forgetting to add an active object to the active scheduler.<br />D. Implementing RunL() so that it performs a lot of time-consuming processing before returning.<br />E. Setting iStatus to KRequestPending before submitting it in a request to an asynchronous service provider.<br />Andreas Jakl, 2008<br />43<br />Copyright Meme Education, 2006<br /><br />
  44. 44. Solution<br />A. Yes. The Active Scheduler can only send completion events to Active Objects that are active and therefore waiting for completion events.<br />B. No. DoCancel() is only called by the Active Object base class after Cancel() checks that a request is currently active <br />C. Yes. The Active Scheduler can’t send the event to the Active Object if it doesn’t know about it.<br />D. No. This is of course bad practice and makes your app unresponsive, but doesn’t cause a panic.<br />E. No. Automatically done by the Asynchronous Service Provider. Therefore, it doesn’t matter to what you set it before submitting the request.<br />Andreas Jakl, 2008<br />44<br />
  45. 45. Thanks for your attention<br />That’s it!<br />Andreas Jakl, 2008<br />45<br />