]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/base/AsyncCall.h
5 #ifndef SQUID_ASYNCCALL_H
6 #define SQUID_ASYNCCALL_H
9 #include "base/InstanceId.h"
11 //#include "TextException.h"
14 \defgroup AsynCallsAPI Async-Calls API
16 * A call is asynchronous if the caller proceeds after the call is made,
17 * and the callee receives the call during the next main loop iteration.
18 * Asynchronous calls help avoid nasty call-me-when-I-call-you loops
19 * that humans often have trouble understanding or implementing correctly.
21 * Asynchronous calls are currently implemented via Squid events. The call
22 * event stores the pointer to the callback function and cbdata-protected
23 * callback data. To call a method of an object, the method is wrapped
24 * in a method-specific, static callback function and the pointer to the
25 * object is passed to the wrapper. For the method call to be safe, the
26 * class must be cbdata-enabled.
28 * You do not have to use the macros below to make or receive asynchronous
29 * method calls, but they give you a uniform interface and handy call
37 \todo add unique call IDs
38 \todo CBDATA_CLASS2 kids
39 \ingroup AsyncCallsAPI
41 class AsyncCall
: public RefCountable
44 typedef RefCount
<AsyncCall
> Pointer
;
45 friend class AsyncCallQueue
;
47 AsyncCall(int aDebugSection
, int aDebugLevel
, const char *aName
);
50 void make(); // fire if we can; handles general call debugging
52 // can be called from canFire() for debugging; always returns false
53 bool cancel(const char *reason
);
55 bool canceled() { return isCanceled
!= NULL
; }
57 virtual CallDialer
*getDialer() = 0;
59 void print(std::ostream
&os
);
61 /// remove us from the queue; we are head unless we are queued after prev
62 void dequeue(AsyncCall::Pointer
&head
, AsyncCall::Pointer
&prev
);
64 void setNext(AsyncCall::Pointer aNext
) {
68 AsyncCall::Pointer
&Next() {
73 const char *const name
;
74 const int debugSection
;
76 const InstanceId
<AsyncCall
> id
;
79 virtual bool canFire();
81 virtual void fire() = 0;
83 AsyncCall::Pointer theNext
; // used exclusively by AsyncCallQueue
86 const char *isCanceled
; // set to the cancelation reason by cancel()
88 // not implemented to prevent nil calls from being passed around and unknowingly scheduled, for now.
90 AsyncCall(const AsyncCall
&);
94 std::ostream
&operator <<(std::ostream
&os
, AsyncCall
&call
)
101 \ingroup AsyncCallAPI
102 * Interface for all async call dialers
108 virtual ~CallDialer() {}
110 // TODO: Add these for clarity when CommCbFunPtrCallT is gone
111 //virtual bool canDial(AsyncCall &call) = 0;
112 //virtual void dial(AsyncCall &call) = 0;
114 virtual void print(std::ostream
&os
) const = 0;
118 \ingroup AsyncCallAPI
119 * This template implements an AsyncCall using a specified Dialer class
121 template <class Dialer
>
122 class AsyncCallT
: public AsyncCall
125 AsyncCallT(int aDebugSection
, int aDebugLevel
, const char *aName
,
126 const Dialer
&aDialer
): AsyncCall(aDebugSection
, aDebugLevel
, aName
),
129 AsyncCallT(const AsyncCallT
<Dialer
> &o
):
130 AsyncCall(o
.debugSection
, o
.debugLevel
, o
.name
),
135 CallDialer
*getDialer() { return &dialer
; }
138 virtual bool canFire() {
139 return AsyncCall::canFire() &&
140 dialer
.canDial(*this);
142 virtual void fire() { dialer
.dial(*this); }
147 AsyncCallT
& operator=(const AsyncCallT
&); // not defined. call assignments not permitted.
150 template <class Dialer
>
153 asyncCall(int aDebugSection
, int aDebugLevel
, const char *aName
,
154 const Dialer
&aDialer
)
156 return new AsyncCallT
<Dialer
>(aDebugSection
, aDebugLevel
, aName
, aDialer
);
159 /** Call scheduling helper. Use ScheduleCallHere if you can. */
160 extern bool ScheduleCall(const char *fileName
, int fileLine
, AsyncCall::Pointer
&call
);
162 /** Call scheduling helper. */
163 #define ScheduleCallHere(call) ScheduleCall(__FILE__, __LINE__, (call))
166 #endif /* SQUID_ASYNCCALL_H */