×
Namespaces

Variants
Actions

Archived:Implementing asynchronous requests using Symbian C++

From Nokia Developer Wiki
Jump to: navigation, search

Archived.pngArchived: This article is archived because it is not considered relevant for third-party developers creating commercial solutions today. If you think this article is still relevant, let us know by adding the template {{ReviewForRemovalFromArchive|user=~~~~|write your reason here}}.

This example shows how to implement asynchronous requests in client/server communication. It shows both the server and its client counterpart implementation.

Article Metadata
Compatibility
Platform(s): S60 3rd Edition, S60 3rd Edition FP1
Symbian
S60 3rd Edition (initial release)
Article
Created: olympio (22 Mar 2008)
Last edited: hamishwillee (21 Jun 2012)


Contents

Overview

Symbian OS programming is event-based. Symbian architecture is composed by several servers that provide access to resources to its clients, the applications. They should provide APIs to event-based programming that consists of asynchronous requests.

Asynchronous requests are made to servers in a way that the response is obtained later, usually through an Active object. This example shows how this kind of request can be implemented by the server.

Preconditions

The reader should be familiarized with Symbian Client-Server Framework.

The reader should also know the basics about implementing servers. See How to create a server from scratch and Client side implementation of a server for more information.

Client side implementation (R class)

The main characteristic in the method signature of a asynchronous request, when compared with a synchronous request is a parameter, an object of type TRequestStatus. This object keeps the state of the request and is owned by the client. The server access it directly to update the state of the request so that the client can know when the request has completed or an error occurred. The header file of the R class is showed bellow. It presents a simple example API that has only one asynchronous request, AsyncRequest, and one synchronous request, CancelAsyncRequest.

// CLASS DECLARATION
/**
* RExampleServerSession
* This class provides the client-side interface to the server session
*/

class RExampleServerSession: public RSessionBase
{
public: // Constructors and destructors
 
/**
* RExampleServerSession.
* Constructs the object.
*/

RExampleServerSession();
 
public: // New functions
 
/**
* Connect.
* Connects to the server and create a session.
* @return Error code.
*/

TInt Connect();
 
/**
* Version.
* Gets the version number.
* @return The version.
*/

TVersion Version() const;
 
/**
* AsyncRequest.
* Issues a request to the server.
* @param aStatus The TRequestStatus object to be used for async comms.
*/

void AsyncRequest( TRequestStatus& aStatus );
 
/**
* CancelAsyncRequest.
* Cancels any outstanding request to the server.
*/

void CancelAsyncRequest() const;
};

Talking about the implementation, the only difference that can be found from the synchronous implementation is the presence of one more parameter when calling the base class SendReceive method, the TRequestStatus. One thing to be noted is that both, synchronous and asynchronous function calls returns immediately. The difference is that in the synchronous function call, the information is obtained immediately, and in the asynchronous function call, the information is obtained later. The implementation of the requests is presented bellow.

// -----------------------------------------------------------------------------
// RExampleServerSession::AsyncRequest()
// Issues a request to the server.
// -----------------------------------------------------------------------------
//
void RExampleServerSession::AsyncRequest( TRequestStatus& aStatus )
{
SendReceive( EExampleServAsyncRequest, args, aStatus );
}
 
// -----------------------------------------------------------------------------
// RExampleServerSession::CancelAsyncRequest()
// Cancels any outstanding request to the server.
// -----------------------------------------------------------------------------
void RExampleServerSession::CancelAsyncRequest() const
{
SendReceive( EExampleServCancelAsyncRequest, TIpcArgs(NULL) );
}

Common File

The Operation Codes (also called Op codes) need to be shared among server and client. We can see the use of these codes on the implementation of the R class in the SendReceive method. They are used by both server and client as an agreement of what information is being requested by the user of this client/server implementation. This information (Op codes) is shared among client and server implementations through a common header file. An example of this file is presented next.

// DATA TYPES
// Opcodes used in message passing between client and server
enum TExampleServRqst
{
EExampleServAsyncRequest,
EExampleServCancelAsyncRequest
};
 
// Opcodes used by server to indicate which asynchronous service
// has completed
enum TExampleServRqstComplete
{
EExampleServAsyncRequestComplete = 1
};

Server side implementation

There are few changes between the implementation of a server that has only synchronous request and a server that has also asynchronous requests. The server object, derived from CServer2 class, is praticaly the same. The main difference is in the ServiceL method of the session object derived from the CSession2. Bellow follow the source file of the main methods of the session class.

void CExampleServerSession::ServiceL( const RMessage2& aMessage )
{
switch ( aMessage.Function() )
{
case EExampleServAsyncRequest: //Op code defined in common header
AsyncRequestL( aMessage ); //method that makes the asynchronous request
break;
 
case EExampleServCancelAsyncRequest: //Op code defined in common header
if ( iWaitingAsyncRequest )
{
iMessage.Complete( KErrCancel ); //Completing the request with a cancel code
iWaitingAsyncRequest = EFalse;
}
aMessage.Complete( KErrNone );
break;
 
default:
break;
}
}
/** Makes the request here. Don't call complete in the aMessage since this is a
* asynchronous request.
*/

void CExampleServerSession::AsyncRequestL( const RMessage2& aMessage )
{
//1. Test if there is also a pending request. if yes panic, only one can exist
//2. Makes the request
//3. Stores the message to complete it later, when the request is ready
iMessage = aMessage;
//4. Sets the flag
iWaitingAsyncRequest = ETrue;
}
 
/** The asynchronous request is ready in this function. Must complete the pending request
* and to signal the client the server completed the request.
*/

void CExampleServerSession::AsyncRequestCallBack( )
{
if( iWaitingAsyncRequest )
{
// 1. Obtain the information required by the user.
// 2. Signals the user about the completion of this request. This different Op code for //the answer allow the AO to differentiate among various asynchronous requests.
iMessage.Complete( EExampleServAsyncRequestComplete );
iWaitingAsyncRequest = EFalse;
}
}

The first method shows the dispatcher of the requests. It switches each request to a different operation based on the Op codes defined in the common header file. When a asynchronous request comes, the session don't complete (call Complete) message and storing it to complete later (it is an asynchronous call). The Cancel request, completes two requests, the pending request (represented by the iMessage msg), if there is any, and the wn call to the cancel, that is a message also. As the call to cancel is synchronous, it shoud be completed immediately.

The second method makes the requests, stores the message and sets a flag so the session object knows there is a pending request.

The third method deals with the completion of the pending request. It calls the Complete mehtod in the stored message and resets the flag so this session can receive more asynchronous calls.

Postconditions

This code snippet shows how to implement an asynchronous call to a Symbian server. The reader should be able to create its own asynchronous calls after reading this article.

This page was last modified on 21 June 2012, at 09:10.
85 page views in the last 30 days.
×