Multitasking Basics
In simplest of applications ,the program code would make a function call to request a service,from either other Os servers/frameworks ,I/O Devices,timers,DMA etc.This service can be performed either synchronously or asynchronously.In a synchronous method the service returns to the caller function with a status of completion (typically success or failure).While the service completes the caller thread is in a blocked mode waiting for completion.In an asynchronous call ,the request is submitted and the control returns to the caller.The completion of that request occurs sometime later.In the meanwhile the caller may perform other tasks and is not in a blocked state.upon completion the caller receives a signal indicating the completion of the request.Now the caller threads handles the result of the completed request.This signal is known as the event and the code is said to be event driven.
Even-driven multitasking
Events can come from external sources,such as UI inputs ,hardware sources,network sockets and also from completed asynchronous requests.Events are managed by event handlers ,which ,as its name suggests,waits for an event and then handles it.Typically the hardware running Symbian or iOs, or for that matter any other RTOS would have far less resources than a typical PC.Thus the operating system needs to have a efficient event handling model to have minimum turnaround time to events as well as prioritize them in desired order.Also between events the system should be a low power state to save on the power consumption.This avoids constant polling, which leads to significant power drain and should be avoided on a battery operated device.
Runloops in iOS and Active Schedulers in Symbian provide a model for lightweight ,event-driven multitasking within the same thread.
Active objects/Active Scheduler:
Active Scheduler is the indefinite runloop which runs inside a thread .Active objects symbolize the requests which are added to the scheduler and get serviced accordingly.
Active objects encapsulate the traditional wait loop inside a class.They were designed such that the switch between the active objects running within a thread incurs a less overhead than context switching of threads(Moreover space overhead for a thread is minimum 4kb on the kernel side and 8kb user side).This makes active objects the most preferable for event-driven multitasking in Symbian.
Active scheduler is a infinite run loop which runs inside a thread,with methods to start and stop the loop.Once started this loop schedules the active objects within the thread.Typically, a Symbian OS thread has a single Active Scheduler. As mentioned above, that Active Scheduler is responsible for managing all active objects belonging to the thread.It is worth noting that the Active Scheduler schedules active objects in a non-pre-emptive way so that one active object cannot interrupt another while that is running. This is in contrast with thread scheduling (even in Symbian OS), since the execution of one thread can be pre-empted at any given time by another thread.
Representation:
Active Objects encapsulates: A data member representing the status of the request(iStatus). A handle on the asynchronous service provider. Connection to the service provider during construction. The function to issue(or reissue) the asynchronous request (user-defined) The handler function to be invoked by the active scheduler when the request completes( RunL() ).This function can be more appropriately called as the event handler for clarity. The function to cancel an outstanding request( Cancel() ).
The above figure shows the process of submitting a request to an asynchronous service provider ,which generates an event on completion.
Explanation:
1.Request is posted to asynchronous service provider.
2.Having issued the request the issuer must call CAtive::SetActive().This sets the active objects iActive flag.
3.The request provider changes the value of the iStatus as KRequestPending.
4.The active scheduler checks the iActive and the iStatus to know that a particular active object has a request pending.
5.Once the request is completed the service provider calls the User::RequestComplete(),passing the completion result in the iStatus.
6.The active scheduler now calls the handler function (Runl()) for the active object and clears the iActive flag for the same.
7.The handler function handles the event.
Runloops(CFRunloop) in iOS
A run loop is essentially an event-processing loop running on a single thread. The RunLoop is what keeps your app running until it should quit.You register potential input sources on it, pointing it to the code that it should execute whenever input is available on those sources .
Then when input comes into a particular source, the run loop will execute the appropriate code, then go back to waiting for input to come in again to any of it’s registered sources. If input comes into a registered source whilst the run-loop is executing another piece of code, it’ll finish executing the code before it handles the new input.The scheduling is non pre-emptive and analogues to the way the active scheduler schedules the requests.
In all its simplicity it can be described as a glorified form of :
while(true){ HandleEvent1(); HandleEvent2(); }
The job is to process events which arrive from elsewhere.User needs to write code to handle these and the OS takes care of all the other things like scheduling,receiving and sending them.The level of abstraction at which the user interacts with the OS is higher than in Symbian ,resulting in fewer things to be done by the user and the OS taking care of the rest.There is exactly one runloop per thread and the user cannot create or destroy the same.
Example showing ,how to hook up a socket with the current runloop
CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent(); //This gets the current run loop
CFRunLoopSourceRef runLoopSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, listeningSocket, 0);
//Event source is created with the listening socket.
CFRunLoopAddSource(currentRunLoop, runLoopSource, kCFRunLoopCommonModes);
//This event source if finally now added to the run loop
Now whenever there is a connection request on the socket the run loops calls the serverAcceptCallback() which is the callback function for the listeningSocket. Following is a comparison between Symbian and iOS.
Symbian
- Active Scehduler
- CActiveScheduler::Add(instance of the active object)
- HandleEvent – RunL()
- CActiveScheduler Start()
iOS
- CFRunloop
- CFRunLoopAddSource(Source for the event)
- Callback function for the above event source.
- CFRunloopRun()
Limitations of event-driven multitasking in a single thread:
We have seen that in both cases the handling of events is non pre-emptive in the way they are scheduled by the active scheduler or the runloop.So if the event handler code is something which would take lot of time to complete ,in such a scenario the main thread would become un-responsive and the loop would wait for the particular event handling to get over.In such scenarios multithreading is a better option.

