proton/work_queue.hpp

Go to the documentation of this file.
00001 #ifndef PROTON_WORK_QUEUE_HPP
00002 #define PROTON_WORK_QUEUE_HPP
00003 
00004 /*
00005  *
00006  * Licensed to the Apache Software Foundation (ASF) under one
00007  * or more contributor license agreements.  See the NOTICE file
00008  * distributed with this work for additional information
00009  * regarding copyright ownership.  The ASF licenses this file
00010  * to you under the Apache License, Version 2.0 (the
00011  * "License"); you may not use this file except in compliance
00012  * with the License.  You may obtain a copy of the License at
00013  *
00014  *   http://www.apache.org/licenses/LICENSE-2.0
00015  *
00016  * Unless required by applicable law or agreed to in writing,
00017  * software distributed under the License is distributed on an
00018  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
00019  * KIND, either express or implied.  See the License for the
00020  * specific language governing permissions and limitations
00021  * under the License.
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 // Utilities to make work from functions/member functions (C++03 version)
00108 // Lots of repetition to handle functions/member functions with up to 3 arguments
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 } } // internal::v03
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         // Make sure we don't match the copy or move constructors
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 } } // internal::v11
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 } // proton
00401 
00402 #endif // PROTON_WORK_QUEUE_HPP

Generated on 1 Jun 2020 for Qpid Proton C++ by  doxygen 1.6.1