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