]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/base/AsyncJobCalls.h
SourceFormat Enforcement
[thirdparty/squid.git] / src / base / AsyncJobCalls.h
index 0657d3672015361f13cbc67e8a31a20635d41482..45d56d0c5aa527b482ac133d417c8dbc82fc0483 100644 (file)
@@ -1,12 +1,73 @@
-
 /*
- * $Id$
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_ASYNCJOBCALLS_H
 #define SQUID_ASYNCJOBCALLS_H
 
 #include "base/AsyncJob.h"
+#include "base/CbcPointer.h"
+#include "Debug.h"
+
+/**
+ \ingroup AsyncJobAPI
+ * This is a base class for all job call dialers. It does all the job
+ * dialing logic (debugging, handling exceptions, etc.) except for calling
+ * the job method. The latter requires knowing the number and type of method
+ * parameters. Thus, we add a dial() virtual method that the MemFunT templates
+ * below implement for us, calling the job's method with the right params.
+ */
+template <class Job>
+class JobDialer: public CallDialer
+{
+public:
+    typedef Job DestClass;
+    typedef CbcPointer<Job> JobPointer;
+
+    JobDialer(const JobPointer &aJob);
+    JobDialer(const JobDialer &d);
+
+    virtual bool canDial(AsyncCall &call);
+    void dial(AsyncCall &call);
+
+    JobPointer job;
+
+protected:
+    virtual void doDial() = 0; // actually calls the job method
+
+private:
+    // not implemented and should not be needed
+    JobDialer &operator =(const JobDialer &);
+};
+
+/// schedule an async job call using a dialer; use CallJobHere macros instead
+template <class Dialer>
+bool
+CallJob(int debugSection, int debugLevel, const char *fileName, int fileLine,
+        const char *callName, const Dialer &dialer)
+{
+    AsyncCall::Pointer call = asyncCall(debugSection, debugLevel, callName, dialer);
+    return ScheduleCall(fileName, fileLine, call);
+}
+
+#define CallJobHere(debugSection, debugLevel, job, Class, method) \
+    CallJob((debugSection), (debugLevel), __FILE__, __LINE__, \
+        (#Class "::" #method), \
+        JobMemFun<Class>((job), &Class::method))
+
+#define CallJobHere1(debugSection, debugLevel, job, Class, method, arg1) \
+    CallJob((debugSection), (debugLevel), __FILE__, __LINE__, \
+        (#Class "::" #method), \
+        JobMemFun((job), &Class::method, (arg1)))
+
+/// Convenience macro to create a Dialer-based job callback
+#define JobCallback(dbgSection, dbgLevel, Dialer, job, method) \
+    asyncCall((dbgSection), (dbgLevel), #method, \
+        Dialer(CbcPointer<Dialer::DestClass>(job), &method))
 
 /*
  * *MemFunT are member function (i.e., class method) wrappers. They store
 
 // Arity names are from http://en.wikipedia.org/wiki/Arity
 
-template <class C>
-class NullaryMemFunT: public JobDialer
+template <class Job>
+class NullaryMemFunT: public JobDialer<Job>
 {
 public:
-    typedef void (C::*Method)();
-    explicit NullaryMemFunT(C *anObject, Method aMethod):
-            JobDialer(anObject), object(anObject), method(aMethod) {}
+    typedef void (Job::*Method)();
+    explicit NullaryMemFunT(const CbcPointer<Job> &aJob, Method aMethod):
+        JobDialer<Job>(aJob), method(aMethod) {}
 
     virtual void print(std::ostream &os) const {  os << "()"; }
 
 public:
-    C *object;
     Method method;
 
 protected:
-    virtual void doDial() { (object->*method)(); }
+    virtual void doDial() { ((&(*this->job))->*method)(); }
 };
 
-template <class C, class Argument1>
-class UnaryMemFunT: public JobDialer
+template <class Job, class Data, class Argument1 = Data>
+class UnaryMemFunT: public JobDialer<Job>
 {
 public:
-    typedef void (C::*Method)(Argument1);
-    explicit UnaryMemFunT(C *anObject, Method aMethod, const Argument1 &anArg1):
-            JobDialer(anObject),
-            object(anObject), method(aMethod), arg1(anArg1) {}
+    typedef void (Job::*Method)(Argument1);
+    explicit UnaryMemFunT(const CbcPointer<Job> &aJob, Method aMethod,
+                          const Data &anArg1): JobDialer<Job>(aJob),
+        method(aMethod), arg1(anArg1) {}
 
     virtual void print(std::ostream &os) const {  os << '(' << arg1 << ')'; }
 
 public:
-    C *object;
     Method method;
-    Argument1 arg1;
+    Data arg1;
 
 protected:
-    virtual void doDial() { (object->*method)(arg1); }
+    virtual void doDial() { ((&(*this->job))->*method)(arg1); }
 };
 
 // ... add more as needed
 
-
 // Now we add global templated functions that create the member function
 // wrappers above. These are for convenience: it is often easier to
 // call a templated function than to create a templated object.
 
 template <class C>
 NullaryMemFunT<C>
-MemFun(C *object, typename NullaryMemFunT<C>::Method method)
+JobMemFun(const CbcPointer<C> &job, typename NullaryMemFunT<C>::Method method)
 {
-    return NullaryMemFunT<C>(object, method);
+    return NullaryMemFunT<C>(job, method);
 }
 
 template <class C, class Argument1>
 UnaryMemFunT<C, Argument1>
-MemFun(C *object, typename UnaryMemFunT<C, Argument1>::Method method,
-       Argument1 arg1)
+JobMemFun(const CbcPointer<C> &job, typename UnaryMemFunT<C, Argument1>::Method method,
+          Argument1 arg1)
+{
+    return UnaryMemFunT<C, Argument1>(job, method, arg1);
+}
+
+// inlined methods
+
+template<class Job>
+JobDialer<Job>::JobDialer(const JobPointer &aJob): job(aJob)
+{
+}
+
+template<class Job>
+JobDialer<Job>::JobDialer(const JobDialer<Job> &d): CallDialer(d), job(d.job)
+{
+}
+
+template<class Job>
+bool
+JobDialer<Job>::canDial(AsyncCall &call)
 {
-    return UnaryMemFunT<C, Argument1>(object, method, arg1);
+    if (!job)
+        return call.cancel("job gone");
+
+    return job->canBeCalled(call);
+}
+
+template<class Job>
+void
+JobDialer<Job>::dial(AsyncCall &call)
+{
+    job->callStart(call);
+
+    try {
+        doDial();
+    } catch (const std::exception &e) {
+        debugs(call.debugSection, 3,
+               HERE << call.name << " threw exception: " << e.what());
+        job->callException(e);
+    }
+
+    job->callEnd(); // may delete job
 }
 
 #endif /* SQUID_ASYNCJOBCALLS_H */
+