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

0001 ## Hello World! with queueing multiple jobs
0002 
0003 The first example showed nothing that would have required multiple
0004 threads to print _Hello World!_, and also did not mention anything
0005 about at what time jobs get deleted. Object life span is of course a
0006 crucial questions when programming in C++. So of what type is the 
0007 value that is returned by `make_job` in the first example? 
0008 
0009 The returned object is of type `JobPointer`, which is a
0010 `QSharedPointer` to `Job`. When `make_job` is executed, it allocates a
0011 `Job` that will later execute the C++ lambda function, and then embeds
0012 it into a shared pointer. Shared pointers count references to the
0013 object pointer they represent, and delete the object when the
0014 last reference to it is destroyed. In a way, they are single-object
0015 garbage collectors. In the example, the new job is immediately handed
0016 over to the queue stream, and no reference to it is kept by
0017 `main()`. This approach is often called "fire-and-forget jobs". 
0018 The queue will process the job and forget about it when it
0019 has been completed. It will then definitely get deleted automatically,
0020 even though the programmer does not necessarily know exactly when. It
0021 could happen (and in the case of ThreadWeaver jobs commonly does)
0022 deeply in the bowels of Qt event handling when the last event holding
0023 a reference to the job gets destroyed. The gist of it is that from the
0024 programmers point of view, it is not necessary to keep a reference to
0025 a job and delete it later. With that in mind, no further memory
0026 management is required in the HelloWorld example, and the program is
0027 complete.
0028 
0029 Fire-and-forget jobs are not always the right tool. For example, if
0030 a job is retrieving and parsing some data, the application needs to
0031 access the data once the job is complete. For that, the programmer
0032 could implement a custom job class.
0033 
0034 @@snippet(HelloWorldRaw/HelloWorldRaw.cpp,sample-helloworldraw-class,cpp)
0035 
0036 The `QDebugJob` class simply prints a message to `qDebug()` when it is
0037 executed. To implement such a custom job class, it is inherited from
0038 `ThreadWeaver::Job`. By overloading the `run()` method, the "payload",
0039 the operation performed by the job, is being defined. The parameters
0040 to the run method are the job as the queue sees it, and the thread
0041 that is executing the job. The first parameter may be surprising. The
0042 reason that there may be a difference between the job that the queue
0043 sees and `this` is that jobs may be decorated, that means wrapped in
0044 something else that waddles and quacks like a job, before being
0045 queued. How this works will be explained later, what is important to
0046 keep in mind for now is not to assume to always find `this` in the
0047 queue.
0048 
0049 @@snippet(HelloWorldRaw/HelloWorldRaw.cpp,sample-helloworldraw-main,cpp)
0050 
0051 This time, in the `main()` function, four jobs in total will be
0052 allocated. Two of them as local variables (j1 and j2), one (j3)
0053 dynamically and saved in a `JobPointer`, and finally j4 is allocated
0054 on the heap with `new`. 
0055 All of them are then queued up for execution in one single
0056 command. Wait, what? Right. Local variables, job pointers and raw
0057 pointers are queued the same way and may be mixed and matched using
0058 the stream operators. When a local variable is queued, a special
0059 shared pointer will be used to hold it which does not delete the
0060 object when the reference count reaches zero. A `JobPointer` is simply
0061 a shared pointer. A raw pointer will be considered a new object and
0062 automatically wrapped in a shared pointer and deleted when it goes out
0063 of scope. Even though three different kinds of objects are handed over
0064 to the stream, in all three cases the programmer does not need to put
0065 special consideration into memory management and the object life
0066 cycles. 
0067 
0068 Now before executing the program, pause for a minute and think about
0069 what you expect it to print. 
0070 
0071 ~~~~
0072 World!
0073 This is...
0074 Hello
0075 ThreadWeaver!
0076 ~~~~
0077 
0078 Four jobs are being queued all at the same time, that is when the
0079 `stream()` statement closes. Assuming there is more than one worker
0080 thread, the order of execution of the jobs is undefined. The strings
0081 will be printed in arbitrary order. In case this comes as a surprise,
0082 it is important to keep in mind that by default, there is no relation
0083 between jobs that defines their execution order. This behaviour is in
0084 line with how thread pools normally work. In ThreadWeaver, there are
0085 ways to influence the order of execution by declaring dependencies
0086 between them or aggregating multiple jobs into collections or
0087 sequences. More on that later. 
0088 
0089 Before the end of `main()`, the application will block and wait for
0090 the queue to finish all jobs. This was not needed in the first
0091 HelloWorld example, so why is it necessary here? As explained there,
0092 the global queue will be destroyed when the `QCoreApplication` object
0093 is destroyed. If `main()` would exit before j1 and j2 have been
0094 executed, it's local variables including j1 and j2 would be
0095 destroyed. In the destructor of `QCoreApplication` the queue would
0096 wait to finish all jobs, and try to execute j1 and j2, which have
0097 already been destructed. Mayhem would ensue. When using local
0098 variables as jobs, make sure that they have been completed before
0099 destroying them. The `finish()` method of the queue guarantees that it
0100 no more holds references to any jobs that have been executed.
0101