00001 #ifndef PROTON_WORK_QUEUE_HPP
00002 #define PROTON_WORK_QUEUE_HPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "./duration.hpp"
00026 #include "./fwd.hpp"
00027 #include "./function.hpp"
00028 #include "./internal/config.hpp"
00029 #include "./internal/export.hpp"
00030 #include "./internal/pn_unique_ptr.hpp"
00031
00032 #include <functional>
00033 #include <utility>
00034 #if PN_CPP_HAS_LAMBDAS && PN_CPP_HAS_VARIADIC_TEMPLATES
00035 #include <type_traits>
00036 #endif
00037
00038 struct pn_connection_t;
00039 struct pn_session_t;
00040 struct pn_link_t;
00041
00044
00045 namespace proton {
00046
00048
00049 namespace internal { namespace v03 {
00050
00051 struct invocable {
00052 invocable() {}
00053 virtual ~invocable() {}
00054
00055 virtual invocable& clone() const = 0;
00056 virtual void operator() () = 0;
00057 };
00058
00059 template <class T>
00060 struct invocable_cloner : invocable {
00061 virtual ~invocable_cloner() {}
00062 virtual invocable& clone() const {
00063 return *new T(static_cast<T const&>(*this));
00064 }
00065 };
00066
00067 struct invocable_wrapper {
00068 invocable_wrapper(): wrapped_(0) {}
00069 invocable_wrapper(const invocable_wrapper& w): wrapped_(&w.wrapped_->clone()) {}
00070 invocable_wrapper& operator=(const invocable_wrapper& that) {
00071 invocable_wrapper newthis(that);
00072 std::swap(wrapped_, newthis.wrapped_);
00073 return *this;
00074 }
00075 #if PN_CPP_HAS_RVALUE_REFERENCES
00076 invocable_wrapper(invocable_wrapper&& w): wrapped_(w.wrapped_) {}
00077 invocable_wrapper& operator=(invocable_wrapper&& that) {delete wrapped_; wrapped_ = that.wrapped_; return *this; }
00078 #endif
00079 ~invocable_wrapper() { delete wrapped_; }
00080
00081 invocable_wrapper(const invocable& i): wrapped_(&i.clone()) {}
00082 void operator()() { (*wrapped_)(); }
00083
00084 invocable* wrapped_;
00085 };
00086
00091 class work {
00092 public:
00094 work() {}
00095
00096 work(const invocable& i): item_(i) {}
00097
00099 void operator()() { item_(); }
00100
00101 ~work() {}
00102
00103 private:
00104 invocable_wrapper item_;
00105 };
00106
00107
00108
00109
00110 template <class R>
00111 struct work0 : public invocable_cloner<work0<R> > {
00112 R (* fn_)();
00113
00114 work0(R (* f)()) :
00115 fn_(f) {}
00116
00117 void operator()() {
00118 (*fn_)();
00119 }
00120 };
00121
00122 template <class R, class A>
00123 struct work1 : public invocable_cloner<work1<R,A> > {
00124 R (* fn_)(A);
00125 A a_;
00126
00127 work1(R (* t)(A), A a) :
00128 fn_(t), a_(a) {}
00129
00130 void operator()() {
00131 (*fn_)(a_);
00132 }
00133 };
00134
00135 template <class R, class A, class B>
00136 struct work2 : public invocable_cloner<work2<R,A,B> > {
00137 R (* fn_)(A, B);
00138 A a_;
00139 B b_;
00140
00141 work2(R (* t)(A, B), A a, B b) :
00142 fn_(t), a_(a), b_(b) {}
00143
00144 void operator()() {
00145 (*fn_)(a_, b_);
00146 }
00147 };
00148
00149 template <class R, class A, class B, class C>
00150 struct work3 : public invocable_cloner<work3<R,A,B,C> > {
00151 R (* fn_)(A, B, C);
00152 A a_;
00153 B b_;
00154 C c_;
00155
00156 work3(R (* t)(A, B, C), A a, B b, C c) :
00157 fn_(t), a_(a), b_(b), c_(c) {}
00158
00159 void operator()() {
00160 (*fn_)(a_, b_, c_);
00161 }
00162 };
00163
00164 template <class R, class T>
00165 struct work_pmf0 : public invocable_cloner<work_pmf0<R,T> > {
00166 T& holder_;
00167 R (T::* fn_)();
00168
00169 work_pmf0(R (T::* a)(), T& h) :
00170 holder_(h), fn_(a) {}
00171
00172 void operator()() {
00173 (holder_.*fn_)();
00174 }
00175 };
00176
00177 template <class R, class T, class A>
00178 struct work_pmf1 : public invocable_cloner<work_pmf1<R,T,A> > {
00179 T& holder_;
00180 R (T::* fn_)(A);
00181 A a_;
00182
00183 work_pmf1(R (T::* t)(A), T& h, A a) :
00184 holder_(h), fn_(t), a_(a) {}
00185
00186 void operator()() {
00187 (holder_.*fn_)(a_);
00188 }
00189 };
00190
00191 template <class R, class T, class A, class B>
00192 struct work_pmf2 : public invocable_cloner<work_pmf2<R,T,A,B> > {
00193 T& holder_;
00194 R (T::* fn_)(A, B);
00195 A a_;
00196 B b_;
00197
00198 work_pmf2(R (T::* t)(A, B), T& h, A a, B b) :
00199 holder_(h), fn_(t), a_(a), b_(b) {}
00200
00201 void operator()() {
00202 (holder_.*fn_)(a_, b_);
00203 }
00204 };
00205
00206 template <class R, class T, class A, class B, class C>
00207 struct work_pmf3 : public invocable_cloner<work_pmf3<R,T,A,B,C> > {
00208 T& holder_;
00209 R (T::* fn_)(A, B, C);
00210 A a_;
00211 B b_;
00212 C c_;
00213
00214 work_pmf3(R (T::* t)(A, B, C), T& h, A a, B b, C c) :
00215 holder_(h), fn_(t), a_(a), b_(b), c_(c) {}
00216
00217 void operator()() {
00218 (holder_.*fn_)(a_, b_, c_);
00219 }
00220 };
00221
00224 template <class R, class T>
00225 work make_work(R (T::*f)(), T* t) {
00226 return work_pmf0<R, T>(f, *t);
00227 }
00228
00229 template <class R, class T, class A>
00230 work make_work(R (T::*f)(A), T* t, A a) {
00231 return work_pmf1<R, T, A>(f, *t, a);
00232 }
00233
00234 template <class R, class T, class A, class B>
00235 work make_work(R (T::*f)(A, B), T* t, A a, B b) {
00236 return work_pmf2<R, T, A, B>(f, *t, a, b);
00237 }
00238
00239 template <class R, class T, class A, class B, class C>
00240 work make_work(R (T::*f)(A, B, C), T* t, A a, B b, C c) {
00241 return work_pmf3<R, T, A, B, C>(f, *t, a, b, c);
00242 }
00243
00244 template <class R>
00245 work make_work(R (*f)()) {
00246 return work0<R>(f);
00247 }
00248
00249 template <class R, class A>
00250 work make_work(R (*f)(A), A a) {
00251 return work1<R, A>(f, a);
00252 }
00253
00254 template <class R, class A, class B>
00255 work make_work(R (*f)(A, B), A a, B b) {
00256 return work2<R, A, B>(f, a, b);
00257 }
00258
00259 template <class R, class A, class B, class C>
00260 work make_work(R (*f)(A, B, C), A a, B b, C c) {
00261 return work3<R, A, B, C>(f, a, b, c);
00262 }
00263
00264 } }
00265
00266 #if PN_CPP_HAS_LAMBDAS && PN_CPP_HAS_VARIADIC_TEMPLATES
00267
00268 namespace internal { namespace v11 {
00269
00270 class work {
00271 public:
00273 work() {}
00274
00280 template <class T,
00281
00282 class = typename std::enable_if<!std::is_same<typename std::decay<T>::type,work>::value>::type
00283 >
00284 work(T&& f): item_(std::forward<T>(f)) {}
00285
00289 void operator()() { item_(); }
00290
00291 ~work() {}
00292
00293 private:
00294 std::function<void()> item_;
00295 };
00296
00304 template <class... Rest>
00305 work make_work(Rest&&... r) {
00306 return std::bind(std::forward<Rest>(r)...);
00307 }
00308
00309 } }
00310
00311 using internal::v11::work;
00312 using internal::v11::make_work;
00313
00314 #else
00315
00316 using internal::v03::work;
00317 using internal::v03::make_work;
00318
00319 #endif
00320
00322
00339 class PN_CPP_CLASS_EXTERN work_queue {
00341 class impl;
00342 work_queue& operator=(impl* i);
00344
00345 public:
00347 PN_CPP_EXTERN work_queue();
00348
00350 PN_CPP_EXTERN work_queue(container&);
00351
00352 PN_CPP_EXTERN ~work_queue();
00353
00362 PN_CPP_EXTERN bool add(work fn);
00363
00365 PN_CPP_EXTERN PN_CPP_DEPRECATED("Use 'work_queue::add(work)'") bool add(void_function0& fn);
00366
00375 PN_CPP_EXTERN void schedule(duration, work fn);
00376
00378 PN_CPP_EXTERN PN_CPP_DEPRECATED("Use 'work_queue::schedule(duration, work)'") void schedule(duration, void_function0& fn);
00379
00380 private:
00383 #if PN_CPP_HAS_LAMBDAS && PN_CPP_HAS_VARIADIC_TEMPLATES
00384 PN_CPP_EXTERN bool add(internal::v03::work fn);
00385 PN_CPP_EXTERN void schedule(duration, internal::v03::work fn);
00386 #endif
00387
00388 PN_CPP_EXTERN static work_queue& get(pn_connection_t*);
00389 PN_CPP_EXTERN static work_queue& get(pn_session_t*);
00390 PN_CPP_EXTERN static work_queue& get(pn_link_t*);
00391
00392 internal::pn_unique_ptr<impl> impl_;
00393
00395 friend class container;
00396 friend class io::connection_driver;
00398 };
00399
00400 }
00401
00402 #endif // PROTON_WORK_QUEUE_HPP