Symbian OS depends heavily on asynchronous services and operations. This
is required by the nature of Symbian OS: micro-core
and C/S architecture, quick response and running on handsets. There are
solutions for asynchronous operation such as multi-threading. Multi-threading
is a good solution on desktops and workstations. However, on handsets, it’s
inappropriate to create so many threads due to limited system resource. User
will get performance penalty on handsets using multi-threading solution,
especially when running many applications.
To make a tradeoff, Symbian introduced the paradigm Active Object to
serve as an alternative. In general, AO is a paradigm for non-preempt, multi-tasking in a single thread. By using AO, the
number of threads can be reduced significantly because few threads (typically 2,
1 for server and 1 for client.) are needed to perform request/response
operations. AO is replacement for multi-thread that sends request and receive
response. One can use 1 AO for each kind of asynchronous request. For example,
in 1 thread, one can create 3 AO’s: 1 to wait for user input, 1 to read file,
the 3rd to communicate with other devices through socket. So far we
will only consider the client thread. Same applies to server thread. As for AO and
C/S internals, I will not talk about details because: I myself am not very
familiar with the internals and, it will be another big story which cannot be
elaborated in 1 essay.
Overview
Consider the figure shown above, How AO and AS work is quite clear and
simple. First we create an AS and install it to a thread. Then in that thread,
we create some AO’s and add them to the task queue of the AS. After issue first
request to service provider, we start the event loop of AS. This will cause a P()
operation on request semaphore of the thread. If the request is done, service
provider will recognize the requesting thread (another topic) then do a V()
operation on request semaphore on that thread and set the status of
corresponding AO to complete. The AS will be waken up upon the event. It will traverse
the task queue to find the AO which in complete status, and then invoke the
RunL() of the AO in a TRAP. (I’m sure this paragraph contains so much
information that you are now lost. Don’t worry, because we don’t need to know
these so far;-)
Lifecycle of AO and AS
The figure
shown above is not accurate but it demonstrates the typical use of AO and AS.
The server itself may be implemented using AO’s
Example
The
simplest one is to read a char from input and write to the screen through
console. No comments are needed:
Obviously, non-preempt
means tasks with higher priority may not be run until other task’s RunL()
returns. The priority helps, but not ensures tasks with higher priority will be
run first. The second pitfall is when RunL() is time consuming, it’s harmful to
other AO’s which may not have opportunity to run. With careful design and
programming, this pitfall can be minimized.