Qpid Proton C++ API  0.18.1
work_queue.hpp
Go to the documentation of this file.
1 #ifndef PROTON_WORK_QUEUE_HPP
2 #define PROTON_WORK_QUEUE_HPP
3 
4 /*
5  *
6  * Licensed to the Apache Software Foundation (ASF) under one
7  * or more contributor license agreements. See the NOTICE file
8  * distributed with this work for additional information
9  * regarding copyright ownership. The ASF licenses this file
10  * to you under the Apache License, Version 2.0 (the
11  * "License"); you may not use this file except in compliance
12  * with the License. You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing,
17  * software distributed under the License is distributed on an
18  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19  * KIND, either express or implied. See the License for the
20  * specific language governing permissions and limitations
21  * under the License.
22  *
23  */
24 
25 #include "./duration.hpp"
26 #include "./fwd.hpp"
27 #include "./function.hpp"
28 #include "./internal/config.hpp"
29 #include "./internal/export.hpp"
30 #include "./internal/pn_unique_ptr.hpp"
31 
32 #include <functional>
33 #include <utility>
34 #if PN_CPP_HAS_LAMBDAS && PN_CPP_HAS_VARIADIC_TEMPLATES
35 #include <type_traits>
36 #endif
37 
38 struct pn_connection_t;
39 struct pn_session_t;
40 struct pn_link_t;
41 
44 
45 namespace proton {
46 
48 
49 namespace internal { namespace v03 {
50 
51 struct invocable {
52  invocable() {}
53  virtual ~invocable() {}
54 
55  virtual invocable& clone() const = 0;
56  virtual void operator() () = 0;
57 };
58 
59 template <class T>
60 struct invocable_cloner : invocable {
61  virtual ~invocable_cloner() {}
62  virtual invocable& clone() const {
63  return *new T(static_cast<T const&>(*this));
64  }
65 };
66 
67 struct invocable_wrapper {
68  invocable_wrapper(): wrapped_(0) {}
69  invocable_wrapper(const invocable_wrapper& w): wrapped_(&w.wrapped_->clone()) {}
70  invocable_wrapper& operator=(const invocable_wrapper& that) {
71  invocable_wrapper newthis(that);
72  std::swap(wrapped_, newthis.wrapped_);
73  return *this;
74  }
75 #if PN_CPP_HAS_RVALUE_REFERENCES
76  invocable_wrapper(invocable_wrapper&& w): wrapped_(w.wrapped_) {}
77  invocable_wrapper& operator=(invocable_wrapper&& that) {delete wrapped_; wrapped_ = that.wrapped_; return *this; }
78 #endif
79  ~invocable_wrapper() { delete wrapped_; }
80 
81  invocable_wrapper(const invocable& i): wrapped_(&i.clone()) {}
82  void operator()() { (*wrapped_)(); }
83 
84  invocable* wrapped_;
85 };
86 
91 class work {
92  public:
94  work() {}
95 
96  work(const invocable& i): item_(i) {}
97 
99  void operator()() { item_(); }
100 
101  ~work() {}
102 
103  private:
104  invocable_wrapper item_;
105 };
106 
107 // Utilities to make work from functions/member functions (C++03 version)
108 // Lots of repetition to handle functions/member functions with up to 3 arguments
109 
110 template <class R>
111 struct work0 : public invocable_cloner<work0<R> > {
112  R (* fn_)();
113 
114  work0(R (* f)()) :
115  fn_(f) {}
116 
117  void operator()() {
118  (*fn_)();
119  }
120 };
121 
122 template <class R, class A>
123 struct work1 : public invocable_cloner<work1<R,A> > {
124  R (* fn_)(A);
125  A a_;
126 
127  work1(R (* t)(A), A a) :
128  fn_(t), a_(a) {}
129 
130  void operator()() {
131  (*fn_)(a_);
132  }
133 };
134 
135 template <class R, class A, class B>
136 struct work2 : public invocable_cloner<work2<R,A,B> > {
137  R (* fn_)(A, B);
138  A a_;
139  B b_;
140 
141  work2(R (* t)(A, B), A a, B b) :
142  fn_(t), a_(a), b_(b) {}
143 
144  void operator()() {
145  (*fn_)(a_, b_);
146  }
147 };
148 
149 template <class R, class A, class B, class C>
150 struct work3 : public invocable_cloner<work3<R,A,B,C> > {
151  R (* fn_)(A, B, C);
152  A a_;
153  B b_;
154  C c_;
155 
156  work3(R (* t)(A, B, C), A a, B b, C c) :
157  fn_(t), a_(a), b_(b), c_(c) {}
158 
159  void operator()() {
160  (*fn_)(a_, b_, c_);
161  }
162 };
163 
164 template <class R, class T>
165 struct work_pmf0 : public invocable_cloner<work_pmf0<R,T> > {
166  T& holder_;
167  R (T::* fn_)();
168 
169  work_pmf0(R (T::* a)(), T& h) :
170  holder_(h), fn_(a) {}
171 
172  void operator()() {
173  (holder_.*fn_)();
174  }
175 };
176 
177 template <class R, class T, class A>
178 struct work_pmf1 : public invocable_cloner<work_pmf1<R,T,A> > {
179  T& holder_;
180  R (T::* fn_)(A);
181  A a_;
182 
183  work_pmf1(R (T::* t)(A), T& h, A a) :
184  holder_(h), fn_(t), a_(a) {}
185 
186  void operator()() {
187  (holder_.*fn_)(a_);
188  }
189 };
190 
191 template <class R, class T, class A, class B>
192 struct work_pmf2 : public invocable_cloner<work_pmf2<R,T,A,B> > {
193  T& holder_;
194  R (T::* fn_)(A, B);
195  A a_;
196  B b_;
197 
198  work_pmf2(R (T::* t)(A, B), T& h, A a, B b) :
199  holder_(h), fn_(t), a_(a), b_(b) {}
200 
201  void operator()() {
202  (holder_.*fn_)(a_, b_);
203  }
204 };
205 
206 template <class R, class T, class A, class B, class C>
207 struct work_pmf3 : public invocable_cloner<work_pmf3<R,T,A,B,C> > {
208  T& holder_;
209  R (T::* fn_)(A, B, C);
210  A a_;
211  B b_;
212  C c_;
213 
214  work_pmf3(R (T::* t)(A, B, C), T& h, A a, B b, C c) :
215  holder_(h), fn_(t), a_(a), b_(b), c_(c) {}
216 
217  void operator()() {
218  (holder_.*fn_)(a_, b_, c_);
219  }
220 };
221 
224 template <class R, class T>
225 work make_work(R (T::*f)(), T* t) {
226  return work_pmf0<R, T>(f, *t);
227 }
228 
229 template <class R, class T, class A>
230 work make_work(R (T::*f)(A), T* t, A a) {
231  return work_pmf1<R, T, A>(f, *t, a);
232 }
233 
234 template <class R, class T, class A, class B>
235 work make_work(R (T::*f)(A, B), T* t, A a, B b) {
236  return work_pmf2<R, T, A, B>(f, *t, a, b);
237 }
238 
239 template <class R, class T, class A, class B, class C>
240 work make_work(R (T::*f)(A, B, C), T* t, A a, B b, C c) {
241  return work_pmf3<R, T, A, B, C>(f, *t, a, b, c);
242 }
243 
244 template <class R>
245 work make_work(R (*f)()) {
246  return work0<R>(f);
247 }
248 
249 template <class R, class A>
250 work make_work(R (*f)(A), A a) {
251  return work1<R, A>(f, a);
252 }
253 
254 template <class R, class A, class B>
255 work make_work(R (*f)(A, B), A a, B b) {
256  return work2<R, A, B>(f, a, b);
257 }
258 
259 template <class R, class A, class B, class C>
260 work make_work(R (*f)(A, B, C), A a, B b, C c) {
261  return work3<R, A, B, C>(f, a, b, c);
262 }
263 
264 } } // internal::v03
265 
266 #if PN_CPP_HAS_LAMBDAS && PN_CPP_HAS_VARIADIC_TEMPLATES
267 
268 namespace internal { namespace v11 {
269 
270 class work {
271  public:
273  work() {}
274 
280  template <class T,
281  // Make sure we don't match the copy or move constructors
282  class = typename std::enable_if<!std::is_same<typename std::decay<T>::type,work>::value>::type
283  >
284  work(T&& f): item_(std::forward<T>(f)) {}
285 
289  void operator()() { item_(); }
290 
291  ~work() {}
292 
293  private:
294  std::function<void()> item_;
295 };
296 
304 template <class... Rest>
305 work make_work(Rest&&... r) {
306  return std::bind(std::forward<Rest>(r)...);
307 }
308 
309 } } // internal::v11
310 
311 using internal::v11::work;
312 using internal::v11::make_work;
313 
314 #else
315 
316 using internal::v03::work;
317 using internal::v03::make_work;
318 
319 #endif
320 
322 
339 class PN_CPP_CLASS_EXTERN work_queue {
341  class impl;
342  work_queue& operator=(impl* i);
344 
345  public:
347  PN_CPP_EXTERN work_queue();
348 
350  PN_CPP_EXTERN work_queue(container&);
351 
352  PN_CPP_EXTERN ~work_queue();
353 
362  PN_CPP_EXTERN bool add(work fn);
363 
365  PN_CPP_EXTERN PN_CPP_DEPRECATED("Use 'work_queue::add(work)'") bool add(void_function0& fn);
366 
368  // This is a hack to ensure that the C++03 version is declared
369  // only during the compilation of the library
370 #if PN_CPP_HAS_LAMBDAS && PN_CPP_HAS_VARIADIC_TEMPLATES && defined(qpid_proton_cpp_EXPORTS)
371  PN_CPP_EXTERN bool add(internal::v03::work fn);
372 #endif
373 
383  PN_CPP_EXTERN void schedule(duration, work fn);
384 
386  PN_CPP_EXTERN PN_CPP_DEPRECATED("Use 'work_queue::schedule(duration, work)'") void schedule(duration, void_function0& fn);
387 
389  // This is a hack to ensure that the C++03 version is declared
390  // only during the compilation of the library
391 #if PN_CPP_HAS_LAMBDAS && PN_CPP_HAS_VARIADIC_TEMPLATES && defined(qpid_proton_cpp_EXPORTS)
392  PN_CPP_EXTERN void schedule(duration, internal::v03::work fn);
393 #endif
394 
396  private:
397  PN_CPP_EXTERN static work_queue& get(pn_connection_t*);
398  PN_CPP_EXTERN static work_queue& get(pn_session_t*);
399  PN_CPP_EXTERN static work_queue& get(pn_link_t*);
400 
401  internal::pn_unique_ptr<impl> impl_;
402 
404  friend class container;
405  friend class io::connection_driver;
407 };
408 
409 } // proton
410 
411 #endif // PROTON_WORK_QUEUE_HPP
A top-level container of connections, sessions, and links.
Definition: container.hpp:55
void swap(map< K, T > &, map< K, T > &)
Swap proton::map instances.
A span of time in milliseconds.
Definition: duration.hpp:39
Forward declarations.
STL namespace.
A span of time in milliseconds.
Deprecated - Use the API in work_queue.hpp.
Unsettled API - A context for thread-safe execution of work.
Definition: work_queue.hpp:339
Unsettled API - An AMQP driver for a single connection.
Definition: connection_driver.hpp:93
The main Proton namespace.
Definition: annotation_key.hpp:33