Symbian activity objects thoroughly understand favorites

Source: Internet
Author: User

Symbian programming Summary-basics-Positive Solutions for activity objects (1)-Understanding activity objects
The use of activity objects in Symbian OS is undoubtedly the most basic, frequent, and important. What are activity objects?

When you learn a new thing, you will always compare this new thing with the thing you know to achieve quick learning. When I started to learn Symbian, I checked many Symbian books and many Symbian tutorials on the Internet all associated activity objects with multithreading. I always think of activity objects as a thread. However, after more in-depth contact, I found that it is not as I imagined.

Now, I want to assure you that the activity object has nothing to do with multithreading! Do not understand activity objects with the idea of multithreading!

The activity object can be understood as follows:

Many asynchronous functions are provided in Symbian OS. Most of these asynchronous functions are based on the "server-client" architecture. This is very different from the functions in Win32 API. For example:
In Win32, csocket: receive (Recv instead of wsarecv) is a synchronous function, and the thread is blocked at the receive until the socket receives the network stream.
Symbian OS also has a similar function, rsocket: receive, but this function is an asynchronous function, the thread will not block in the receive and will continue to execute.
How can we differentiate functions in Symbian from Synchronous functions and asynchronous functions? Simple: Check whether the function contains parameters of the trequeststatus type. If yes, the function is an asynchronous function. For example, the rsocket: receive function is prototype:
Import_c void Recv (tdes8 & adesc, tuint flags, trequeststatus & AStatus); The AStatus parameter is a status bit and the initial value is erequestpending (the value is 1 ), it indicates whether the operation requested by the user has been completed. For example, if we call the asynchronous function rsocket: receive to request to receive network streams, the receive function will return directly. After the process of "receiving" a network stream is completed, the AStatus changes to eactive. Therefore, we only need to monitor whether the AStatus is not erequestpending and whether the "receiving" is complete.
We can use the following pseudo code to complete the above operations:

Trequeststatus status (krequestpending); rsocket: receive (adesc, flags, status); For (;) {If (status! = Krequestpending) break;} // here we have completed synchronization similar to csocket: receive through rsocket: receive. We do not recommend that you use the above methods for Symbian OS, we recommend that you use the asynchronous method instead of force synchronization. The active object is used to help us do this. The activity object system helps us monitor the value of AStatus, As long as AStatus! = Erequestpending, he will notify us by event, telling us that "the socket has been received, you can get the data !", The activity object does this.
To sum up, there is an "activity scheduler" in the system. We create an "activity object ao1" and bind this object to an asynchronous function in a system, register the activity object to the "activity scheduler". The "activity scheduler" waits for the "completion" message returned by the asynchronous function. After receiving the completion message, the scheduler traverses the registered activity object. If the status is found! = Krequestpending: Find the "Active Object ao1" corresponding to the status, call the runl method, and notify us that the asynchronous function has been executed in Event Mode.
Symbian programming Summary-basics-positive solution of activity objects (2)-use activity objects
We have a general understanding of the basic concepts of activity objects. To use the activity object mechanism, we need to use activity objects, activity schedulers, and asynchronous functions. To use an asynchronous function, you must follow the procedure of application> activity Object> activity scheduler> asynchronous function. Next, we will start to use the activity objects.

1. Create an activity Scheduler

We know that the active scheduler serves as a bridge between an application and an asynchronous function. The application uses the active object to intercept the "completed" message returned by the asynchronous function through the active scheduler, and notify the application as an event.

Using carbide C ++ 1.3, the console program generated by the template wizard automatically generates code for creating the activity Scheduler for us:

Cactivescheduler * schedave = new (eleave) cactivescheduler (); cactivescheduler: Install (Scheduler); cactivescheduler: After the install () method is called, the internal code will assign the scheduler pointer to the static pointer inside the cactivescheduler class, and the subsequent code will be able to conveniently use the static method of the cactivescheduler class, such:

