An introduction to Asynchronous loading
1. What's asynchronous loading(AL)?
1.1. Synchronous loading
The original loading process(synchronous loading, abbreviate to SL) is consisted of two steps:
- Load (filter): Read the document data from the disk and construct the content model in the memory.
- CreateView: Construct the view model according to the content model and display to the users.
In synchronous loading, the two steps are executed in sequence, so the users have to wait until the entire document data have been loaded into memory and formatted to display. When the document is very large, it will take a long time before the user can view the contents.
1.2. Asynchronous loading
To improve the loading performance, we make the two steps executed in two threads, so the user can view part of the document content during the document is loading, which is called ‘Asynchronous Loading’ (abbreviate to AL).
2. Key conceptual design points.
The key function of loading process is SfxObjectShell::DoLoad(). In this function, it will call function LoadOwnFormat()/ConvertFrom()/ImportFrom() which actually do the loading/filter task. To implement the asynchronous loading, we will execute these load functions in a separate thread(the load thread) so that the main thread can continue to execute the CreateView() to display the content.
- Loading thread:
The Loading thread focuses on the filter's job.
- Main thread:
Main thread will wait the loading thread's one signal to CreateView. After that, main thread will continue its main loop : to peek and dispatch message to response the user's input.
- IdleTimer in Main thread
All timers are managed by main thread, we can still regard the timer as an separate thread.
3. Asynchronous loading in framework layer.
There are 3 steps need to be done by a filter to adapt to the AL mechanism.
3.1. Register the AL enable filters by filter name.
Then the AL mechanism will automatically create a load thread for this filter when loading. Here the 'filter name' refer to the result of SfxFilter.GetName().
3.2. Create a loading thread.
In SfxObjectShell::DoLoad(), execute load functions in a separate thread(the load thread) so that the main thread can continue to execute the CreateView() to display the content.
3.3. Interact between loading thread and main thread.
In order to make the CreateView() thread ( the main thread ) be aware of the progress of the load thread, we define some state of the loading:
- LoadFinish: (set by load thread)
All the data of the document file on the disk has been loaded and the content model has been completely created.
- StopLoad: (set by main thread)
Terminate the loading process due to the user action.
- ReadyToShow: (set by load thread)
Begin to read the data of TextBody part of the document file.
- Asyncload:(set by load thread)
if current document opened through async mode
- ResumeReadElements: (set by main thread)
After the CreateView() finish, this flag is set by main thread, then load thread continue to read elements.
All the above states of the loading process can be recorded in a class SfxAsyncLoadInfo.
4. Asynchronous loading in application layer.
In the application layer, the SW module is consisting of two main parts: the content model (SwDoc including SwNode/SwFrmFmt/SdrObject) and the view model (SwRootFrm including SwFrm). Each part has a core and two types of interfaces. The cores of the SW module can been modified to make them support the AL mechanism.
4.1.1. Document content model
4.1.2. Document view model
4.1.3. Connection between CM and VM
- VM listen to CM's change
- In CM
Node listen to style's change
- In VM
Any change of lower frame will invalidate container frame and vice versa.
4.1.4. Asynchronous loading mechanism
In AL, loading thread will focus on CM, and will read elements and set attribute for the elements. Main thread will focus on VM, and will make frame, format and paint.
Note: Need further investigation.
5. Some guidelines.
- Try to filter in the 'right' sequence.
- Filter must NOT touch the view model.
- Filter must use mutex to protect the share variables between load thread and main thread.