Confirmed users
431
edits
m (→API Discussion) |
|||
(4 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
At the April 2009 Platform work week we had a meeting on making necko support requests from threads other than the main thread. Here's some design notes on what we came up with. | At the April 2009 Platform work week we had a meeting on making necko support requests from threads other than the main thread. Here's some design notes on what we came up with. | ||
== | == Goals == | ||
Goal: allow the off-main-thread HTML 5 parser to get data from the network without having to proxy the data from the main thread. | |||
Benefits: greater parallelism and reduced interference between the main thread and the parser thread (resulting in better UI responsiveness). | |||
Note that this is only useful for single-process Gecko (non-electrolysis): at least until IPDL supports sending/receiving on non-main threads, we will always need to use the main thread when multiple processes are used. | |||
== API target: sending OnDataAvailable() to other threads == | == API target: sending OnDataAvailable() to other threads == | ||
Line 23: | Line 21: | ||
1) Decision to divert data to other thread should only be made within OnStartRequest(). | 1) Decision to divert data to other thread should only be made within OnStartRequest(). | ||
There seemed to be general agreement that the decision to offload OnDataAvailable() to a different thread should only be possible within OnStartRequest(). By this point, we will have the final channel for the request (i.e. any redirects, auth requests, etc, will have been resolved). We will also have the Content-type of the request, which we will need to determine whether the data should be handled by an off-thread consumer (like the HTML parser) in the first place. | There seemed to be general agreement that the decision to offload OnDataAvailable() to a different thread should only be possible within OnStartRequest(). By this point, we will have the final channel for the request (i.e. any redirects, auth requests, etc, will have been resolved). We will also (usually!) have the Content-type of the request, which we will need to determine whether the data should be handled by an off-thread consumer (like the HTML parser) in the first place. | ||
2) How to notify other-thread listener when request is complete? | 2) How to notify other-thread listener when request is complete? | ||
Line 29: | Line 27: | ||
Two obvious ways come to mind. 1) We could also divert OnStopRequest() to the listener's thread. Or, 2) we could send an additional OnDataAvailable() with data length == 0 to signal the end of the Request. #1 is more intuitive for the programmer; #2 is more conservative, in that the main thread will still receive OnStopRequest. Since compliant nsChannels will need to be modified anyway, no one could think of a good reason not to change them to no longer expect OnStopRequest(), and so #1 is the current winner, pending discovery of any problems with not delivering OnStopReq() to the main thread. | Two obvious ways come to mind. 1) We could also divert OnStopRequest() to the listener's thread. Or, 2) we could send an additional OnDataAvailable() with data length == 0 to signal the end of the Request. #1 is more intuitive for the programmer; #2 is more conservative, in that the main thread will still receive OnStopRequest. Since compliant nsChannels will need to be modified anyway, no one could think of a good reason not to change them to no longer expect OnStopRequest(), and so #1 is the current winner, pending discovery of any problems with not delivering OnStopReq() to the main thread. | ||
3) Code would need to query both the | 3) Code would need to query both the nsIChannel and any StreamListeners chained (via nsITraceableChannel) between the nsIChannel and the target listener, to make sure they are ALL safe to be switched to a different thread for OnDataAvailable. (We could modify any relevant existing internal listeners to become safe, but since some listeners could come from extensions, we cannot guarantee all listeners will always be safe). Code must be prepared to handle the case where OnDataAvailable cannot be redirected to the desired thread. | ||
* 3/6/13: jduell: note this this would mean that any addons that use nsITraceableChannel.setNewListener() (noscript and 71 other addons according to mxr) would silently revert any channels they hook to using main-thread delivery. That sucks. And in general any JS listeners are not going to be able to handle off-main thread delivery. JST suggests we simply fail setNewListener if the new listener is JS (i.e. QI's to nsIXPCWrappedJS). Another possibility is that we add a different asyncOpenToThread() call that takes a different kind of nsIRequestObserver-like IDL, and/or which winds up triggering different (or no) on-modify-request-(offmainthread) notifications. The trick is that we were planning to allow the main vs non-main decision to be delayed until OnStartRequest and that's late in the game... Hmm... | |||
4) The API would probably consist of two new XPCOM interfaces, one for thread-retargetable Channels, one for Listeners (nsIThreadSinkableChannel and nsIThreadSinkableStreamListener?). The Channel interface would have a method (RedirectDeliveryToThread?) that would take a thread object argument, and redirect OnDataAvailable (and OnStopRequest) to that thread. The method would first check the chain of Listeners to ensure that they are all ThreadSink listeners, else the method would fail and the redirect would not happen. | 4) The API would probably consist of two new XPCOM interfaces, one for thread-retargetable Channels, one for Listeners (nsIThreadSinkableChannel and nsIThreadSinkableStreamListener?). The Channel interface would have a method (RedirectDeliveryToThread?) that would take a thread object argument, and redirect OnDataAvailable (and OnStopRequest) to that thread. The method would first check the chain of Listeners to ensure that they are all ThreadSink listeners, else the method would fail and the redirect would not happen. |