Import_c static void add (cactive * aactive); import_c static void start (); import_c static void stop (); add () method: add the activity object to the activity Scheduler for registration, for use
Start () method: Start the activity scheduler, which starts to wait cyclically for the notification message returned by the asynchronous function.
Stop () method: stop the activity Scheduler
2. Create activity objects

1. The created activity object must be derived from the cactive class, And the cactive class has prepared the istatus member variable for us:

Public: trequeststatus istatus; private: tbool iactive; another member variable, iactive, identifies the activity object that has requested an asynchronous function, such:

Rtimer: After (istatus, 1000000); setactive () method for the base class cactive method, in fact, iactive = etrue ;, used to identify that an active object has called an asynchronous function. Therefore, as long as an asynchronous function is called, the code that calls the asynchronous function should be followed by the code that calls the setactive () method.

2. Two virtual methods must be inherited:

Virtual void docancel () = 0; virtual void runl () = 0; runl Method: After the activity scheduler receives the "finish" message returned by the asynchronous function, traverse all the activity objects registered in the activity object. If the iactive of the activity object is etrue and istatus! = Krequestpending: Call the runl method of the activity object and set iactive to efalse to prevent the activity object from being called in the next round-robin.
Here, the name "runl" may lead to ambiguity for many people. When I first came into contact, I always thought it was similar to the run method of the runnable interface in j21. In fact, it is more appropriate to change "runl" to "policyrequestcompletel" here.

Again, when an asynchronous function is called, The trequeststatus and status parameters are passed in reference mode, for example:

Import_c void after (trequeststatus & AStatus, ttimeintervalmicroseconds32 aninterval );
So the asynchronous function can change the real parameter of status, that is, change the class member istatus of the activity object.
Docancel () method: The base class cactive has the cancel () method for canceling asynchronous functions. After cancel () is called, the activity object will pass docancel () the method notifies the application to cancel the method, such as deleting objects and revoking pointers. Note: To terminate an activity object in an application, use the cancel () method instead of the docancel () method.
3. constructors with priority for activity objects:

The prototype of the base class cactive constructor is as follows:

Protected: import_c cactive (tint priority ority); a priority enumeration value is input here. The enumerated value is as follows:

/** Defines standard priorities for active objects. */Enum tpriority {/** a low priority, useful for active Objects representing background processing. */epriorityidle =-100,/** a priority higher than epriorityidle but lower than eprioritystandard. */eprioritylow =-20,/** most active objects will have this priority. */eprioritystandard = 0,/** a priority higher than eprioritystandard; useful for Ctive objects handling user input. */epriorityuserinput = 10,/** a priority higher than epriorityuserinput. */epriorityhigh = 20,}; when the cactivesched: add method is called to register an activity object, the activity scheduler will sort the activity object by its priority, insert or add to the activity object set. When multiple asynchronous function messages are returned at the same time (multiple istatus are not krequestpending at the same time ), when an activity object scheduler training set, it always finds the activity object with a higher priority and calls its runl method.

However, in general, eprioritystandard is passed in the constructor.

3. pseudocode of the Start method of the activity Scheduler

Through the above two analyses, we can simulate the cactivescheduler: Start method:

