GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/util/async.h Lines: 33 33 100.0 %
Date: 2019-02-03 02:48:13 Branches: 24 50 48.0 %

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
590858
class CallbackBase {
22
 public:
23

590799
  virtual ~CallbackBase() {}
24
  virtual void operator()(const ParamT &value) const = 0;
25
};
26
27
template <>
28
6
class CallbackBase<void> {
29
 public:
30
3
  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

305
class Callback : public CallbackBase<ParamT> {
46
 public:
47
  typedef void (*CallbackFunction)(const ParamT &value);
48
49
154
  explicit Callback(CallbackFunction function) : function_(function) {}
50
5919
  void operator()(const ParamT &value) const { function_(value); }
51
52
 private:
53
  CallbackFunction function_;
54
};
55
56
template <>
57
1
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


498
class BoundCallback : public CallbackBase<ParamT> {
85
 public:
86
  typedef void (DelegateT::*CallbackMethod)(const ParamT &value);
87
88
306
  BoundCallback(CallbackMethod method, DelegateT *delegate) :
89
    delegate_(delegate),
90
306
    method_(method) {}
91
92

86058
  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
2
  BoundCallback(CallbackMethod method, DelegateT *delegate) :
105
2
    delegate_(delegate), method_(method) {}
106
107

6
  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


1180794
class BoundClosure : public CallbackBase<ParamT> {
130
 public:
131
  typedef void (DelegateT::*CallbackMethod)(const ParamT        &value,
132
                                            const ClosureDataT   closure_data);
133
134
 public:
135
590398
  BoundClosure(CallbackMethod  method,
136
               DelegateT      *delegate,
137
               ClosureDataT    data) :
138
    delegate_(delegate),
139
    method_(method),
140
590398
    closure_data_(data) {}
141
142
590407
  void operator()(const ParamT &value) const {
143

590407
    (delegate_->*method_)(value, closure_data_);
144
590407
  }
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
2
  BoundClosure(CallbackMethod  method,
159
               DelegateT      *delegate,
160
               ClosureDataT    data) :
161
2
    delegate_(delegate), method_(method), closure_data_(data) {}
162
163

2
  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
766
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
590398
  static CallbackTN* MakeClosure(
205
    typename BoundClosure<ParamT, DelegateT, ClosureDataT>::
206
             CallbackMethod method,
207
    DelegateT *delegate,
208
    const ClosureDataT &closure_data)
209
  {
210
    return new BoundClosure<ParamT, DelegateT, ClosureDataT>(method,
211
                                                             delegate,
212
590398
                                                             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
306
  static CallbackTN* MakeCallback(
223
        typename BoundCallback<ParamT, DelegateT>::CallbackMethod method,
224
        DelegateT *delegate) {
225
306
    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
154
  static CallbackTN* MakeCallback(
235
        typename Callback<ParamT>::CallbackFunction function) {
236
154
    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_