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