]> git.ipfire.org Git - thirdparty/squid.git/blame - src/base/AsyncJobCalls.h
Source Format Enforcement (#1234)
[thirdparty/squid.git] / src / base / AsyncJobCalls.h
CommitLineData
bbc27441 1/*
b8ae064d 2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
bbc27441
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
0edbef7e 9#ifndef SQUID_ASYNCJOBCALLS_H
10#define SQUID_ASYNCJOBCALLS_H
11
d1e045c3 12#include "base/AsyncJob.h"
4299f876 13#include "base/CbcPointer.h"
675b8408 14#include "debug/Stream.h"
4299f876
AR
15
16/**
17 \ingroup AsyncJobAPI
18 * This is a base class for all job call dialers. It does all the job
19 * dialing logic (debugging, handling exceptions, etc.) except for calling
20 * the job method. The latter requires knowing the number and type of method
21 * parameters. Thus, we add a dial() virtual method that the MemFunT templates
22 * below implement for us, calling the job's method with the right params.
23 */
24template <class Job>
25class JobDialer: public CallDialer
26{
27public:
28 typedef Job DestClass;
29 typedef CbcPointer<Job> JobPointer;
30
31 JobDialer(const JobPointer &aJob);
32 JobDialer(const JobDialer &d);
33
34 virtual bool canDial(AsyncCall &call);
35 void dial(AsyncCall &call);
36
37 JobPointer job;
38
39protected:
40 virtual void doDial() = 0; // actually calls the job method
41
42private:
43 // not implemented and should not be needed
44 JobDialer &operator =(const JobDialer &);
45};
46
47/// schedule an async job call using a dialer; use CallJobHere macros instead
48template <class Dialer>
55622953 49AsyncCall::Pointer
4299f876
AR
50CallJob(int debugSection, int debugLevel, const char *fileName, int fileLine,
51 const char *callName, const Dialer &dialer)
52{
53 AsyncCall::Pointer call = asyncCall(debugSection, debugLevel, callName, dialer);
55622953
CT
54 ScheduleCall(fileName, fileLine, call);
55 return call;
4299f876
AR
56}
57
4299f876
AR
58#define CallJobHere(debugSection, debugLevel, job, Class, method) \
59 CallJob((debugSection), (debugLevel), __FILE__, __LINE__, \
60 (#Class "::" #method), \
61 JobMemFun<Class>((job), &Class::method))
62
63#define CallJobHere1(debugSection, debugLevel, job, Class, method, arg1) \
64 CallJob((debugSection), (debugLevel), __FILE__, __LINE__, \
65 (#Class "::" #method), \
a3855a07 66 JobMemFun((job), &Class::method, (arg1)))
4299f876 67
4299f876
AR
68/// Convenience macro to create a Dialer-based job callback
69#define JobCallback(dbgSection, dbgLevel, Dialer, job, method) \
70 asyncCall((dbgSection), (dbgLevel), #method, \
71 Dialer(CbcPointer<Dialer::DestClass>(job), &method))
72
0edbef7e 73/*
74 * *MemFunT are member function (i.e., class method) wrappers. They store
75 * details of a method call in an object so that the call can be delayed
76 * and executed asynchronously. Details may include the object pointer,
77 * the handler method pointer, and parameters. To simplify, we require
78 * all handlers to return void and not be constant.
79 */
80
81/*
82 * We need one wrapper for every supported member function arity (i.e.,
83 * number of handler arguments). The first template parameter is the class
84 * type of the handler. That class must be an AsyncJob child.
85 */
86
87// Arity names are from http://en.wikipedia.org/wiki/Arity
88
4299f876
AR
89template <class Job>
90class NullaryMemFunT: public JobDialer<Job>
0edbef7e 91{
92public:
4299f876
AR
93 typedef void (Job::*Method)();
94 explicit NullaryMemFunT(const CbcPointer<Job> &aJob, Method aMethod):
f53969cc 95 JobDialer<Job>(aJob), method(aMethod) {}
0edbef7e 96
337b9aa4 97 void print(std::ostream &os) const override { os << "()"; }
0edbef7e 98
99public:
0edbef7e 100 Method method;
101
102protected:
337b9aa4 103 void doDial() override { ((&(*this->job))->*method)(); }
0edbef7e 104};
105
8822ebee 106template <class Job, class Data, class Argument1 = Data>
4299f876 107class UnaryMemFunT: public JobDialer<Job>
0edbef7e 108{
109public:
4299f876
AR
110 typedef void (Job::*Method)(Argument1);
111 explicit UnaryMemFunT(const CbcPointer<Job> &aJob, Method aMethod,
8822ebee 112 const Data &anArg1): JobDialer<Job>(aJob),
f53969cc 113 method(aMethod), arg1(anArg1) {}
0edbef7e 114
337b9aa4 115 void print(std::ostream &os) const override { os << '(' << arg1 << ')'; }
0edbef7e 116
117public:
0edbef7e 118 Method method;
8822ebee 119 Data arg1;
0edbef7e 120
121protected:
337b9aa4 122 void doDial() override { ((&(*this->job))->*method)(arg1); }
0edbef7e 123};
124
125// ... add more as needed
126
0edbef7e 127// Now we add global templated functions that create the member function
128// wrappers above. These are for convenience: it is often easier to
129// call a templated function than to create a templated object.
130
131template <class C>
132NullaryMemFunT<C>
4299f876 133JobMemFun(const CbcPointer<C> &job, typename NullaryMemFunT<C>::Method method)
0edbef7e 134{
4299f876 135 return NullaryMemFunT<C>(job, method);
0edbef7e 136}
137
138template <class C, class Argument1>
139UnaryMemFunT<C, Argument1>
4299f876 140JobMemFun(const CbcPointer<C> &job, typename UnaryMemFunT<C, Argument1>::Method method,
4cb2536f 141 Argument1 arg1)
0edbef7e 142{
4299f876
AR
143 return UnaryMemFunT<C, Argument1>(job, method, arg1);
144}
145
4299f876
AR
146// inlined methods
147
148template<class Job>
149JobDialer<Job>::JobDialer(const JobPointer &aJob): job(aJob)
150{
151}
152
153template<class Job>
154JobDialer<Job>::JobDialer(const JobDialer<Job> &d): CallDialer(d), job(d.job)
155{
156}
157
158template<class Job>
159bool
160JobDialer<Job>::canDial(AsyncCall &call)
161{
162 if (!job)
163 return call.cancel("job gone");
164
165 return job->canBeCalled(call);
166}
167
168template<class Job>
169void
170JobDialer<Job>::dial(AsyncCall &call)
171{
172 job->callStart(call);
173
174 try {
175 doDial();
176 } catch (const std::exception &e) {
177 debugs(call.debugSection, 3,
bf95c10a 178 call.name << " threw exception: " << e.what());
4299f876
AR
179 job->callException(e);
180 }
181
182 job->callEnd(); // may delete job
0edbef7e 183}
184
185#endif /* SQUID_ASYNCJOBCALLS_H */
f53969cc 186