Thursday, June 09, 2005

Symbian IPC #2

In this article, we will focus on Symbian IPC again. The examples we'll focus on will be from the Fibonacci series. These examples illustrate the basic idea of an application engine and active objects.

Wednesday, June 08, 2005

Symbian IPC #1

Letz start with some examples shipped with Symbian code. In this article we'll discuss the IPC examples. These can be found in examples/base/ipc directory.

Interprocess Communication can be of two types :-
1. Synchronous
2. Asynchronous

Let us talk about Asynchronous Interprocess Communication first...

An asynchronous operation issued by a process will not block further processing of the process. Instead, the process is free to proceed with its processing, and may optionally be notified by the system when the operation is fulfilled.

Let us begin with the "acceptInput1" example shipped with the Symbian code. This example illustrates asynchronous IPC processing via a
keyboard. The basic idea is that there is a messenger program which can print greetings periodically . This messenger program is controlled via keystrokes.

The major classes are :-
1. CTimedMessenger - Customized Timer
2. CExampleScheduler - Customized Scheduler
3. CActiveConsole - Abstract class providing facility to issue key requests
4. CWriteKeyProcessor - Accepts input from the keyboard and outputs it to the console.

Working
CTimedMessenger is our customized messenger. It is actually an active object which derives from CTimer and has method for issuing request, cancelling requests and RunL() method, which is called after a request has been completed. It follows the 2-phase construction model

The most interesting function is
void CTimedMessenger::IssueRequest()
{
// There should never be an outstanding request at this point.
_LIT(KMsgAlreadyActive,"Is already Active");

__ASSERT_ALWAYS(!IsActive(),User::Panic(KMsgAlreadyActive,EPanicAlreadyActive));

// Request another wait
CTimer::After( iTicksInterval*1000000);
}

In issueRequest(), we simple ask the program to wait. This is done because the actual code is in RunL().

void CTimedMessenger::RunL()
{
// Handle request completion
// One more tick done
iTicksDone++;

// Print greeting
_LIT(KFormatString1,"%S \n");
console->Printf(KFormatString1,&iGreeting);

// Issue new request, or stop if we have reached the limit
if (iTicksDone <>Printf(KMsgFinished);

// Reset this variable - needed if the object is re-activated later
iTicksDone=0;

// Can now stop the active scheduler
CActiveScheduler::Stop();
}
}

CExampleScheduler only has an implementation of Error function, which throws a panic, when invoked.

CActiveConsole is another active object. It derives from CActive and again provides method for issuing, cancelling requests and the RunL() method. It also wraps a console to write on to.
It further provides a pure virtual method called ProcessKey(), which is implemented by CWriteKeyProcessor. The RunL() method calls this virtual method.

CWriteKeyProcessor derives from
CActiveConsole and provides ProcessKey() implementation. It just has logic for printing any character(except Escape) on screen.

CMessageKeyProcessor is also like CWriteKeyProcessor. It also derives from CActiveConsole and provides implementation for ProcessKeyPress() virtual function. It has another data member CTimedMessenger* iMessenger. This messenger is invoked and cancelled depending on key press.

In doExample(), we create and install a scheduler. We also create a messenger object and finally create a message processor passing these 2 objects. The first requestr is issued explicitely and the scheduler is started.

Major Players :-
1.
CActiveScheduler

Controls the handling of asynchronous requests as represented by active objects.

An active scheduler is used to schedule the sequence in which active object request completion events are handled by a single event-handling thread.

An active scheduler can be instantiated and used directly if either:

  • The RunL() function of all of its active objects is guaranteed not to leave

  • Each of its active objects implements a suitable RunError() function to provide suitable cleanup

If any of the active scheduler's active objects does not provide a RunError() function, then a CActiveScheduler derived class must be defined and an implementation of the Error() function provided to perform the cleanup required.

There is one active scheduler per thread and the static functions provided by the class always refer to the current active scheduler.

2. CActive

The core class of the active object abstraction.

It encapsulates both the issuing of a request to an asynchronous service provider and the handling of completed requests. An application can have one or more active objects whose processing is controlled by an active scheduler.

3. CTimer

Base class for a timer active object.

This is an active object that uses the asynchronous services provided by RTimer, to generate events. These events occur either at a specific time specified as a TTime, or after an interval specified in microseconds.

The RunL() virtual member function is called by the active scheduler after this event occurs.

To write a class derived from CTimer, first define and implement a constructor through which the priority of the CTimer active object can be specified. Then define and implement a suitable RunL() function to handle the completion of a timer request. This function is not defined by CTimer itself and must, therefore, be provided by the derived class.

Note that the CPeriodic and CHeartbeat classes are derived from CTimer, and answer most timing needs.

Symbian Tute Intro

Am beginning a tute of sorts about my Symbian learnings. Kinda building upon the excellent tute by Michele SciabarrĂ .You may access his tutorial at http://www.sciabarra.com/blog/