]> git.ipfire.org Git - thirdparty/squid.git/blame - src/base/AsyncCall.h
Boilerplate: update copyright blurbs on Squid helpers
[thirdparty/squid.git] / src / base / AsyncCall.h
CommitLineData
854d4d81 1#ifndef SQUID_ASYNCCALL_H
2#define SQUID_ASYNCCALL_H
3
52ed047a 4#include "base/InstanceId.h"
854d4d81 5#include "event.h"
314782d4 6#include "RefCount.h"
854d4d81 7
63be0a78 8/**
9 \defgroup AsynCallsAPI Async-Calls API
10 \par
11 * A call is asynchronous if the caller proceeds after the call is made,
12 * and the callee receives the call during the next main loop iteration.
13 * Asynchronous calls help avoid nasty call-me-when-I-call-you loops
14 * that humans often have trouble understanding or implementing correctly.
15 \par
16 * Asynchronous calls are currently implemented via Squid events. The call
17 * event stores the pointer to the callback function and cbdata-protected
18 * callback data. To call a method of an object, the method is wrapped
19 * in a method-specific, static callback function and the pointer to the
26ac0430 20 * object is passed to the wrapper. For the method call to be safe, the
63be0a78 21 * class must be cbdata-enabled.
22 \par
23 * You do not have to use the macros below to make or receive asynchronous
26ac0430 24 * method calls, but they give you a uniform interface and handy call
63be0a78 25 * debugging.
26 */
854d4d81 27
3e5c8cf4 28class CallDialer;
29class AsyncCallQueue;
30
63be0a78 31/**
32 \todo add unique call IDs
33 \todo CBDATA_CLASS2 kids
34 \ingroup AsyncCallsAPI
35 */
3e5c8cf4 36class AsyncCall: public RefCountable
37{
38public:
39 typedef RefCount <AsyncCall> Pointer;
40 friend class AsyncCallQueue;
41
42 AsyncCall(int aDebugSection, int aDebugLevel, const char *aName);
43 virtual ~AsyncCall();
26ac0430 44
3e5c8cf4 45 void make(); // fire if we can; handles general call debugging
46
47 // can be called from canFire() for debugging; always returns false
48 bool cancel(const char *reason);
26ac0430 49
3e5c8cf4 50 bool canceled() { return isCanceled != NULL; }
51
52 virtual CallDialer *getDialer() = 0;
53
54 void print(std::ostream &os);
26ac0430 55
37cba319
AR
56 /// remove us from the queue; we are head unless we are queued after prev
57 void dequeue(AsyncCall::Pointer &head, AsyncCall::Pointer &prev);
58
3e5c8cf4 59 void setNext(AsyncCall::Pointer aNext) {
26ac0430 60 theNext = aNext;
3e5c8cf4 61 }
62
63 AsyncCall::Pointer &Next() {
26ac0430 64 return theNext;
3e5c8cf4 65 }
66
67public:
68 const char *const name;
69 const int debugSection;
70 const int debugLevel;
52ed047a 71 const InstanceId<AsyncCall> id;
3e5c8cf4 72
73protected:
74 virtual bool canFire();
75
76 virtual void fire() = 0;
77
78 AsyncCall::Pointer theNext; // used exclusively by AsyncCallQueue
79
80private:
81 const char *isCanceled; // set to the cancelation reason by cancel()
cbff89ba
AJ
82
83 // not implemented to prevent nil calls from being passed around and unknowingly scheduled, for now.
84 AsyncCall();
85 AsyncCall(const AsyncCall &);
3e5c8cf4 86};
87
88inline
89std::ostream &operator <<(std::ostream &os, AsyncCall &call)
90{
91 call.print(os);
92 return os;
854d4d81 93}
94
63be0a78 95/**
96 \ingroup AsyncCallAPI
97 * Interface for all async call dialers
98 */
3e5c8cf4 99class CallDialer
100{
101public:
102 CallDialer() {}
103 virtual ~CallDialer() {}
104
105 // TODO: Add these for clarity when CommCbFunPtrCallT is gone
106 //virtual bool canDial(AsyncCall &call) = 0;
107 //virtual void dial(AsyncCall &call) = 0;
108
109 virtual void print(std::ostream &os) const = 0;
110};
111
63be0a78 112/**
113 \ingroup AsyncCallAPI
114 * This template implements an AsyncCall using a specified Dialer class
115 */
3e5c8cf4 116template <class Dialer>
117class AsyncCallT: public AsyncCall
118{
119public:
120 AsyncCallT(int aDebugSection, int aDebugLevel, const char *aName,
26ac0430
AJ
121 const Dialer &aDialer): AsyncCall(aDebugSection, aDebugLevel, aName),
122 dialer(aDialer) {}
3e5c8cf4 123
cbff89ba
AJ
124 AsyncCallT(const AsyncCallT<Dialer> &o):
125 AsyncCall(o.debugSection, o.debugLevel, o.name),
126 dialer(o.dialer) {}
127
128 ~AsyncCallT() {}
129
3e5c8cf4 130 CallDialer *getDialer() { return &dialer; }
131
132protected:
26ac0430
AJ
133 virtual bool canFire() {
134 return AsyncCall::canFire() &&
135 dialer.canDial(*this);
136 }
3e5c8cf4 137 virtual void fire() { dialer.dial(*this); }
138
139 Dialer dialer;
cbff89ba
AJ
140
141private:
142 AsyncCallT & operator=(const AsyncCallT &); // not defined. call assignments not permitted.
3e5c8cf4 143};
144
145template <class Dialer>
146inline
147AsyncCall *
148asyncCall(int aDebugSection, int aDebugLevel, const char *aName,
26ac0430 149 const Dialer &aDialer)
3e5c8cf4 150{
151 return new AsyncCallT<Dialer>(aDebugSection, aDebugLevel, aName, aDialer);
152}
854d4d81 153
63be0a78 154/** Call scheduling helper. Use ScheduleCallHere if you can. */
8a648e8d 155bool ScheduleCall(const char *fileName, int fileLine, AsyncCall::Pointer &call);
63be0a78 156
157/** Call scheduling helper. */
3e5c8cf4 158#define ScheduleCallHere(call) ScheduleCall(__FILE__, __LINE__, (call))
854d4d81 159
854d4d81 160#endif /* SQUID_ASYNCCALL_H */