--------------------- PatchSet 4038 Date: 2007/02/14 04:40:01 Author: rousskov Branch: squid3-icap Tag: (none) Log: - Added basic support for asynchronous calls. The calls are implemented using Squid events, at least for now. The provided functions and macros provide simple debugging at the call scheduling and execution times. Macros are used to log the location of the call and the call handler. For a simple usage sketch, please see AsyncCall.cc. It may be possible to customize call scheduling and debugging and in a class context, but I have not tested that theory yet. The code was inspired by ICAP/MsgPipe implementation, that is about to be deleted for reasons unrelated to asynchronous calling. Members: src/AsyncCall.cc:1.1->1.1.2.1 src/AsyncCall.h:1.1->1.1.2.1 --- /dev/null Wed Feb 14 13:37:19 2007 +++ squid3/src/AsyncCall.cc Wed Feb 14 13:38:37 2007 @@ -0,0 +1,47 @@ +#include "squid.h" +#include "AsyncCall.h" + +void scheduleAsyncCall(int debugSection, int debugLevel, + const char *fileName, int fileLine, void *objectPtr, const char *callName, + EVH *wrapper) +{ + debugs(debugSection, debugLevel, fileName << "(" << fileLine << + ") will call " << callName << '(' << objectPtr << ')'); + eventAdd(callName, wrapper, objectPtr, 0.0, 0, true); +} + +bool enterAsyncCallWrapper(int debugSection, int debugLevel, + void *objectPtr, const char *className, const char *methodName) +{ + assert(objectPtr); + debugs(debugSection, debugLevel, "entering " << className << "::" << + methodName << '(' << objectPtr << ')'); + return true; +} + +void exitAsyncCallWrapper(int debugSection, int debugLevel, + void *objectPtr, const char *className, const char *methodName) +{ + debugs(debugSection, debugLevel, "exiting " << className << "::" << + methodName << '(' << objectPtr << ')'); +} + + +#if USAGE_SKETCH + +class TestClass { + public: + virtual ~TestClass(); + + virtual void testMethod(); // does not have to be virtual + AsyncCallWrapper(0,0, TestClass, testMethod) // define a wrapper + + private: + CBDATA_CLASS2(TestClass); +}; + +void testCase(TestClass *c) { + AsyncCall(0,0, &c, TestClass::testMethod); // make an async call to c +} + +#endif --- /dev/null Wed Feb 14 13:37:19 2007 +++ squid3/src/AsyncCall.h Wed Feb 14 13:38:37 2007 @@ -0,0 +1,92 @@ + +/* + * $Id: AsyncCall.h,v 1.1.2.1 2007/02/14 04:40:01 rousskov Exp $ + * + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#ifndef SQUID_ASYNCCALL_H +#define SQUID_ASYNCCALL_H + +//#include "cbdata.h" +#include "event.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. +// Asynchronous calls help avoid nasty call-me-when-I-call-you loops +// that humans often have trouble understanding or implementing correctly. + +// Asynchronous calls are currently implemented via Squid events. The call +// event stores the pointer to the callback function and cbdata-protected +// callback data. To call a method of an object, the method is wrapped +// in a method-specific, static callback function and the pointer to the +// object is passed to the wrapper. For the method call to be safe, the +// class must be cbdata-enabled. + +// You do not have to use the macros below to make or receive asynchronous +// method calls, but they give you a uniform interface and handy call +// debugging. + +// See AsyncCall.cc for a usage sketch. + + +// Make an asynchronous object->callName() call. +#define AsyncCall(debugSection, debugLevel, objectPtr, callName) \ + scheduleAsyncCall((debugSection), (debugLevel), __FILE__, __LINE__, \ + (objectPtr), #callName, \ + &(callName ## Wrapper)) + +// Declare and define a wrapper for an asynchronous call handler method +#define AsyncCallWrapper(debugSection, debugLevel, ClassName, callName) \ +static \ +void callName ## Wrapper(void *data) { \ + ClassName *objectPtr = static_cast(data); \ + if (enterAsyncCallWrapper((debugSection), (debugLevel), data, #ClassName, #callName)) { \ + objectPtr->callName(); \ + exitAsyncCallWrapper((debugSection), (debugLevel), data, #ClassName, #callName); \ + } \ +} + + +// Hint: to customize debugging of asynchronous messages in a class, provide +// class method called scheduleAsyncCall, enterAsyncCallWrapper, and/or +// exitAsyncCallWrapper. Class method will take priority over these globals. + +extern void scheduleAsyncCall(int debugSection, int debugLevel, + const char *fileName, int fileLine, void *objectPtr, const char *callName, + EVH *wrapper); + +extern bool enterAsyncCallWrapper(int debugSection, int debugLevel, + void *objectPtr, const char *className, const char *methodName); + +extern void exitAsyncCallWrapper(int debugSection, int debugLevel, + void *objectPtr, const char *className, const char *methodName); + + +#endif /* SQUID_ASYNCCALL_H */