]>
Commit | Line | Data |
---|---|---|
9a1b46cc | 1 | /* |
5b74111a | 2 | * Copyright (C) 1996-2018 The Squid Software Foundation and contributors |
9a1b46cc AJ |
3 | * |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
3889d00c AR |
9 | /** |
10 | \defgroup AsyncJobs Asynchronous Jobs | |
11 | \ingroup Components | |
12 | ||
13 | \section Terminology Terminology | |
14 | ||
15 | - \b Job: an AsyncJob object. | |
16 | - \b Creator: the code creating the job. Usually the Initiator. | |
4299f876 | 17 | - \b Start: the act of calling AsyncJob::Start with a job pointer. |
3889d00c AR |
18 | - \b Initiator: the code starting the job. Usually the Creator. |
19 | ||
20 | \section Life Typical life cycle | |
21 | ||
22 | -# Creator creates and initializes a job. | |
4299f876 AR |
23 | -# If Initiator expects to communicate with the job after start, |
24 | then it stores the job pointer | |
25 | -# Initiator starts the job by calling AsyncJob::Start. | |
3889d00c AR |
26 | -# The job's start() method is called. The method usually schedules |
27 | some I/O or registers to receive some other callbacks. | |
28 | -# The job runs and does what it is supposed to do. This usually involves | |
29 | scheduling I/O, setting timeouts, receiving Comm or Store callbacks, and | |
30 | then notifying Initiator of the final result. | |
31 | -# The job reaches its goal or encounters an error condition. | |
32 | -# The swanSong() method is called. | |
33 | -# The job object is destroyed. | |
34 | ||
35 | ||
36 | If you want to do something before starting the job, do it in the constructor | |
37 | or some custom method that the job creator will call _before_ calling | |
4299f876 | 38 | AsyncJob::Start(): |
3889d00c | 39 | |
829030b5 | 40 | std::unique_ptr<MyJob> job(new MyJob(...)); // sync/blocking |
3889d00c AR |
41 | job->prepare(...); // sync/blocking |
42 | job->prepareSomethingElse(...); // sync/blocking | |
43 | AsyncStart(job.release()); // non-blocking | |
44 | ||
45 | If you do not need complex preparations, it is better to do this instead: | |
46 | ||
4299f876 | 47 | AsyncJob::Start(new MyJob(...)); |
3889d00c AR |
48 | |
49 | Keep in mind that you have no async debugging, cleanup, and protections until | |
4299f876 | 50 | you call AsyncJob::Start with a job pointer. |
3889d00c AR |
51 | |
52 | ||
53 | \section Rules Basic rules | |
54 | ||
4299f876 AR |
55 | - To start a job, use AsyncJob::Start. |
56 | Do not start the same job more than once. | |
60ce3189 AR |
57 | |
58 | - Never call start() directly. Treat this method as main() in C/C++. | |
3889d00c AR |
59 | |
60 | - Never call swanSong() directly. If you are outside an AsyncCall | |
61 | handler, and want to kill the job, then call deleteThis(). If you are | |
62 | inside an AsyncCall handler, you have several options for job termination: | |
63 | ||
64 | -# Call mustStop(reason) for errors that require further processing in | |
65 | the same method(s) chain, below/after the mustStop() call. Efficient. | |
66 | ||
67 | -# Throw (via Must or directly) for errors that do not require further | |
68 | processing in the same method(s) chain, below/after the mustStop() call. | |
69 | Inefficient but simple and allows exiting from deeply nested method calls. | |
70 | ||
71 | -# Otherwise, just finish the call. Your doneAll() should return true | |
72 | and the job will terminate successfully. | |
73 | ||
74 | swanSong() will be called automatically in all of these cases when the | |
75 | job is being terminated. It is a general cleanup method, like a | |
76 | destructor. The only difference is that a destructor must not throw. | |
77 | ||
78 | ||
79 | - Do not assume swanSong() is called in some perfectly nice job state. | |
80 | The job code or the code it calls may throw at any time after start() | |
81 | was called. The entry may be gone, the Abort may have been called, the | |
82 | fd may have been closed, etc. | |
83 | ||
84 | ||
85 | - Never call deleteThis() in contexts other than those documented above. | |
86 | It is a hack for the old-style code. You can avoid it and other | |
87 | old-style special precautions altogether if you convert sync calls into | |
88 | async ones. This is especially easy for old-style calls that have only | |
89 | one parameter ("data") or two simple parameters. | |
90 | ||
91 | ||
92 | - In swanSong, always call swanSong() of the parent, after you are done | |
93 | cleaning up your job. It does not matter whether the [current] parent | |
94 | swanSong() does nothing. | |
95 | ||
3071d963 AR |
96 | - You must implement start() and doneAll() methods. These methods may be |
97 | marked as pure virtual in future releases. | |
98 | ||
99 | - In doneAll(), always call doneAll() of the parent. If the parent is not | |
100 | done, you are not done. It does not matter whether the [current] parent | |
101 | doneAll() always returns true. | |
3889d00c AR |
102 | |
103 | - If a job does not have a doneAll() method implemented, it is probably | |
104 | buggy. Any job must know what it wants to accomplish. Please note that | |
105 | doneAll() is for defining the successful termination goal/condition. | |
106 | Errors are handled by mustStop() or throw, as discussed above. | |
107 | ||
108 | Similarly, if your doneAll() implementation looks like "return isDone;", | |
109 | you are doing it wrong. Compute the condition directly rather than | |
110 | expecting various job methods to maintain some isDone variable correctly. | |
111 | ||
112 | ||
113 | - If a job does Comm I/O, it probably needs a Comm closing handler. | |
114 | ||
115 | - If a job stores a StoreEntry, it probably needs an entry Abort handler. | |
116 | ||
117 | - Ask yourself what the user will see/experience when the job throws, | |
118 | which could happen as early as in the start() method (technically, it | |
119 | can happen even earlier, during job creation and initialization). Are you | |
120 | OK with that? | |
121 | ||
122 | ||
123 | */ |