GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/util/async.h
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 30 30 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 1714000 virtual ~CallbackBase() {}
24 virtual void operator()(const ParamT &value) const = 0;
25 };
26
27 template <>
28 class CallbackBase<void> {
29 public:
30 6 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 91 explicit Callback(CallbackFunction function) : function_(function) {}
50 619529 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 2 explicit Callback(CallbackFunction function) : function_(function) {}
62 5 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 1146 BoundCallback(CallbackMethod method, DelegateT *delegate) :
89 1146 delegate_(delegate),
90 1146 method_(method) {}
91
92
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 334997 times.
669991 void operator()(const ParamT &value) const { (delegate_->*method_)(value); }
93
94 private:
95 DelegateT* delegate_;
96 CallbackMethod method_;
97 };
98
99 template <class DelegateT>
100 class BoundCallback<void, DelegateT> : public CallbackBase<void> {
101 public:
102 typedef void (DelegateT::*CallbackMethod)();
103
104 4 BoundCallback(CallbackMethod method, DelegateT *delegate) :
105 4 delegate_(delegate), method_(method) {}
106
107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
12 void operator()() const { (delegate_->*method_)(); }
108
109 private:
110 DelegateT* delegate_;
111 CallbackMethod method_;
112 };
113
114
115 /**
116 * A BoundClosure works exactly the same as a BoundCallback (see above) but,
117 * allows for an opaque enclosure of an arbitrary chunk of user data on
118 * creation. When the closure is invoked the provided user data chunk is
119 * passed as a second argument to the specified callback method.
120 *
121 * Note: delegate must be still around when the closure is invoked!
122 *
123 * @param ParamT the type of the parameter to be passed to the callback
124 * @param DelegateT the <class name> of the object the member <member name>
125 * should be invoked in
126 * @param ClosureDataT the type of the user data chunk to be passed on invoke
127 */
128 template <typename ParamT, class DelegateT, typename ClosureDataT>
129 class BoundClosure : public CallbackBase<ParamT> {
130 public:
131 typedef void (DelegateT::*CallbackMethod)(const ParamT &value,
132 const ClosureDataT closure_data);
133
134 public:
135 1528137 BoundClosure(CallbackMethod method,
136 DelegateT *delegate,
137 ClosureDataT data) :
138 1528113 delegate_(delegate),
139 1528113 method_(method),
140
1/2
✓ Branch 2 taken 2618 times.
✗ Branch 3 not taken.
1528137 closure_data_(data) {}
141
142 1528633 void operator()(const ParamT &value) const {
143
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 856419 times.
✓ Branch 4 taken 2618 times.
✗ Branch 5 not taken.
1528633 (delegate_->*method_)(value, closure_data_);
144 1528646 }
145
146 private:
147 DelegateT* delegate_;
148 CallbackMethod method_;
149 const ClosureDataT closure_data_;
150 };
151
152 template <class DelegateT, typename ClosureDataT>
153 class BoundClosure<void, DelegateT, ClosureDataT> : public CallbackBase<void> {
154 public:
155 typedef void (DelegateT::*CallbackMethod)(const ClosureDataT closure_data);
156
157 public:
158 4 BoundClosure(CallbackMethod method,
159 DelegateT *delegate,
160 ClosureDataT data) :
161 4 delegate_(delegate), method_(method), closure_data_(data) {}
162
163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
4 void operator()() const { (delegate_->*method_)(closure_data_); }
164
165 private:
166 DelegateT* delegate_;
167 CallbackMethod method_;
168 const ClosureDataT closure_data_;
169 };
170
171
172 /**
173 * This template contains convenience functions to be inherited by classes pro-
174 * viding callback functionality. You can use this as a base class providing the
175 * callback parameter your class is going to process.
176 * Users of your class can profit from the static MakeCallback resp. MakeClosure
177 * methods to generated Callback objects. Later they can easily be passed back
178 * to your class.
179 *
180 * Note: the convenience methods return a pointer to a callback object. The user
181 * is responsible to clean up those pointers in some way. If it is a one-
182 * time callback, it makes sense to delete it inside the inheriting class
183 * once it was invoked.
184 *
185 * TODO: C++11 - Replace this functionality by lambdas
186 *
187 * @param ParamT the parameter type of the callbacks to be called
188 */
189 template <class ParamT>
190 class Callbackable {
191 public:
192 typedef CallbackBase<ParamT> CallbackTN;
193
194 public:
195 /**
196 * Produces a BoundClosure object that captures a closure value passed along
197 * to the invoked method.
198 *
199 * @param method Function pointer to the method to be called
200 * @param delegate The delegate object on which <method> will be called
201 * @param closure_data The closure data to be passed along to <method>
202 */
203 template <class DelegateT, typename ClosureDataT>
204 856102 static CallbackTN* MakeClosure(
205 typename BoundClosure<ParamT, DelegateT, ClosureDataT>::
206 CallbackMethod method,
207 DelegateT *delegate,
208 const ClosureDataT &closure_data)
209 {
210 856102 return new BoundClosure<ParamT, DelegateT, ClosureDataT>(method,
211 delegate,
212
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
858737 closure_data);
213 }
214
215 /**
216 * Produces a BoundCallback object that invokes a method on a delegate object.
217 *
218 * @param method Function pointer to the method to be called
219 * @param delegate The delegate object on which <method> will be called
220 */
221 template <class DelegateT>
222 585 static CallbackTN* MakeCallback(
223 typename BoundCallback<ParamT, DelegateT>::CallbackMethod method,
224 DelegateT *delegate) {
225 585 return new BoundCallback<ParamT, DelegateT>(method, delegate);
226 }
227
228 /**
229 * Produces a Callback object that invokes a static function or a globally de-
230 * fined C-like function.
231 *
232 * @param function Function pointer to the function to be invoked
233 */
234 87 static CallbackTN* MakeCallback(
235 typename Callback<ParamT>::CallbackFunction function) {
236 87 return new Callback<ParamT>(function);
237 }
238 };
239
240
241 /**
242 * Wrapper function to bind an arbitrary this* to a method call in a C-style
243 * spawned thread function.
244 * The method called by the ThreadProxy template is meant to look like this:
245 * void foo();
246 */
247 template <class DelegateT>
248 void ThreadProxy(DelegateT *delegate,
249 void (DelegateT::*method)()) {
250 (*delegate.*method)();
251 }
252
253
254
255 #ifdef CVMFS_NAMESPACE_GUARD
256 } // namespace CVMFS_NAMESPACE_GUARD
257 #endif
258
259 #endif // CVMFS_UTIL_ASYNC_H_
260