work_queue.hpp
Go to the documentation of this file.
#ifndef PROTON_WORK_QUEUE_HPP
#define PROTON_WORK_QUEUE_HPP
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
#include "./duration.hpp"
#include "./fwd.hpp"
#include "./function.hpp"
#include "./internal/config.hpp"
#include "./internal/export.hpp"
#include "./internal/pn_unique_ptr.hpp"
#include <functional>
#include <utility>
#if PN_CPP_HAS_LAMBDAS && PN_CPP_HAS_VARIADIC_TEMPLATES
#include <type_traits>
#endif
struct pn_connection_t;
struct pn_session_t;
struct pn_link_t;
namespace proton {
namespace internal { namespace v03 {
struct invocable {
invocable() {}
virtual ~invocable() {}
virtual invocable& clone() const = 0;
virtual void operator() () = 0;
};
template <class T>
struct invocable_cloner : invocable {
virtual ~invocable_cloner() {}
virtual invocable& clone() const {
return *new T(static_cast<T const&>(*this));
}
};
struct invocable_wrapper {
invocable_wrapper(): wrapped_(0) {}
invocable_wrapper(const invocable_wrapper& w): wrapped_(&w.wrapped_->clone()) {}
invocable_wrapper& operator=(const invocable_wrapper& that) {
invocable_wrapper newthis(that);
std::swap(wrapped_, newthis.wrapped_);
return *this;
}
#if PN_CPP_HAS_RVALUE_REFERENCES
invocable_wrapper(invocable_wrapper&& w): wrapped_(w.wrapped_) {}
invocable_wrapper& operator=(invocable_wrapper&& that) {delete wrapped_; wrapped_ = that.wrapped_; return *this; }
#endif
~invocable_wrapper() { delete wrapped_; }
invocable_wrapper(const invocable& i): wrapped_(&i.clone()) {}
void operator()() { (*wrapped_)(); }
invocable* wrapped_;
};
class work {
public:
work() {}
work(const invocable& i): item_(i) {}
void operator()() { item_(); }
~work() {}
private:
invocable_wrapper item_;
};
// Utilities to make work from functions/member functions (C++03 version)
// Lots of repetition to handle functions/member functions with up to 3 arguments
template <class R>
struct work0 : public invocable_cloner<work0<R> > {
R (* fn_)();
work0(R (* f)()) :
fn_(f) {}
void operator()() {
(*fn_)();
}
};
template <class R, class A>
struct work1 : public invocable_cloner<work1<R,A> > {
R (* fn_)(A);
A a_;
work1(R (* t)(A), A a) :
fn_(t), a_(a) {}
void operator()() {
(*fn_)(a_);
}
};
template <class R, class A, class B>
struct work2 : public invocable_cloner<work2<R,A,B> > {
R (* fn_)(A, B);
A a_;
B b_;
work2(R (* t)(A, B), A a, B b) :
fn_(t), a_(a), b_(b) {}
void operator()() {
(*fn_)(a_, b_);
}
};
template <class R, class A, class B, class C>
struct work3 : public invocable_cloner<work3<R,A,B,C> > {
R (* fn_)(A, B, C);
A a_;
B b_;
C c_;
work3(R (* t)(A, B, C), A a, B b, C c) :
fn_(t), a_(a), b_(b), c_(c) {}
void operator()() {
(*fn_)(a_, b_, c_);
}
};
template <class R, class T>
struct work_pmf0 : public invocable_cloner<work_pmf0<R,T> > {
T& holder_;
R (T::* fn_)();
work_pmf0(R (T::* a)(), T& h) :
holder_(h), fn_(a) {}
void operator()() {
(holder_.*fn_)();
}
};
template <class R, class T, class A>
struct work_pmf1 : public invocable_cloner<work_pmf1<R,T,A> > {
T& holder_;
R (T::* fn_)(A);
A a_;
work_pmf1(R (T::* t)(A), T& h, A a) :
holder_(h), fn_(t), a_(a) {}
void operator()() {
(holder_.*fn_)(a_);
}
};
template <class R, class T, class A, class B>
struct work_pmf2 : public invocable_cloner<work_pmf2<R,T,A,B> > {
T& holder_;
R (T::* fn_)(A, B);
A a_;
B b_;
work_pmf2(R (T::* t)(A, B), T& h, A a, B b) :
holder_(h), fn_(t), a_(a), b_(b) {}
void operator()() {
(holder_.*fn_)(a_, b_);
}
};
template <class R, class T, class A, class B, class C>
struct work_pmf3 : public invocable_cloner<work_pmf3<R,T,A,B,C> > {
T& holder_;
R (T::* fn_)(A, B, C);
A a_;
B b_;
C c_;
work_pmf3(R (T::* t)(A, B, C), T& h, A a, B b, C c) :
holder_(h), fn_(t), a_(a), b_(b), c_(c) {}
void operator()() {
(holder_.*fn_)(a_, b_, c_);
}
};
template <class R, class T>
work make_work(R (T::*f)(), T* t) {
return work_pmf0<R, T>(f, *t);
}
template <class R, class T, class A>
work make_work(R (T::*f)(A), T* t, A a) {
return work_pmf1<R, T, A>(f, *t, a);
}
template <class R, class T, class A, class B>
work make_work(R (T::*f)(A, B), T* t, A a, B b) {
return work_pmf2<R, T, A, B>(f, *t, a, b);
}
template <class R, class T, class A, class B, class C>
work make_work(R (T::*f)(A, B, C), T* t, A a, B b, C c) {
return work_pmf3<R, T, A, B, C>(f, *t, a, b, c);
}
template <class R>
work make_work(R (*f)()) {
return work0<R>(f);
}
template <class R, class A>
work make_work(R (*f)(A), A a) {
return work1<R, A>(f, a);
}
template <class R, class A, class B>
work make_work(R (*f)(A, B), A a, B b) {
return work2<R, A, B>(f, a, b);
}
template <class R, class A, class B, class C>
work make_work(R (*f)(A, B, C), A a, B b, C c) {
return work3<R, A, B, C>(f, a, b, c);
}
} } // internal::v03
#if PN_CPP_HAS_LAMBDAS && PN_CPP_HAS_VARIADIC_TEMPLATES
namespace internal { namespace v11 {
class work {
public:
work() {}
template <class T,
// Make sure we don't match the copy or move constructors
class = typename std::enable_if<!std::is_same<typename std::decay<T>::type,work>::value>::type
>
work(T&& f): item_(std::forward<T>(f)) {}
void operator()() { item_(); }
~work() {}
private:
std::function<void()> item_;
};
template <class... Rest>
work make_work(Rest&&... r) {
return std::bind(std::forward<Rest>(r)...);
}
} } // internal::v11
using internal::v11::work;
using internal::v11::make_work;
#else
using internal::v03::work;
using internal::v03::make_work;
#endif
class PN_CPP_CLASS_EXTERN work_queue {
class impl;
work_queue& operator=(impl* i);
public:
PN_CPP_EXTERN work_queue();
PN_CPP_EXTERN work_queue(container&);
PN_CPP_EXTERN ~work_queue();
PN_CPP_EXTERN bool add(work fn);
PN_CPP_EXTERN PN_CPP_DEPRECATED("Use 'work_queue::add(work)'") bool add(void_function0& fn);
// This is a hack to ensure that the C++03 version is declared
// only during the compilation of the library
#if PN_CPP_HAS_LAMBDAS && PN_CPP_HAS_VARIADIC_TEMPLATES && defined(qpid_proton_cpp_EXPORTS)
PN_CPP_EXTERN bool add(internal::v03::work fn);
#endif
PN_CPP_EXTERN void schedule(duration, work fn);
PN_CPP_EXTERN PN_CPP_DEPRECATED("Use 'work_queue::schedule(duration, work)'") void schedule(duration, void_function0& fn);
// This is a hack to ensure that the C++03 version is declared
// only during the compilation of the library
#if PN_CPP_HAS_LAMBDAS && PN_CPP_HAS_VARIADIC_TEMPLATES && defined(qpid_proton_cpp_EXPORTS)
PN_CPP_EXTERN void schedule(duration, internal::v03::work fn);
#endif
private:
PN_CPP_EXTERN static work_queue& get(pn_connection_t*);
PN_CPP_EXTERN static work_queue& get(pn_session_t*);
PN_CPP_EXTERN static work_queue& get(pn_link_t*);
internal::pn_unique_ptr<impl> impl_;
friend class container;
friend class io::connection_driver;
};
} // proton
#endif // PROTON_WORK_QUEUE_HPP
proton::container
A top-level container of connections, sessions, and links.
Definition: container.hpp:50
proton::duration
A span of time in milliseconds.
Definition: duration.hpp:39
proton::io::connection_driver
Unsettled API - An AMQP driver for a single connection.
Definition: connection_driver.hpp:94
proton::work_queue
Unsettled API - A context for thread-safe execution of work.
Definition: work_queue.hpp:339
proton::work_queue::work_queue
work_queue()
Unsettled API - Create a work queue.
proton::work_queue::schedule
void schedule(duration, work fn)
Unsettled API - Add work fn to the work queue after a duration.
proton::work_queue::add
bool add(work fn)
Unsettled API - Add work fn to the work queue.
proton::work_queue::work_queue
work_queue(container &)
Unsettled API - Create a work queue backed by a container.
duration.hpp
A span of time in milliseconds.
function.hpp
Deprecated - Use the API in work_queue.hpp.
fwd.hpp
Forward declarations.
proton
The main Proton namespace.
Definition: annotation_key.hpp:33
proton::get
T get(const scalar &s)
Get a contained value of type T.
Definition: scalar.hpp:58
proton::swap
void swap(map< K, T > &, map< K, T > &)
Swap proton::map instances.