Qpid Proton C++ 0.33.0
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
38struct pn_connection_t;
39struct pn_session_t;
40struct pn_link_t;
41
44
45namespace proton {
46
48
49namespace internal { namespace v03 {
50
51struct invocable {
52 invocable() {}
53 virtual ~invocable() {}
54
55 virtual invocable& clone() const = 0;
56 virtual void operator() () = 0;
57};
58
59template <class T>
60struct invocable_cloner : invocable {
61 virtual ~invocable_cloner() {}
62 virtual invocable& clone() const {
63 return *new T(static_cast<T const&>(*this));
64 }
65};
66
67struct 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
91class 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
110template <class R>
111struct 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
122template <class R, class A>
123struct 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
135template <class R, class A, class B>
136struct 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
149template <class R, class A, class B, class C>
150struct 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
164template <class R, class T>
165struct 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
177template <class R, class T, class A>
178struct 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
191template <class R, class T, class A, class B>
192struct 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
206template <class R, class T, class A, class B, class C>
207struct 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
224template <class R, class T>
225work make_work(R (T::*f)(), T* t) {
226 return work_pmf0<R, T>(f, *t);
227}
228
229template <class R, class T, class A>
230work make_work(R (T::*f)(A), T* t, A a) {
231 return work_pmf1<R, T, A>(f, *t, a);
232}
233
234template <class R, class T, class A, class B>
235work 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
239template <class R, class T, class A, class B, class C>
240work 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
244template <class R>
245work make_work(R (*f)()) {
246 return work0<R>(f);
247}
248
249template <class R, class A>
250work make_work(R (*f)(A), A a) {
251 return work1<R, A>(f, a);
252}
253
254template <class R, class A, class B>
255work make_work(R (*f)(A, B), A a, B b) {
256 return work2<R, A, B>(f, a, b);
257}
258
259template <class R, class A, class B, class C>
260work 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
268namespace internal { namespace v11 {
269
270class 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
304template <class... Rest>
305work make_work(Rest&&... r) {
306 return std::bind(std::forward<Rest>(r)...);
307}
308
309} } // internal::v11
310
311using internal::v11::work;
312using internal::v11::make_work;
313
314#else
315
316using internal::v03::work;
317using internal::v03::make_work;
318
319#endif
320
322
339class 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
375 PN_CPP_EXTERN void schedule(duration, work fn);
376
378 PN_CPP_EXTERN PN_CPP_DEPRECATED("Use 'work_queue::schedule(duration, work)'") void schedule(duration, void_function0& fn);
379
380 private:
383#if PN_CPP_HAS_LAMBDAS && PN_CPP_HAS_VARIADIC_TEMPLATES
384 PN_CPP_EXTERN bool add(internal::v03::work fn);
385 PN_CPP_EXTERN void schedule(duration, internal::v03::work fn);
386#endif
387
388 PN_CPP_EXTERN static work_queue& get(pn_connection_t*);
389 PN_CPP_EXTERN static work_queue& get(pn_session_t*);
390 PN_CPP_EXTERN static work_queue& get(pn_link_t*);
391
392 internal::pn_unique_ptr<impl> impl_;
393
395 friend class container;
396 friend class io::connection_driver;
398};
399
400} // proton
401
402#endif // PROTON_WORK_QUEUE_HPP
A top-level container of connections, sessions, and links.
Definition: container.hpp:50
A span of time in milliseconds.
Definition: duration.hpp:39
Unsettled API - An AMQP driver for a single connection.
Definition: connection_driver.hpp:94
Unsettled API - A context for thread-safe execution of work.
Definition: work_queue.hpp:339
work_queue()
Unsettled API - Create a work queue.
bool add(work fn)
Unsettled API - Add work fn to the work queue.
work_queue(container &)
Unsettled API - Create a work queue backed by a container.
A span of time in milliseconds.
Deprecated - Use the API in work_queue.hpp.
Forward declarations.
The main Proton namespace.
Definition: annotation_key.hpp:33
T get(const scalar &s)
Get a contained value of type T.
Definition: scalar.hpp:60
void swap(map< K, T > &, map< K, T > &)
Swap proton::map instances.