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