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