GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/util/async.h
Date: 2025-06-22 02:36:02
Exec Total Coverage
Lines: 27 27 100.0%
Branches: 8 14 57.1%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #ifndef CVMFS_UTIL_ASYNC_H_
6 #define CVMFS_UTIL_ASYNC_H_
7
8 #ifdef CVMFS_NAMESPACE_GUARD
9 namespace CVMFS_NAMESPACE_GUARD {
10 #endif
11
12 /**
13 * Encapsulates a callback function that handles asynchronous responses.
14 *
15 * This is an abstract base class for two different callback function objects.
16 * There are two specializations:
17 * --> 1. for static members or global C-like functions
18 * --> 2. for member functions of arbitrary objects
19 */
20 template<typename ParamT>
21 class CallbackBase {
22 public:
23 20413032 virtual ~CallbackBase() { }
24 virtual void operator()(const ParamT &value) const = 0;
25 };
26
27 template<>
28 class CallbackBase<void> {
29 public:
30 90 virtual ~CallbackBase() { }
31 virtual void operator()() const = 0;
32 };
33
34 /**
35 * This callback function object can be used to call static members or global
36 * functions with the following signature:
37 * void <name>(ParamT <parameter>);
38 *
39 * TODO: One might use varidic templates once C++11 will be supported, in order
40 * to allow for more than one parameter to be passed to the callback.
41 *
42 * @param ParamT the type of the parameter to be passed to the callback
43 */
44 template<typename ParamT>
45 class Callback : public CallbackBase<ParamT> {
46 public:
47 typedef void (*CallbackFunction)(const ParamT &value);
48
49 2645 explicit Callback(CallbackFunction function) : function_(function) { }
50 18313873 void operator()(const ParamT &value) const { function_(value); }
51
52 private:
53 CallbackFunction function_;
54 };
55
56 template<>
57 class Callback<void> : public CallbackBase<void> {
58 public:
59 typedef void (*CallbackFunction)();
60
61 30 explicit Callback(CallbackFunction function) : function_(function) { }
62 75 void operator()() const { function_(); }
63
64 private:
65 CallbackFunction function_;
66 };
67
68
69 /**
70 * A BoundCallback can be used to call a member of an arbitrary object as a
71 * callback.
72 * The member must have the following interface:
73 * void <DelegateT>::<member name>(ParamT <parameter>);
74 *
75 * Note: it is the responsibility of the user to ensure that the bound object
76 * for `delegate` remains alive in the whole time this callback might be
77 * invoked.
78 *
79 * @param ParamT the type of the parameter to be passed to the callback
80 * @param DelegateT the <class name> of the object the member <member name>
81 * should be invoked in
82 */
83 template<typename ParamT, class DelegateT>
84 class BoundCallback : public CallbackBase<ParamT> {
85 public:
86 typedef void (DelegateT::*CallbackMethod)(const ParamT &value);
87
88 29643 BoundCallback(CallbackMethod method, DelegateT *delegate)
89 29643 : delegate_(delegate), method_(method) { }
90
91
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 1067174 times.
2134265 void operator()(const ParamT &value) const { (delegate_->*method_)(value); }
92
93 private:
94 DelegateT *delegate_;
95 CallbackMethod method_;
96 };
97
98 template<class DelegateT>
99 class BoundCallback<void, DelegateT> : public CallbackBase<void> {
100 public:
101 typedef void (DelegateT::*CallbackMethod)();
102
103 60 BoundCallback(CallbackMethod method, DelegateT *delegate)
104 60 : delegate_(delegate), method_(method) { }
105
106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
180 void operator()() const { (delegate_->*method_)(); }
107
108 private:
109 DelegateT *delegate_;
110 CallbackMethod method_;
111 };
112
113
114 /**
115 * A BoundClosure works exactly the same as a BoundCallback (see above) but,
116 * allows for an opaque enclosure of an arbitrary chunk of user data on
117 * creation. When the closure is invoked the provided user data chunk is
118 * passed as a second argument to the specified callback method.
119 *
120 * Note: delegate must be still around when the closure is invoked!
121 *
122 * @param ParamT the type of the parameter to be passed to the callback
123 * @param DelegateT the <class name> of the object the member <member name>
124 * should be invoked in
125 * @param ClosureDataT the type of the user data chunk to be passed on invoke
126 */
127 template<typename ParamT, class DelegateT, typename ClosureDataT>
128 class BoundClosure : public CallbackBase<ParamT> {
129 public:
130 typedef void (DelegateT::*CallbackMethod)(const ParamT &value,
131 const ClosureDataT closure_data);
132
133 public:
134 11380271 BoundClosure(CallbackMethod method, DelegateT *delegate, ClosureDataT data)
135
1/2
✓ Branch 2 taken 81158 times.
✗ Branch 3 not taken.
11380271 : delegate_(delegate), method_(method), closure_data_(data) { }
136
137 11381046 void operator()(const ParamT &value) const {
138
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10192438 times.
✓ Branch 4 taken 81158 times.
✗ Branch 5 not taken.
11381046 (delegate_->*method_)(value, closure_data_);
139 11381634 }
140
141 private:
142 DelegateT *delegate_;
143 CallbackMethod method_;
144 const ClosureDataT closure_data_;
145 };
146
147 template<class DelegateT, typename ClosureDataT>
148 class BoundClosure<void, DelegateT, ClosureDataT> : public CallbackBase<void> {
149 public:
150 typedef void (DelegateT::*CallbackMethod)(const ClosureDataT closure_data);
151
152 public:
153 60 BoundClosure(CallbackMethod method, DelegateT *delegate, ClosureDataT data)
154 60 : delegate_(delegate), method_(method), closure_data_(data) { }
155
156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
60 void operator()() const { (delegate_->*method_)(closure_data_); }
157
158 private:
159 DelegateT *delegate_;
160 CallbackMethod method_;
161 const ClosureDataT closure_data_;
162 };
163
164
165 /**
166 * This template contains convenience functions to be inherited by classes pro-
167 * viding callback functionality. You can use this as a base class providing the
168 * callback parameter your class is going to process.
169 * Users of your class can profit from the static MakeCallback resp. MakeClosure
170 * methods to generated Callback objects. Later they can easily be passed back
171 * to your class.
172 *
173 * Note: the convenience methods return a pointer to a callback object. The user
174 * is responsible to clean up those pointers in some way. If it is a one-
175 * time callback, it makes sense to delete it inside the inheriting class
176 * once it was invoked.
177 *
178 * TODO: C++11 - Replace this functionality by lambdas
179 *
180 * @param ParamT the parameter type of the callbacks to be called
181 */
182 template<class ParamT>
183 class Callbackable {
184 public:
185 typedef CallbackBase<ParamT> CallbackTN;
186
187 public:
188 /**
189 * Produces a BoundClosure object that captures a closure value passed along
190 * to the invoked method.
191 *
192 * @param method Function pointer to the method to be called
193 * @param delegate The delegate object on which <method> will be called
194 * @param closure_data The closure data to be passed along to <method>
195 */
196 template<class DelegateT, typename ClosureDataT>
197 10193644 static CallbackTN *MakeClosure(
198 typename BoundClosure<ParamT, DelegateT, ClosureDataT>::CallbackMethod
199 method,
200 DelegateT *delegate,
201 const ClosureDataT &closure_data) {
202 10193644 return new BoundClosure<ParamT, DelegateT, ClosureDataT>(
203
1/2
✓ Branch 1 taken 893 times.
✗ Branch 2 not taken.
10276555 method, delegate, closure_data);
204 }
205
206 /**
207 * Produces a BoundCallback object that invokes a method on a delegate object.
208 *
209 * @param method Function pointer to the method to be called
210 * @param delegate The delegate object on which <method> will be called
211 */
212 template<class DelegateT>
213 15272 static CallbackTN *MakeCallback(
214 typename BoundCallback<ParamT, DelegateT>::CallbackMethod method,
215 DelegateT *delegate) {
216 15272 return new BoundCallback<ParamT, DelegateT>(method, delegate);
217 }
218
219 /**
220 * Produces a Callback object that invokes a static function or a globally de-
221 * fined C-like function.
222 *
223 * @param function Function pointer to the function to be invoked
224 */
225 2575 static CallbackTN *MakeCallback(
226 typename Callback<ParamT>::CallbackFunction function) {
227 2575 return new Callback<ParamT>(function);
228 }
229 };
230
231
232 /**
233 * Wrapper function to bind an arbitrary this* to a method call in a C-style
234 * spawned thread function.
235 * The method called by the ThreadProxy template is meant to look like this:
236 * void foo();
237 */
238 template<class DelegateT>
239 void ThreadProxy(DelegateT *delegate, void (DelegateT::*method)()) {
240 (*delegate.*method)();
241 }
242
243
244 #ifdef CVMFS_NAMESPACE_GUARD
245 } // namespace CVMFS_NAMESPACE_GUARD
246 #endif
247
248 #endif // CVMFS_UTIL_ASYNC_H_
249