]> git.ipfire.org Git - thirdparty/squid.git/blob - src/base/AsyncJobCalls.h
Enable source-formatting tools to collapse multiple whitelines in the source to one.
[thirdparty/squid.git] / src / base / AsyncJobCalls.h
1
2 /*
3 * $Id$
4 */
5
6 #ifndef SQUID_ASYNCJOBCALLS_H
7 #define SQUID_ASYNCJOBCALLS_H
8
9 #include "base/AsyncJob.h"
10 #include "base/CbcPointer.h"
11 #include "Debug.h"
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 */
21 template <class Job>
22 class JobDialer: public CallDialer
23 {
24 public:
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
36 protected:
37 virtual void doDial() = 0; // actually calls the job method
38
39 private:
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
45 template <class Dialer>
46 bool
47 CallJob(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
54
55 #define CallJobHere(debugSection, debugLevel, job, Class, method) \
56 CallJob((debugSection), (debugLevel), __FILE__, __LINE__, \
57 (#Class "::" #method), \
58 JobMemFun<Class>((job), &Class::method))
59
60 #define CallJobHere1(debugSection, debugLevel, job, Class, method, arg1) \
61 CallJob((debugSection), (debugLevel), __FILE__, __LINE__, \
62 (#Class "::" #method), \
63 JobMemFun((job), &Class::method, (arg1)))
64
65
66 /// Convenience macro to create a Dialer-based job callback
67 #define JobCallback(dbgSection, dbgLevel, Dialer, job, method) \
68 asyncCall((dbgSection), (dbgLevel), #method, \
69 Dialer(CbcPointer<Dialer::DestClass>(job), &method))
70
71
72 /*
73 * *MemFunT are member function (i.e., class method) wrappers. They store
74 * details of a method call in an object so that the call can be delayed
75 * and executed asynchronously. Details may include the object pointer,
76 * the handler method pointer, and parameters. To simplify, we require
77 * all handlers to return void and not be constant.
78 */
79
80 /*
81 * We need one wrapper for every supported member function arity (i.e.,
82 * number of handler arguments). The first template parameter is the class
83 * type of the handler. That class must be an AsyncJob child.
84 */
85
86 // Arity names are from http://en.wikipedia.org/wiki/Arity
87
88 template <class Job>
89 class NullaryMemFunT: public JobDialer<Job>
90 {
91 public:
92 typedef void (Job::*Method)();
93 explicit NullaryMemFunT(const CbcPointer<Job> &aJob, Method aMethod):
94 JobDialer<Job>(aJob), method(aMethod) {}
95
96 virtual void print(std::ostream &os) const { os << "()"; }
97
98 public:
99 Method method;
100
101 protected:
102 virtual void doDial() { ((&(*this->job))->*method)(); }
103 };
104
105 template <class Job, class Data, class Argument1 = Data>
106 class UnaryMemFunT: public JobDialer<Job>
107 {
108 public:
109 typedef void (Job::*Method)(Argument1);
110 explicit UnaryMemFunT(const CbcPointer<Job> &aJob, Method aMethod,
111 const Data &anArg1): JobDialer<Job>(aJob),
112 method(aMethod), arg1(anArg1) {}
113
114 virtual void print(std::ostream &os) const { os << '(' << arg1 << ')'; }
115
116 public:
117 Method method;
118 Data arg1;
119
120 protected:
121 virtual void doDial() { ((&(*this->job))->*method)(arg1); }
122 };
123
124 // ... add more as needed
125
126
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
131 template <class C>
132 NullaryMemFunT<C>
133 JobMemFun(const CbcPointer<C> &job, typename NullaryMemFunT<C>::Method method)
134 {
135 return NullaryMemFunT<C>(job, method);
136 }
137
138 template <class C, class Argument1>
139 UnaryMemFunT<C, Argument1>
140 JobMemFun(const CbcPointer<C> &job, typename UnaryMemFunT<C, Argument1>::Method method,
141 Argument1 arg1)
142 {
143 return UnaryMemFunT<C, Argument1>(job, method, arg1);
144 }
145
146
147 // inlined methods
148
149 template<class Job>
150 JobDialer<Job>::JobDialer(const JobPointer &aJob): job(aJob)
151 {
152 }
153
154 template<class Job>
155 JobDialer<Job>::JobDialer(const JobDialer<Job> &d): CallDialer(d), job(d.job)
156 {
157 }
158
159 template<class Job>
160 bool
161 JobDialer<Job>::canDial(AsyncCall &call)
162 {
163 if (!job)
164 return call.cancel("job gone");
165
166 return job->canBeCalled(call);
167 }
168
169 template<class Job>
170 void
171 JobDialer<Job>::dial(AsyncCall &call)
172 {
173 job->callStart(call);
174
175 try {
176 doDial();
177 } catch (const std::exception &e) {
178 debugs(call.debugSection, 3,
179 HERE << call.name << " threw exception: " << e.what());
180 job->callException(e);
181 }
182
183 job->callEnd(); // may delete job
184 }
185
186 #endif /* SQUID_ASYNCJOBCALLS_H */