--------------------- PatchSet 6098 Date: 2007/11/06 18:37:01 Author: chtsanti Branch: async-calls Tag: (none) Log: - The JobCall holds and can use the name of scheduled method and also the debugsection and level of the caller. This will help as debuging async calls. - Implement JobCall::fire, jobCall::handleException and jobCall::end and AsyncCallBase::fireWrapper2 methods so jobCall is able to work with AsyncJob objects. - Implement the CallJob templated function which creates a jobCall object and schedules a call to the AsyncCallBase::fireWrapper2 - The AsyncJob::callStart, AsyncJob::callException and AsyncJob::callEnd are now public method members to allow its use by AsyncCallBase class. - Implement CallJobHere and CallJobHere1 macros which can be used as an easy interface for scheduling AsyncJob calls. For an usage example look at the Tester class and do_test_arg0 and do_test_arg1 methods Members: src/AsyncCall.cc:1.3.22.1->1.3.22.2 src/AsyncCall.h:1.3.22.1->1.3.22.2 src/ICAP/AsyncJob.cc:1.3.4.4->1.3.4.5 src/ICAP/AsyncJob.h:1.3.14.4->1.3.14.5 src/ICAP/ICAPInitiate.h:1.2.30.1->1.2.30.2 Index: squid3/src/AsyncCall.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/AsyncCall.cc,v retrieving revision 1.3.22.1 retrieving revision 1.3.22.2 diff -u -r1.3.22.1 -r1.3.22.2 --- squid3/src/AsyncCall.cc 1 Nov 2007 19:06:21 -0000 1.3.22.1 +++ squid3/src/AsyncCall.cc 6 Nov 2007 18:37:01 -0000 1.3.22.2 @@ -28,7 +28,40 @@ } +bool JobCall::fire() +{ + AsyncJob *job = theObject(); + + if(!cbdataReferenceValid(job->toCbdata())) + return false; + + if (!job->callStart(theName)) { + debugs(debugSection, debugLevel, HERE << "job call "<< theName <<" NOT fire " << this); + return false; + } + debugs(debugSection, debugLevel, HERE << "job call " << theName << " fire " << this); + callJob(); + debugs(debugSection, debugLevel, HERE << theName << " fired"); + return true; +} + +void JobCall::handleException(const TextException &e) +{ + debugs(debugSection, debugLevel, HERE << "job call exception"); + AsyncJob *job = theObject(); + job->callException(e); +} + +void JobCall::end() +{ + debugs(debugSection, debugLevel, HERE << "job call end"); + + AsyncJob *job = theObject(); + if(!cbdataReferenceValid(job->toCbdata())) + return; + job->callEnd(); +} #if USAGE_SKETCH @@ -52,12 +85,20 @@ // Note that it is not inherited from AsyncJob yet. It will be once JobCall // methods are implemented and start casting AsyncCallBase::theObject // to AsyncJob to call well-known job API methods such as swanSong. -struct Tester { - virtual ~Tester() {} - - virtual void method0() { debugs(0,0, HERE << "METHOD0()"); } - virtual void method1(int arg1) { debugs(0,0, HERE << "METHOD1(" << arg1 << ")"); } +struct Tester: virtual public AsyncJob { + Tester():AsyncJob("Tester"){} + virtual ~Tester() {} + + virtual void start(){}; + virtual bool doneAll() const{return true;}; // return true when done + virtual void swanSong(){}; // perform internal cleanup + virtual const char *status() const {return NULL;}; // for debugging + + virtual void method0() { debugs(0,0, HERE << "METHOD0()"); } + virtual void method1(int arg1) { debugs(0,0, HERE << "METHOD1(" << arg1 << ")"); } + CBDATA_CLASS2(Tester); }; +CBDATA_CLASS_INIT(Tester); // Set to false to test immediate call firing from test cases. No calls // will be fired without submitting an asynchronous event in real code. @@ -81,20 +122,16 @@ void do_test_arg0() { Tester *tester = new Tester; // leaking - debugs(0,0, HERE << "creating call for " << tester); - AsyncCallBase *call = jobCall(MemFun(tester, &Tester::method0)); - debugs(0,0, HERE << "created"); - do_test_call(call); + CallJobHere(0,0,tester,Tester::method0); + return; } // do one test with a member function having one int argument. void do_test_arg1() { Tester *tester = new Tester; // leaking - debugs(0,0, HERE << "creating call for " << tester); - AsyncCallBase *call = jobCall(MemFun(tester, &Tester::method1, 5)); - debugs(0,0, HERE << "created"); - do_test_call(call); + CallJobHere1(0,0,tester,Tester::method1,5); + return; } void do_testAsyncCalls() Index: squid3/src/AsyncCall.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/AsyncCall.h,v retrieving revision 1.3.22.1 retrieving revision 1.3.22.2 diff -u -r1.3.22.1 -r1.3.22.2 --- squid3/src/AsyncCall.h 1 Nov 2007 19:06:21 -0000 1.3.22.1 +++ squid3/src/AsyncCall.h 6 Nov 2007 18:37:01 -0000 1.3.22.2 @@ -1,6 +1,6 @@ /* - * $Id: AsyncCall.h,v 1.3.22.1 2007/11/01 19:06:21 chtsanti Exp $ + * $Id: AsyncCall.h,v 1.3.22.2 2007/11/06 18:37:01 chtsanti Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -34,8 +34,10 @@ #ifndef SQUID_ASYNCCALL_H #define SQUID_ASYNCCALL_H -//#include "cbdata.h" +#include "cbdata.h" #include "event.h" +#include "ICAP/AsyncJob.h" +#include "ICAP/TextException.h" // A call is asynchronous if the caller proceeds after the call is made, // and the callee receives the call during the next main loop iteration. @@ -100,14 +102,17 @@ // Arity names are from http://en.wikipedia.org/wiki/Arity + template -class NullaryMemFunT { +class NullaryMemFunT +{ public: typedef void (C::*MemFunPtr)(); explicit NullaryMemFunT(C *anObject, MemFunPtr aP): theObject(anObject), theP(aP) {} void operator ()() { (theObject->*theP)(); } + C *Object() const {return theObject;} private: C *theObject; @@ -115,13 +120,16 @@ }; template -class UnaryMemFunT { +class UnaryMemFunT +{ public: typedef void (C::*MemFunPtr)(Argument1); explicit UnaryMemFunT(C *anObject, MemFunPtr aP, const Argument1 &anArg1): theObject(anObject), theP(aP), theArg1(anArg1) {} void operator ()() { (theObject->*theP)(theArg1); } + C *Object() const {return theObject;} + private: C *theObject; @@ -155,21 +163,33 @@ AsyncCallWrapper(0, 0, AsyncCallBase, fire); // nedded for AsyncCall macro static void fireWrapper2(void *data) { - debugs(0,0, HERE << "data=" << data); +// debugs(0,0, HERE << "data=" << data); AsyncCallBase *call = static_cast(data); if (enterAsyncCallWrapper(0, 0, data, "AsyncCallBase", "fire")) { - debugs(0,0, HERE << "call=" << call); - call->fire(); +// debugs(0,0, HERE << "call=" << call); + try{ + call->fire(); + } + catch (const TextException &e) { + call->handleException(e); + } + call->end(); exitAsyncCallWrapper(0, 0, data, "AsyncCallBase", "fire"); } } - - virtual ~AsyncCallBase() {} - - virtual bool fire() = 0; - virtual void handleException() = 0; - virtual void end() = 0; + AsyncCallBase(int debug_section, int debug_level, const char *callName): + theName(callName), debugSection(debug_section), debugLevel(debug_level){} + virtual ~AsyncCallBase() {} + + virtual bool fire() = 0; + virtual void handleException(const TextException &e) = 0; + virtual void end() = 0; +protected: + virtual AsyncJob *theObject() = 0; + const char *theName; + int debugSection; + int debugLevel; }; // Same as AsyncCall, but does not assume the object is cbdata-protected. @@ -191,16 +211,18 @@ // and we want to keep this class simple and template-free. Thus, we // add a callJob() virtual method that the JobCallT template below will // implement for us, calling the job. - +//class AsyncJob; class JobCall: public AsyncCallBase { public: - virtual bool fire() { debugs(0,0, HERE << "job call fire " << this); callJob(); debugs(0,0, HERE << "fired"); return true; } - virtual void handleException() { debugs(0,0, HERE << "job call exception"); } - virtual void end() { debugs(0,0, HERE << "job call end"); } + JobCall(int debug_section, int debug_level, const char *callName): + AsyncCallBase(debug_section, debug_level, callName){} + virtual bool fire(); + virtual void handleException(const TextException &e); + virtual void end(); protected: - virtual void callJob() = 0; + virtual void callJob() = 0; }; // This template combines member function pointer calling ability of MemFunT @@ -210,11 +232,16 @@ class JobCallT: public JobCall { public: - JobCallT(const Dialer &aDialer): theDialer(aDialer) { debugs(0,0, HERE << "job call created " << this); } + JobCallT(const Dialer &aDialer,int debug_section, int debug_level, const char *callName): + JobCall(debug_section, debug_level, callName), theDialer(aDialer) + { + AsyncJob *job = dynamic_cast(aDialer.Object()); + cbdataReference(job->toCbdata()); + } protected: - virtual void callJob() { debugs(0,0, HERE << "dialing"); theDialer(); } - + virtual void callJob() { debugs(debugSection, debugLevel, HERE << "dialing "<< theName); theDialer(); } + virtual AsyncJob *theObject() {return dynamic_cast(theDialer.Object());} private: Dialer theDialer; }; @@ -224,9 +251,30 @@ // a templated function than to create a templated object. // We need one function for each *MemFunT template. template -JobCall *jobCall(const Dialer &dialer) +JobCall *jobCall(const Dialer &dialer,int debug_section, int debug_level, const char *callName) { - return new JobCallT(dialer); + return new JobCallT(dialer, debug_section, debug_level, callName); +} + +template bool CallJob(int debugSection, int debugLevel, const char *fileName, int fileLine, const char *callName, const Dialer &dialer){ + debugs(debugSection, debugLevel, HERE << "creating call for " << dialer.Object()); + AsyncCallBase *call = jobCall(dialer, debugSection, debugLevel, callName); + debugs(debugSection, debugLevel, HERE << "created"); + + debugs(debugSection, debugLevel, HERE << "objectPtr=" << call); + scheduleAsyncCall(debugSection, debugLevel, fileName, fileLine, + call, callName, + &(AsyncCallBase::fireWrapper2), false); + + debugs(debugSection, debugLevel, HERE << "scheduled"); + return true; } + +#define CallJobHere(debugSection, debugLevel, objectPtr, callName) \ + CallJob(debugSection, debugLevel, __FILE__, __LINE__, #callName, MemFun(objectPtr,&callName)) + +#define CallJobHere1(debugSection, debugLevel, objectPtr, callName, arg1) \ + CallJob(debugSection, debugLevel, __FILE__, __LINE__, #callName, MemFun(objectPtr,&callName, arg1)) + #endif /* SQUID_ASYNCCALL_H */ Index: squid3/src/ICAP/AsyncJob.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ICAP/AsyncJob.cc,v retrieving revision 1.3.4.4 retrieving revision 1.3.4.5 diff -u -r1.3.4.4 -r1.3.4.5 --- squid3/src/ICAP/AsyncJob.cc 24 Oct 2007 17:15:09 -0000 1.3.4.4 +++ squid3/src/ICAP/AsyncJob.cc 6 Nov 2007 18:37:01 -0000 1.3.4.5 @@ -6,6 +6,7 @@ #include "cbdata.h" #include "TextException.h" #include "AsyncJob.h" +#include "AsyncCall.h" /* AsyncJobHolder */ Index: squid3/src/ICAP/AsyncJob.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ICAP/AsyncJob.h,v retrieving revision 1.3.14.4 retrieving revision 1.3.14.5 diff -u -r1.3.14.4 -r1.3.14.5 --- squid3/src/ICAP/AsyncJob.h 25 Oct 2007 16:41:21 -0000 1.3.14.4 +++ squid3/src/ICAP/AsyncJob.h 6 Nov 2007 18:37:01 -0000 1.3.14.5 @@ -1,6 +1,6 @@ /* - * $Id: AsyncJob.h,v 1.3.14.4 2007/10/25 16:41:21 chtsanti Exp $ + * $Id: AsyncJob.h,v 1.3.14.5 2007/11/06 18:37:01 chtsanti Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -34,8 +34,6 @@ #ifndef SQUID_ASYNC_JOB_H #define SQUID_ASYNC_JOB_H -#include "AsyncCall.h" - /* * AsyncJob is an API and a base for a class that implements a stand-alone * "job", "task", or "logical processing thread" which receives asynchronous @@ -108,11 +106,13 @@ virtual void swanSong() = 0; // perform internal cleanup virtual const char *status() const = 0; // for debugging +public: // asynchronous call maintenance bool callStart(const char *methodName); virtual void callException(const TextException &e); virtual void callEnd(); +protected: const char *stopReason; // reason for forcing done() to be true const char *typeName; // kid (leaf) class name, for debugging const char *inCall; // name of the asynchronous call being executed, if any Index: squid3/src/ICAP/ICAPInitiate.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ICAP/ICAPInitiate.h,v retrieving revision 1.2.30.1 retrieving revision 1.2.30.2 diff -u -r1.2.30.1 -r1.2.30.2 --- squid3/src/ICAP/ICAPInitiate.h 22 Oct 2007 19:26:14 -0000 1.2.30.1 +++ squid3/src/ICAP/ICAPInitiate.h 6 Nov 2007 18:37:01 -0000 1.2.30.2 @@ -1,6 +1,6 @@ /* - * $Id: ICAPInitiate.h,v 1.2.30.1 2007/10/22 19:26:14 chtsanti Exp $ + * $Id: ICAPInitiate.h,v 1.2.30.2 2007/11/06 18:37:01 chtsanti Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -37,7 +37,7 @@ #include "comm.h" #include "MemBuf.h" #include "ICAPServiceRep.h" -#include "AsyncJob.h" +#include "AsyncCall.h" class HttpMsg; class ICAPInitiator;