Analysis of chrome cancelablerequest class

Source: Internet
Author: User
The chrome task class introduced earlier allows code to run on a specified thread. Another common scenario is to send an asynchronous request and want to know the request processing result. At this time, although the request processing process is on another thread, the request result is returned from the thread initiated by the (caller) request, and the request can be canceled. This is very useful. For example, we often initiate an action from the interface (ui thread). This action will be executed in the worker thread and will be returned through the callback function after completion. In this case, the callback function runs on the work thread and the interface cannot be directly operated (for example, the MFC object cannot be accessed across threads ), the access interface member variables may also conflict with the UI thread (lock is required ). It is best to convert the thread and run the callback function on the UI thread to avoid the problem mentioned above. With the previous Task Foundation, we can simply imagine the basic implementation method. Remember the current thread when the request is initiated. Then, after the request is complete, send the pasttask to the saved thread to execute the callback function. Next, let's take a look at the chrome implementation code. The usage scenario is as follows. The myclass object calls the starrequest method of the frontend object. The parameters are some_input1 and some_input2, And the callback function is requestcomplete. callback_consumer _ is used to track all sent requests. Once the myclass is released, the unfinished request is automatically canceled. Class myclass {void makerequest () {frontend_service-> startrequest (some_input1, callback, callback_consumer _, newcallback (this, & myclass: requestcomplete);} void requestcomplete (INT status) {...} PRIVATE: callbackconsumer callback_consumer _;}; frontend: startrequest () first create a cancelablerequest object to save the callback function, and then record the request object request and the consumer object, finally, place a task (backend: dorequest) to the background thread to process the request. The parameter is the request object The some_input1 and some_input2 parameters passed in by lass. At this time, the function is returned, and only the result is returned asynchronously. Class frontend: Public callback {typedef callback1 <int>: Type requestcallbacktype; handle startrequest (INT some_input1, int some_input2, callbackconsumer * Consumer, requestcallbacktype * callback) {scoped_refptr <cancelablerequest <requestcallbacktype> request (New cancelablerequest <requestcallbacktype> (callback); addrequest (request, consumer); // send the parameters and the Re Quest to the backend thread. backend_thread _-> posttask (from_here, newrunnablemethod (backend _, & backend: dorequest, request, some_input1, some_input2); // The handle will have been set by addrequest. return request-> handle () ;}}; backend: The dorequest parameter includes the cancelablerequest object, call the forwardresult method to put the result back to the caller thread (that is, callback in the caller thread ). In addition, you can check whether the request has been canceled at any time before or during execution. If yes, the request is exited directly. Class backend {void dorequest (scoped_refptr <cancelablerequest <frontend: requestcallbacktype> request, int some_input1, int callback) {If (request-> canceled () return ;... do your processing... // depending on your typedefs, one of these two forms will be more // convenient: Request-> forwardresult (tuple1 <int> (return_value )); // -- or -- (inferior in this case) Request-> forwardresult (front End: requestcallbacktype: tupletype (return_value) ;}}; The cancelablerequest object is called cancelablerequestprovider, which can trace request execution. The addrequest method is used to add a request and return a handle. You can use this handle to cancel the request. When the request execution ends, it also calls requestcompleted and passes in the corresponding handle. Class cancelablerequestprovider {public: // identifies a specific request from this provider. typedef int handle; cancelablerequestprovider (); Virtual ~ Cancelablerequestprovider (); // called by the enduser of the request to cancel it. this must be called on // The same thread that originally issued the request (which is also the same // thread that wocould have got the callback if it was not canceled ). void cancelrequest (handle); protected: // adds a new request and initializes it. this is called by a derived class // to add a new reques T. the request's Init () will be called (which is why // the consumer is required. the handle to the new request is returned. handle addrequest (cancelablerequestbase * request, cancelablerequestconsumerbase * Consumer); // called by the cancelablerequest when the request has executed. it will // be removed from the list of pending requests (as opposed to canceling, // which will also set some state o N the request ). void requestcompleted (handle); cancelablerequestprovider: Inside addrequest, a handle (actually an integer number) is generated for the request, and the consumer is notified that a request and corresponding handle have been created for it. Similarly, consumber is also notified when the request is canceled or ended. At the same time, call the init method of the request to complete the final initialization, and pass in the handle and consumer objects. Cancelablerequestprovider: handle cancelablerequestprovider: addrequest (cancelablerequestbase * request, parameters * Consumer) {handle; {autolock lock (pending_request_lock _); handle = next_handle _; pending_requests _ [next_handle _] = request; ++ next_handle _;} consumer-> onrequestadded (this, handle); Request-> Init (this, handle, consumer ); return handle;} cancelablerequestcon Sumer can be used as a member variable of the class. When the object is released, cancelablerequestconsumer automatically cancels all ongoing requests to avoid crash during callback. Of course, each time you create a request, you also need to input the cancelablerequestconsumer object to bind the request and cancelablerequestconsumer. Setclientdata and getclientdata can bind a data (type: T) to each request, so that the context can be easily known when the request ends or is canceled. Class cancelablerequestconsumerbase {protected: Friend class cancelablerequestprovider; virtual ~ Cancelablerequestconsumerbase () {}// adds a new request to the list of requests that are being tracked. this // is called by the provider when a new request is created. virtual void onrequestadded (cancelablerequestprovider * provider, cancelablerequestprovider: handle) = 0; // removes the given request from the list of pending requests. called // By the cancelablerequest immediately after T He callback has executed for a // given request, and by the provider when a request is canceled. virtual void onrequestremoved (cancelablerequestprovider * provider, cancelablerequestprovider: handle) = 0 ;}; template <class T> class metadata: Public cancelablerequestconsumerbase {public: Login () {}// cancel any outstanding requests so that w E do not get called back after we // are destroyed. as these requests are removed, the providers will call us // back on onrequestremoved, which will then update the list. to iterate // successfully while the list is changing out from under us, we make a copy. virtual ~ Cancelablerequestconsumertsimple () {cancelallrequests ();} // associates some random data with a specified request. the request must be // outstanding, or it will assert. this is intended to be called immediately // after a request is issued. void setclientdata (cancelablerequestprovider * P, cancelablerequestprovider: handle h, t client_data) {pendingrequest request (p, H); dcheck (pending_requests _. Find (request )! = Pending_requests _. end (); pending_requests _ [request] = client_data;} // retrieves previusly associated data for a specified request. the request // must be outstanding, or it will assert. this is intended to be called // during processing of a callback to retrieve extra data. t getclientdata (cancelablerequestprovider * P, cancelablerequestprovider: handle h) {pendingrequest request (p, H); dchec K (pending_requests _. Find (request )! = Pending_requests _. End (); Return pending_requests _ [request];} You can also assign an initial value to all requests in a unified manner, rather than assigning values each time. Cancelablerequestconsumer is the simplest and does not contain anything. Template <class t, t initial_t> class cancelablerequestconsumert: public amount <t> {protected: Virtual t get_initial_t () const {return initial_t ;}}; typedef cancelablerequestconsumert <int, 0> cancelablerequestconsumer; from cancelablerequestbase, we can see that the messageloop of the current thread is retained during construction and will be called back later. Class cancelablerequestbase: public base: refcountedthreadsafe <cancelablerequestbase> {cancelablerequestbase (): provider _ (null), consumer _ (null), handle _ (0), canceled _ (false) {callback_thread _ = messageloop: Current ();} // tells the provider that the request is complete, which then tells the // consumer. void policycompleted () const {provider _-> requestcompleted (handle ();} Then let's take a look at the specific implementation class, and its forward The result method puts the result on the correct thread to return the result, which is actually posttask. After the callback is completed, the provider is notified that the request has ended. Template <typename CB> class cancelablerequest: Public cancelablerequestbase {public: void forwardresult (const tupletype & PARAM) {dcheck (callback _. Get (); If (! Canceled () {If (callback_thread _ = messageloop: Current () {// We Can Do synchronous callbacks when we're on the same thread. executecallback (PARAM);} else {callback_thread _-> posttask (from_here, newrunnablemethod (this, & cancelablerequest <CB >:: executecallback, Param);} PRIVATE: // executes the callback and notifies the provider and the consumer that this // request has been completed. thi S must be called on the callback_thread _. Void executecallback (const tupletype & PARAM) {If (! Canceled _) {// execute the callback. callback _-> runwithparams (PARAM); // configure y the provider that the request is complete. the provider will // your y the consumer for us. notifycompleted () ;}} Finally, let's take a look at the callback _ object, which was created by newcallback (this, & myclass: requestcomplete. Template <class T, typename arg1> typename callback1 <arg1>: type * newcallback (T * object, void (T: * method) (arg1 )) {return New callbackimpl <t, void (T: *) (arg1), tuple1 <arg1> (object, method);} template <class T, typename method, typename Params> class callbackimpl: Public callbackstorage <t, method>, public callbackrunner <Params> {public: callbackimpl (T * OBJ, method meth): callbackstorage <t, metho D> (OBJ, meth) {}virtual void runwithparams (const Params & Params) {dispatchtomethod (this-> OBJ _, this-> meth _, Params );}}; we have already mentioned dispatchtomethod when talking about tasks. Source code online http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/cancelable_request.h? Revision = 31932 http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/cancelable_request.cc? Revision = 32105.
Related Article

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.