Qpid Proton C++ API  0.37.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/export.hpp"
29 
30 #include <functional>
31 #include <memory>
32 #include <type_traits>
33 #include <utility>
34 
35 struct pn_connection_t;
36 struct pn_session_t;
37 struct pn_link_t;
38 
41 
42 namespace proton {
43 
45 
46 namespace internal { namespace v03 {
47 
48 struct invocable {
49  invocable() = default;
50  virtual ~invocable() = default;
51 
52  virtual invocable& clone() const = 0;
53  virtual void operator() () = 0;
54 };
55 
56 template <class T>
57 struct invocable_cloner : invocable {
58  virtual ~invocable_cloner() = default;
59  virtual invocable& clone() const {
60  return *new T(static_cast<T const&>(*this));
61  }
62 };
63 
64 struct invocable_wrapper {
65  invocable_wrapper(): wrapped_(0) {}
66  invocable_wrapper(const invocable_wrapper& w): wrapped_(&w.wrapped_->clone()) {}
67  invocable_wrapper& operator=(const invocable_wrapper& that) {
68  invocable_wrapper newthis(that);
69  std::swap(wrapped_, newthis.wrapped_);
70  return *this;
71  }
72  invocable_wrapper(invocable_wrapper&& w): wrapped_(w.wrapped_) {}
73  invocable_wrapper& operator=(invocable_wrapper&& that) {delete wrapped_; wrapped_ = that.wrapped_; return *this; }
74  ~invocable_wrapper() { delete wrapped_; }
75 
76  invocable_wrapper(const invocable& i): wrapped_(&i.clone()) {}
77  void operator()() { (*wrapped_)(); }
78 
79  invocable* wrapped_;
80 };
81 
86 class work {
87  public:
89  work() = default;
90 
91  work(const invocable& i): item_(i) {}
92 
94  void operator()() { item_(); }
95 
96  ~work() = default;
97 
98  private:
99  invocable_wrapper item_;
100 };
101 
102 // Utilities to make work from functions/member functions (C++03 version)
103 // Lots of repetition to handle functions/member functions with up to 3 arguments
104 
105 template <class R>
106 struct work0 : public invocable_cloner<work0<R> > {
107  R (* fn_)();
108 
109  work0(R (* f)()) :
110  fn_(f) {}
111 
112  void operator()() {
113  (*fn_)();
114  }
115 };
116 
117 template <class R, class A>
118 struct work1 : public invocable_cloner<work1<R,A> > {
119  R (* fn_)(A);
120  A a_;
121 
122  work1(R (* t)(A), A a) :
123  fn_(t), a_(a) {}
124 
125  void operator()() {
126  (*fn_)(a_);
127  }
128 };
129 
130 template <class R, class A, class B>
131 struct work2 : public invocable_cloner<work2<R,A,B> > {
132  R (* fn_)(A, B);
133  A a_;
134  B b_;
135 
136  work2(R (* t)(A, B), A a, B b) :
137  fn_(t), a_(a), b_(b) {}
138 
139  void operator()() {
140  (*fn_)(a_, b_);
141  }
142 };
143 
144 template <class R, class A, class B, class C>
145 struct work3 : public invocable_cloner<work3<R,A,B,C> > {
146  R (* fn_)(A, B, C);
147  A a_;
148  B b_;
149  C c_;
150 
151  work3(R (* t)(A, B, C), A a, B b, C c) :
152  fn_(t), a_(a), b_(b), c_(c) {}
153 
154  void operator()() {
155  (*fn_)(a_, b_, c_);
156  }
157 };
158 
159 template <class R, class T>
160 struct work_pmf0 : public invocable_cloner<work_pmf0<R,T> > {
161  T& holder_;
162  R (T::* fn_)();
163 
164  work_pmf0(R (T::* a)(), T& h) :
165  holder_(h), fn_(a) {}
166 
167  void operator()() {
168  (holder_.*fn_)();
169  }
170 };
171 
172 template <class R, class T, class A>
173 struct work_pmf1 : public invocable_cloner<work_pmf1<R,T,A> > {
174  T& holder_;
175  R (T::* fn_)(A);
176  A a_;
177 
178  work_pmf1(R (T::* t)(A), T& h, A a) :
179  holder_(h), fn_(t), a_(a) {}
180 
181  void operator()() {
182  (holder_.*fn_)(a_);
183  }
184 };
185 
186 template <class R, class T, class A, class B>
187 struct work_pmf2 : public invocable_cloner<work_pmf2<R,T,A,B> > {
188  T& holder_;
189  R (T::* fn_)(A, B);
190  A a_;
191  B b_;
192 
193  work_pmf2(R (T::* t)(A, B), T& h, A a, B b) :
194  holder_(h), fn_(t), a_(a), b_(b) {}
195 
196  void operator()() {
197  (holder_.*fn_)(a_, b_);
198  }
199 };
200 
201 template <class R, class T, class A, class B, class C>
202 struct work_pmf3 : public invocable_cloner<work_pmf3<R,T,A,B,C> > {
203  T& holder_;
204  R (T::* fn_)(A, B, C);
205  A a_;
206  B b_;
207  C c_;
208 
209  work_pmf3(R (T::* t)(A, B, C), T& h, A a, B b, C c) :
210  holder_(h), fn_(t), a_(a), b_(b), c_(c) {}
211 
212  void operator()() {
213  (holder_.*fn_)(a_, b_, c_);
214  }
215 };
216 
219 template <class R, class T>
220 work make_work(R (T::*f)(), T* t) {
221  return work_pmf0<R, T>(f, *t);
222 }
223 
224 template <class R, class T, class A>
225 work make_work(R (T::*f)(A), T* t, A a) {
226  return work_pmf1<R, T, A>(f, *t, a);
227 }
228 
229 template <class R, class T, class A, class B>
230 work make_work(R (T::*f)(A, B), T* t, A a, B b) {
231  return work_pmf2<R, T, A, B>(f, *t, a, b);
232 }
233 
234 template <class R, class T, class A, class B, class C>
235 work make_work(R (T::*f)(A, B, C), T* t, A a, B b, C c) {
236  return work_pmf3<R, T, A, B, C>(f, *t, a, b, c);
237 }
238 
239 template <class R>
240 work make_work(R (*f)()) {
241  return work0<R>(f);
242 }
243 
244 template <class R, class A>
245 work make_work(R (*f)(A), A a) {
246  return work1<R, A>(f, a);
247 }
248 
249 template <class R, class A, class B>
250 work make_work(R (*f)(A, B), A a, B b) {
251  return work2<R, A, B>(f, a, b);
252 }
253 
254 template <class R, class A, class B, class C>
255 work make_work(R (*f)(A, B, C), A a, B b, C c) {
256  return work3<R, A, B, C>(f, a, b, c);
257 }
258 
259 } } // internal::v03
260 
261 
262 namespace internal { namespace v11 {
263 
264 class work {
265  public:
267  work() = default;
268 
274  template <class T,
275  // Make sure we don't match the copy or move constructors
276  class = typename std::enable_if<!std::is_same<typename std::decay<T>::type,work>::value>::type
277  >
278  work(T&& f): item_(std::forward<T>(f)) {}
279 
283  void operator()() { item_(); }
284 
285  ~work() = default;
286 
287  private:
288  std::function<void()> item_;
289 };
290 
298 template <class... Rest>
299 work make_work(Rest&&... r) {
300  return std::bind(std::forward<Rest>(r)...);
301 }
302 
303 } } // internal::v11
304 
305 using internal::v11::work;
306 using internal::v11::make_work;
307 
308 
310 
327 class PN_CPP_CLASS_EXTERN work_queue {
329  class impl;
330  work_queue& operator=(impl* i);
332 
333  public:
335  PN_CPP_EXTERN work_queue();
336 
338  PN_CPP_EXTERN work_queue(container&);
339 
340  PN_CPP_EXTERN ~work_queue();
341 
350  PN_CPP_EXTERN bool add(work fn);
351 
353  PN_CPP_EXTERN PN_CPP_DEPRECATED("Use 'work_queue::add(work)'") bool add(void_function0& fn);
354 
363  PN_CPP_EXTERN void schedule(duration, work fn);
364 
366  PN_CPP_EXTERN PN_CPP_DEPRECATED("Use 'work_queue::schedule(duration, work)'") void schedule(duration, void_function0& fn);
367 
368  private:
371  PN_CPP_EXTERN bool add(internal::v03::work fn);
372  PN_CPP_EXTERN void schedule(duration, internal::v03::work fn);
373 
374  PN_CPP_EXTERN static work_queue& get(pn_connection_t*);
375  PN_CPP_EXTERN static work_queue& get(pn_session_t*);
376  PN_CPP_EXTERN static work_queue& get(pn_link_t*);
377 
378  std::unique_ptr<impl> impl_;
379 
381  friend class container;
382  friend class io::connection_driver;
384 };
385 
386 } // proton
387 
388 #endif // PROTON_WORK_QUEUE_HPP
A top-level container of connections, sessions, and links.
Definition: container.hpp:49
A span of time in milliseconds.
Definition: duration.hpp:39
Unsettled API - A context for thread-safe execution of work.
Definition: work_queue.hpp:327
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.