]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
- Added basic support for asynchronous calls. The calls are
authorrousskov <>
Fri, 6 Apr 2007 10:45:07 +0000 (10:45 +0000)
committerrousskov <>
Fri, 6 Apr 2007 10:45:07 +0000 (10:45 +0000)
  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
  being deleted for reasons unrelated to asynchronous calling.

src/AsyncCall.cc [new file with mode: 0644]
src/AsyncCall.h [new file with mode: 0644]

diff --git a/src/AsyncCall.cc b/src/AsyncCall.cc
new file mode 100644 (file)
index 0000000..b115452
--- /dev/null
@@ -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
diff --git a/src/AsyncCall.h b/src/AsyncCall.h
new file mode 100644 (file)
index 0000000..5fc2816
--- /dev/null
@@ -0,0 +1,92 @@
+
+/*
+ * $Id: AsyncCall.h,v 1.1 2007/04/06 04:45:07 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<ClassName*>(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 */