]> git.ipfire.org Git - thirdparty/squid.git/blame - src/base/AsyncCall.h
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / base / AsyncCall.h
CommitLineData
bbc27441 1/*
f70aedc4 2 * Copyright (C) 1996-2021 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
ccfbe8f4 12#include "base/CodeContext.h"
52ed047a 13#include "base/InstanceId.h"
854d4d81 14#include "event.h"
314782d4 15#include "RefCount.h"
854d4d81 16
63be0a78 17/**
18 \defgroup AsynCallsAPI Async-Calls API
19 \par
20 * A call is asynchronous if the caller proceeds after the call is made,
21 * and the callee receives the call during the next main loop iteration.
22 * Asynchronous calls help avoid nasty call-me-when-I-call-you loops
23 * that humans often have trouble understanding or implementing correctly.
24 \par
25 * Asynchronous calls are currently implemented via Squid events. The call
26 * event stores the pointer to the callback function and cbdata-protected
27 * callback data. To call a method of an object, the method is wrapped
28 * in a method-specific, static callback function and the pointer to the
26ac0430 29 * object is passed to the wrapper. For the method call to be safe, the
63be0a78 30 * class must be cbdata-enabled.
31 \par
32 * You do not have to use the macros below to make or receive asynchronous
26ac0430 33 * method calls, but they give you a uniform interface and handy call
63be0a78 34 * debugging.
35 */
854d4d81 36
3e5c8cf4 37class CallDialer;
38class AsyncCallQueue;
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;
ccfbe8f4
AR
73
74 /// what the callee is expected to work on
75 CodeContext::Pointer codeContext;
76
3e5c8cf4 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:
2f8abb64 89 const char *isCanceled; // set to the cancellation 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