Warning, /frameworks/threadweaver/examples/HelloInternet.in.md is written in an unsupported language. File is not indexed.

0001 ## Doing things in a Sequence
0002 
0003 The time when an application starts, especially one that needs
0004 to load quite some data, is usually one of contention. Translations
0005 need to be loaded and resources like icons and images initialized. As
0006 the application matures, more and more of such tasks are piled on to
0007 it. It will have to check for updates from a server, and load a
0008 greeting of the day to the user. Eventually, the application will
0009 take ages to load, users will tweet about how they are making coffee
0010 while it comes up, and the programmers will start to find a solution. 
0011 
0012 The application will come up a lot faster if it defers as many
0013 tasks as possible while it creates and shows the user interface, and
0014 also takes as many as possible of the startup tasks of an application
0015 off the main thread. The main thread is the one that runs when
0016 `main()` is entered, and in which the user interface lives. Everything
0017 that slows down or intermittendly blocks the main thread may be
0018 experienced by the user as the user interface being sluggish or
0019 hung. This is a common use case where concurrent programming can
0020 help. 
0021 
0022 But ... this is also one of the examples where standard thread pools
0023 fail. The startup tasks commonly need to be done in a certain order
0024 and are of different priority, and also should not be all tackled by
0025 the application process at the same time. 
0026 For example, the applications icons and translations may be needed
0027 first and urgently, where the information on available updates can
0028 still be processed a couple of seconds later. There are ways around
0029 this that are rather cumbersome, like using timers to queue up some
0030 tasks later or using chains of functions that queue up new tasks when
0031 one group is done. The following example will illustrate some aspects
0032 of how ThreadWeaver comes with the necessary tools to specify the
0033 order of tasks, on application startup and otherwise. The following
0034 `main()`[^4] function allocates a main widget and an object of type
0035 `ViewController` that takes care of the startup tasks.
0036 
0037 @@snippet(HelloInternet/main.cpp,hellointernet-main,cpp)
0038 
0039 The example application shows an image that it eventually loads from
0040 the network, and a caption for it. In the constructor of
0041 `ViewController`, the startup operations need to be kicked off. The
0042 operations in this example are 
0043 
0044 * to load a placeholder image that is shown while the application
0045   loads the image and caption from the network,
0046 * to load the post that contains the caption, but only the URL of the
0047   image to show,
0048 * and then, once the image URL is known, to finally load the image
0049   from the network and display it.
0050 
0051 The application's user interface will be shown right away, even before
0052 step 1 has been completed. Let's assume that the three steps need to
0053 be done in order, not in parallel.
0054 
0055 The important aspect is to do as little as possible in the
0056 constructor, considering that it is called from the main
0057 thread. Creating jobs and queueing them is not expensive however, so
0058 the constructor focuses on that and then returns.
0059 
0060 @@snippet(HelloInternet/ViewController.cpp,hellointernet-sequence,cpp)
0061 
0062 Remember the assumption that the three startup steps have to be
0063 performed in order. The new thing here is that instead of queueing
0064 individual jobs, the constructor creates a `Sequence`, and then adds
0065 jobs to that. A sequence has the jobs performed by the thread pool in
0066 the order they have been added to it. The jobs each simply call a
0067 member function of `ViewController` when being
0068 executed. ThreadWeaver's execution logic guarantees that the next job
0069 is only executed after the previous one has been finished. Because of
0070 that, only one of the member functions will be called at a time, and
0071 they will be called in the order the jobs have been added to the
0072 sequence. 
0073 
0074 Since only one of the member functions will be called at a time, there
0075 is no need for further synchronization of access to the member
0076 variables of `ViewController`. This raises the question of how the
0077 controller submits new captions, statuses and images to the main
0078 widget. It would be a mistake to simply call member functions of the
0079 main widget from the methods of `ViewController`, since these are
0080 executed from a worker thread. The controller submits update by using
0081 Qt signals that are connected to corresponding slots in the main
0082 widget. The parameters of the signals are passed by value, not by
0083 reference or pointers, making use of the implicit sharing built into
0084 Qt to avoid copying. This approach relies on the fact that the
0085 reference counting of Qt's implicit-sharing mechanism is thread safe. 
0086 
0087 @@snippet(HelloInternet/ViewController.cpp,hellointernet-loadresource,cpp)
0088 
0089 The method `loadPlaceholderFromResource()` implements the first step,
0090 to load an image from a resource that acts as a place holder until the
0091 real images has been downloaded. It cheats to appear busy by first
0092 sleeping for a short while. While it does so, the user interface will
0093 already appear to the user, with a blank background. It then emits a
0094 signal to make the main widget show a status message that indicates
0095 the program is downloading the post. 
0096 
0097 The method is called from the worker thread that executes the job, not
0098 the main thread. When the signal is emitted, Qt notices that sender and
0099 receiver are not in the same thread at the time, and sends the signal
0100 asynchronously. The receiver will not be called from the thread
0101 executing `loadPlaceholderFromResource()`, instead it will be invoked
0102 from the event loop of the main thread. That means there is no shared
0103 data between the controller and the main widget for processing the
0104 signal, and no further serialization of access to the QString variable
0105 holding the status text is necessary.
0106 
0107 Once the method returns and the job executing it completes, the next
0108 job of the sequence will be unlocked. This causes the method
0109 `loadPostFromTumblr()` to be executed by a worker thread. This method
0110 illustrates the convenience built into Qt to process data present in
0111 Open Standard formats (XML, in this case), even though this won't be
0112 discussed here in detail.[^5] If processing the data turns out to be
0113 expensive, the user interface will not be blocked by it, since it
0114 is not performed by the main thread.
0115 
0116 @@snippet(HelloInternet/ViewController.cpp,hellointernet-loadpost,cpp)
0117 
0118 In case an error occurs, the method invokes another method called
0119 `error()`. `error()` indicates the problem to the user by setting a
0120 status messages in the main widget. But it also apparently aborts the
0121 execution of the sequence, as the code assumes it does not continue
0122 after calling it.
0123 
0124 @@snippet(HelloInternet/ViewController.cpp,hellointernet-error,cpp)
0125 
0126 `error()` shows a different placeholder image, and emits the status
0127 message to the main widget. It then raises an exception of type
0128 `ThreadWeaver::JobFailed`, which will be caught by the worker thread
0129 executing the current job. The worker thread sets the status of
0130 the job to a failed state. Specific to sequences (because only
0131 sequences know the order of the execution of their elements), this
0132 will cause the sequence to abort the execution of it's remaining
0133 elements. Raising the exception will abort the processing of the job,
0134 but not terminate the worker thread. Leaking any other type of
0135 exception than `ThreadWeaver::Exception` from the `run()` method of a
0136 job is considered a runtime error. The exception will not be caught by
0137 the worker thread, and the application will terminate. 
0138 
0139 The example illustrates the steps necessary to perform concurrent
0140 operations in a certain order. It also shows how a specialized
0141 object (`ViewController`, in this case) can handle the data shared
0142 between the sequential operations, how to submit data and status
0143 information back to the user interface, and how to signal error
0144 conditions from job execution.
0145 
0146 ![Hello Internet](screenshots/HelloInternet.png "The HelloInternet
0147  example, after downloading the post") 
0148 
0149 [^4]: See `examples/HelloInternet` in the ThreadWeaver repository.
0150 [^5]: The example uses the
0151 [Tumblr API version 1](https://www.tumblr.com/docs/en/api/v1).