Void cactivescheduler: Start () {for (;) {// suspend the thread until the asynchronous function message is returned. // note: the active scheduler and application are not in the same thread, therefore, the application will not block user: waitforanyrequest (); // If the asynchronous function and the main program are in different threads, rthread: waitforanyrequest (); // when a message is returned, the thread will wake up. // in descending order of priority, the thread will detect every active object in the scheduler set (;;) {// call the first completed activity object event processing function, if (activeobject-> isactive () & activeobject-> istatus! = Krequestpending) {// locate an activity object that is ready to process the event // reset the iactive status to indicate that it is no longer in the active status activeobject-> iactive = efalse; // call the event processing function trapd (ERR, activeobject-> runl () of the activity object in the trap; If (Err! = Kerrnone) {// if an exception occurs, call the runerror method err = activeobject-> runerror (); If (Err! = Kerrnone) {error (ERR) ;}} break ;}}}4. Example of using an activity object

Click here to download the source code

In this example, a console program is started and the rtimer timer of the asynchronous service class is used to display the accumulated number on the screen every second. The effect is as follows:

 

V. Summary

In this section, we have a basic understanding of the working mechanism and workflow of the activity scheduler and activity objects. In the next section, we will go deep into the activity objects, understand its working principles and further deepen its understanding of the activity objects.

Symbian programming Summary-basics-positive solution of activity objects (3)-working principle of activity objects
We already know how to create and use activity objects. Everyone has a certain understanding of the creation and use of activity objects. In this section, I will go deep into the activity object mechanism, which is divided into two parts: "activity object Workflow" and "signal loss error", to analyze the working principle of the activity object.

I. workflow of activity targets

First, we use the sequence diagram to illustrate the process of creating and calling between applications, activity objects, activity schedulers, and asynchronous function servers:

 

The following describes how to use the code for each step (Click here to download the code:

1. Create and install the active scheduler:

Cactivescheduler * schedstack = new (eleave) cactiveschedstack (); cleanupstack: pushl (schedhl); cactivescheduler: Install (schedhl ); if you have created an application based on the GUI application framework and the framework has already created and installed an active scheduler for us, we can directly use a series of methods of cactivescheduler.

2. Create activity objects

Imyao = cmyactiveobject: newl (* console); The cmyactiveobject class created here is the activity object inherited from the cactive class.

3. Add the activity object to the activity scheduler.

Void cmyactiveobject: constructl (){.... cactivescheduler: add (this); // Add to scheduler, when an activity object is created through the "two-stage constructor", its pointer has been added to the activity scheduler.

4. startl

Startl calls the asynchronous Function Method for the activity object requested by the application. You can rename this method as needed:

Void cmyactiveobject: startl (ttimeintervalmicroseconds32 adelay) {cancel (); // cancel the asynchronous function request istatus = krequestpending; itimer. after (istatus, adelay); // call the asynchronous function setactive () here (); // set the member variable iactive = etrue} because you cannot ensure that the startl method is not re-called when the user waits for the return of the asynchronous function call, the startl method first calls cancel () at the entry point of the startl method () method to cancel the asynchronous request. Otherwise, the "Lost signal" error may occur.

5. istatus = krequestpending

In the startl method of the above Code, before calling an asynchronous function, you must first set istatus to krequestpending to enable the active scheduler to perform time-over-time matching.

6. Request asynchronous functions and send istatus

In the startl method, itimer. After (istatus, adelay); this line of code passes a reference to the member variable and calls the asynchronous function itimer. After.

7. setactive

Call the setactive method of the base class cactive to set the iactive to etrue in the method so that the active scheduler can match the time and duration.

8. Start the activity Scheduler

Cactivesched: Start (); 10. Search for the corresponding activity object.

We have analyzed and restored the pseudo code of the cactivescheduler: Start () method in the previous section. This code block traverses all the activity objects registered with the scheduler in another thread, check that the object's istatus is not krequestpending and the iactive is etrue. After the asynchronous function server completes the request, it will change the real parameter of istatus so that it is not equal to krequestpending, in addition, the iactive value of the activity object is changed to etrue immediately after the asynchronous function is returned, so the activity Scheduler only needs to judge istatus! = Krequestpending & iactive = etrue, you can know which activity object requested the asynchronous service has been completed.

9. waitforanyrequest () waits for the asynchronous function to return a notification. 11. requestcomplete () and changes the value of istatus.

When the asynchronous service has completed the requested work, it will use User: requestcomplete () to send a notification, the activity scheduler will use User: waitforanyrequest () or rthread :: waitforanyrequest () receives this notification, and then traverses the activity object that matches the conditions it is registered with (8th underlines ).

12. Call the runl Method

If the activity object corresponding to the asynchronous function is found, the runl method of the activity object is called, and the runl method runs in the trap macro. If the runl method throws an exception, the activity scheduler automatically calls the runerror method of the activity object. Therefore, you do not need to write exception capture code in runl in most cases.

After the runl method is called for an activity object, set the iactive value of the activity object to efalse so that the processed activity object can be skipped the next time the collection is traversed.

If the activity object corresponding to the asynchronous function is not found, the activity scheduler throws a "lost signal" exception.

13. cactivescheduler: Stop ()

Stop the event scheduler and stop monitoring signals returned by asynchronous functions.

Ii. Dedicated error of activity objects-"Lost signal"

From the above analysis, we know that the activity scheduler intercepts the messages returned by the asynchronous function, and then traverses the activity object set to find the corresponding activity object call. If not, it throws a "signal loss" exception. You can use either of the following methods to "cannot find the activity object:

The activity object is not registered to the activity scheduler at all: the cactivescheduler: add method is not called to register the activity object.
Unable to meet the istatus standard used by the activity scheduler to search for activity objects! = Krequestpending & iactive = etrue: After the asynchronous function is called, The setactive () method is not called to set the value of iactive to etrue; or the istatus is sent to two asynchronous functions at the same time, when the second asynchronous function returns, the iactive value of the current active object is efalse, And the Scheduler cannot find the corresponding activity object.
Iii. Summary

In this section, we learned the internal working principle of the activity object and gained a deeper understanding of the activity object processing mechanism. In the next section, we will learn how to synchronously call existing asynchronous functions.

Symbian programming Summary-basics-positive solutions to active objects (4)-synchronous calls to asynchronous Functions
We have a deep understanding of the working principle and running mechanism of the activity object, the activity scheduler, And the asynchronous function server. We must be familiar with the use of the mechanism and architecture of the activity object. But do you think it is troublesome to use Asynchronous functions? Do I have to use an active object to call an asynchronous function in asynchronous mode? This section will solve this problem: Synchronous use of asynchronous functions.
 

1. Use the cactiveschedulerwait class

In the previous article "Symbian programming Summary-ui-open JPEG/GIF/PNG images", we have seen how to use the cactiveschedulerwait class. I will introduce it in detail here.

Many beginners mix the cactiveschedit and cactiveschedulerwait classes at the beginning. cactivescheduler is the scheduler of the activity object, while cactiveschedulerwait can be simply understood as a scheduler of the current thread:

Thread blocking when cactiveschedulerwait: Start () method is called;
When the cactiveschedulerwait: asyncstop () method is called, the request stops blocking the thread.
Therefore, without modifying the code of the original active object, simply add "cactiveschedulerwait: Start ()" after the asynchronous function call method ()", add "cactiveschedulerwait: ansycstop ()" to the beginning of the runl method of the activity object.

For the console application described in the previous tutorial, we can modify the following methods (the underline is the modification part:

 

Click here to download the source code

 

Cactiveschedulerwait * iwait;

 

Void cmyactiveobject: constructl ()

{

User: leaveiferror (itimer. createlocal (); // initialize Timer

Cactivescheduler: add (this); // Add to Scheduler

 

Iwait = new (eleave) cactiveschedulerwait;

}

 

Cmyactiveobject ::~ Cmyactiveobject ()

{

Cancel (); // cancel any request, if outstanding

Itimer. Close (); // destroy the rtimer object

// Delete instance variables if any

 

If (iwait-> isstarted ())

{

Iwait-> asyncstop ();

}

 

Delete iwait;

Iwait = NULL;

}

 

Void cmyactiveobject: startl (ttimeintervalmicroseconds32 adelay)

{

Cancel (); // cancel any request, just to be sure

 

Itimer. After (istatus, adelay); // set for later

Setactive (); // tell scheduler a request is active

 

Iwait-> Start (); // 1st points

}

 

Void cmyactiveobject: runl ()

{

Iwait-> asyncstop (); // 2nd o'clock

 

Tbuf <50> outputstr;

Outputstr. appendnum (icount );

Iconsole. Write (outputstr );

Iconsole. Write (_ L ("/N "));

Icount ++;

}

 

Precautions for using cactiveschedulerwait:

Cactiveschedulerwait must be used in conjunction with the activity object, and only the one described in the above code is used;
The start method and asyncstop method must be paired;
When the program exits, check whether cactiveschedulerwait is in the isstarted () status. If yes, call the asyncstop method. Otherwise, the program cannot exit normally;
The cactivescheduler class has its own internal static pointer, and all provided static methods call internal static pointers. The cactiveschedulerwait class does not have internal static pointers, and the method is not static. We must manage the global pointers of the cactiveschedulerwait class by ourselves. At this point, the program should be well designed.
 

Ii. Use the user: waitforrequest Method

If you do not want to use activity objects or cactiveschedulerwait that is difficult to manage, you can use the user: waitforrequest method. The following is a prototype of user: waitforrequest:

Import_c static void waitforrequest (trequeststatus & AStatus );

This method will wait for the semaphore returned by the asynchronous function server and then match the AStatus parameter. If the received signal matches the AStatus parameter one by one, skip the blocking and enter the next line of code. Otherwise, the blocking thread continues until the signal corresponding to the AStatus is returned.

User: waitforrequest also has an overloaded method, which can monitor notifications of two signals:

Import_c static void waitforrequest (trequeststatus & astatus1, trequeststatus & astatus2 );

With user: waitforrequest, It is very convenient to use Asynchronous functions. We do not need to create activity objects or create the member variable trequeststatus, you only need to declare partial trequeststatus and local asynchronous function classes. After the asynchronous function is called, Add User: waitforrequest (Status) to block the thread in user :: at waitforrequest, wait until the asynchronous function corresponding to status is processed completely.

Local_c void dotestl ()

{

Rtimer timer;

Cleanupclosepushl (timer );

User: leaveiferror (timer. createlocal ());

Trequeststatus status (krequestpending );

// Call the Asynchronous Method and pass the status

Timer. After (status, 1000000 );

// Wait for the semaphore corresponding to the status. Here, the user: waitforrequest method is used to simulate Asynchronous Method calls into synchronization.

User: waitforrequest (Status );

Cleanupstack: Pop (& timer );

}

 

Local_c void mainl ()

{

Tint n = 0;

Tbuf <10> STR;

_ Partition (knewline, "/N ");

Forever

{

Dotestl ();

Str. Num (N );

N ++;

Console-> write (STR );

Console-> write (knewline );

}

}

 

Iii. Problems with using the user: waitforrequest Method

User: waitforrequest sometimes does not run normally, such as: cimagedecoder: Convert method:

Import_c virtual void convert (trequeststatus * arequeststatus, cfbsbitmap & adestination, cfbsbitmap & adestinationmask, tint aframenumber = 0 );

The last parameter must be eoptionalwaysthread, and user: waitforrequest can be executed normally. In my opinion, cimagedecoder :: if the eoptionalwaysthread parameter is not added to convert, it is implemented using a "long-term task" (which will be described in the next section. Therefore, the cimagedecoder: Convert method should be called as follows:

Trequeststatus status (krequestpending );

Cimagedecoder * decoder = cimagedecoder: filenewl (IFS, afilename, kmimetype, cimagedecoder: eoptionalwaysthread );

Decoder-> convert (& status, abitmap );

User: waitforrequest (Status );

Delete decoder;

Decoder = NULL;

 

Iv. Summary

This article describes how to use Asynchronous functions synchronously. In fact, there is also an asynchronous function synchronization method in early Symbian programming, that is, after the asynchronous function call, use the cactivescheduler: Start () method to nest the activity scheduler. However, this method has been replaced by cactiveschedulerwait after Symbian 7.0 and will not be introduced here.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.