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