AsyncCallbacks.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
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 
9 #ifndef SQUID_SRC_BASE_ASYNCCALLBACKS_H
10 #define SQUID_SRC_BASE_ASYNCCALLBACKS_H
11 
12 #include "base/AsyncCall.h"
13 #include "base/AsyncJobCalls.h"
14 #include "base/TypeTraits.h"
15 
17 template <typename AnswerT>
19 {
20 public:
21  using Answer = AnswerT;
22 
23  virtual ~WithAnswer() = default;
24 
26  virtual Answer &answer() = 0;
27 };
28 
30 template <typename Answer>
32 {
33 public:
34  // all generated copying/moving functions are correct
35  AsyncCallback() = default;
36 
37  template <class Call>
38  explicit AsyncCallback(const RefCount<Call> &call):
39  call_(call),
40  answer_(&(call->dialer.answer()))
41  {
42  }
43 
44  Answer &answer()
45  {
46  assert(answer_);
47  return *answer_;
48  }
49 
53  {
54  answer_ = nullptr;
55  const auto call = call_;
56  call_ = nullptr;
57  return call;
58  }
59 
61  explicit operator bool() const { return answer_; }
62 
63  /* methods for decaying into an AsyncCall pointer w/o access to answer */
64  operator const AsyncCall::Pointer &() const { return call_; }
65  const AsyncCall &operator *() const { return call_.operator*(); }
66  const AsyncCall *operator ->() const { return call_.operator->(); }
67 
68 private:
71 
74  Answer *answer_ = nullptr;
75 };
76 
78 template <typename Argument1>
80  public CallDialer,
81  public WithAnswer<Argument1>
82 {
83 public:
84  // stand-alone function that receives our answer
85  using Handler = void (Argument1 &);
86 
87  explicit UnaryFunCallbackDialer(Handler * const aHandler): handler(aHandler) {}
88  ~UnaryFunCallbackDialer() override = default;
89 
90  /* CallDialer API */
91  bool canDial(AsyncCall &) { return bool(handler); }
92  void dial(AsyncCall &) { handler(arg1); }
93  void print(std::ostream &os) const final { os << '(' << arg1 << ')'; }
94 
95  /* WithAnswer API */
96  Argument1 &answer() final { return arg1; }
97 
98 private:
101 };
102 
105 template <class Destination, typename Argument1>
107  public CallDialer,
108  public WithAnswer<Argument1>
109 {
110 public:
111  // class member function that receives our answer
112  typedef void (Destination::*Method)(Argument1 &);
113 
114  UnaryCbcCallbackDialer(Method method, Destination *destination): destination_(destination), method_(method) {}
115  ~UnaryCbcCallbackDialer() override = default;
116 
117  /* CallDialer API */
118  bool canDial(AsyncCall &) { return destination_.valid(); }
119  void dial(AsyncCall &) {((*destination_).*method_)(arg1_); }
120  void print(std::ostream &os) const final { os << '(' << arg1_ << ')'; }
121 
122  /* WithAnswer API */
123  Argument1 &answer() final { return arg1_; }
124 
125 private:
129 };
130 
133 template <class Job, typename Argument1>
135  public UnaryMemFunT<Job, Argument1, Argument1&>,
136  public WithAnswer<Argument1>
137 {
138 public:
140 
141  UnaryJobCallbackDialer(const CbcPointer<Job> &aJob, typename Base::Method aMethod):
142  Base(aJob, aMethod, {}) {}
143 
144  /* WithAnswer API */
145  Argument1 &answer() final { return this->arg1; }
146 };
147 
150 template <typename T>
151 using IsAsyncJob = typename std::conditional<
152  std::is_base_of<AsyncJob, T>::value,
153  std::true_type,
154  std::false_type
155  >::type;
156 
158 template <class Destination, typename Argument1, std::enable_if_t<!IsAsyncJob<Destination>::value, int> = 0>
160 callbackDialer(void (Destination::*method)(Argument1 &), Destination * const destination)
161 {
162  static_assert(!std::is_base_of<AsyncJob, Destination>::value, "wrong wrapper");
163  return UnaryCbcCallbackDialer<Destination, Argument1>(method, destination);
164 }
165 
167 template <class Destination, typename Argument1, std::enable_if_t<IsAsyncJob<Destination>::value, int> = 0>
169 callbackDialer(void (Destination::*method)(Argument1 &), Destination * const destination)
170 {
171  static_assert(std::is_base_of<AsyncJob, Destination>::value, "wrong wrapper");
172  return UnaryJobCallbackDialer<Destination, Argument1>(destination, method);
173 }
174 
176 template <typename Argument1>
178 callbackDialer(void (*destination)(Argument1 &))
179 {
180  return UnaryFunCallbackDialer<Argument1>(destination);
181 }
182 
185 template <class Call>
188 {
190 }
191 
195 #define asyncCallback(dbgSection, dbgLevel, method, object) \
196  AsyncCallback_(asyncCall((dbgSection), (dbgLevel), #method, \
197  callbackDialer(&method, (object))))
198 
199 // TODO: Use C++20 __VA_OPT__ to merge this with asyncCallback().
201 #define asyncCallbackFun(dbgSection, dbgLevel, function) \
202  AsyncCallback_(asyncCall((dbgSection), (dbgLevel), #function, \
203  callbackDialer(&function)))
204 
205 #endif /* SQUID_SRC_BASE_ASYNCCALLBACKS_H */
206 
UnaryFunCallbackDialer(Handler *const aHandler)
virtual ~WithAnswer()=default
void print(std::ostream &os) const final
AsyncCallback< typename Call::Dialer::Answer > AsyncCallback_(const RefCount< Call > &call)
bool canDial(AsyncCall &)
UnaryCbcCallbackDialer< Destination, Argument1 > callbackDialer(void(Destination::*method)(Argument1 &), Destination *const destination)
helper function to simplify UnaryCbcCallbackDialer creation
Argument1 & answer() final
callback results setter
Answer * answer_
a smart AsyncCall pointer for delivery of future results
CallDialer for single-parameter callback functions.
AsyncCallback()=default
~UnaryFunCallbackDialer() override=default
Argument1 & answer() final
callback results setter
void(Argument1 &) Handler
void dial(AsyncCall &)
Answer & answer()
~UnaryCbcCallbackDialer() override=default
AsyncCall::Pointer call_
callback carrying the answer
AsyncCall::Pointer release()
#define assert(EX)
Definition: assert.h:17
UnaryJobCallbackDialer(const CbcPointer< Job > &aJob, typename Base::Method aMethod)
typename std::conditional< std::is_base_of< AsyncJob, T >::value, std::true_type, std::false_type >::type IsAsyncJob
void dial(AsyncCall &)
UnaryCbcCallbackDialer(Method method, Destination *destination)
const AsyncCall & operator*() const
virtual Answer & answer()=0
callback results setter
Method method_
Destination method to call with the answer.
access to a callback result carried by an asynchronous CallDialer
Argument1 & answer() final
callback results setter
void(Destination::* Method)(Argument1 &)
AsyncCallback(const RefCount< Call > &call)
bool canDial(AsyncCall &)
Handler * handler
the function to call
void print(std::ostream &os) const final
const AsyncCall * operator->() const
CbcPointer< Destination > destination_
object to deliver the answer to
Argument1 arg1
actual call parameter

 

Introduction

Documentation

Support

Miscellaneous