You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by as...@apache.org on 2017/07/21 17:01:57 UTC
[01/20] qpid-proton git commit: PROTON-1400: [C++ example] Use
multiple threads in broker example if available
Repository: qpid-proton
Updated Branches:
refs/heads/master 6f88f525e -> b17671eef
PROTON-1400: [C++ example] Use multiple threads in broker example if available
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/b17671ee
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/b17671ee
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/b17671ee
Branch: refs/heads/master
Commit: b17671eefa3a13579f858cd7a72df4231058a429
Parents: 2a60653
Author: Andrew Stitcher <as...@apache.org>
Authored: Fri May 26 17:01:00 2017 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
examples/cpp/broker.cpp | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/b17671ee/examples/cpp/broker.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/broker.cpp b/examples/cpp/broker.cpp
index 2cb2b36..01dab36 100644
--- a/examples/cpp/broker.cpp
+++ b/examples/cpp/broker.cpp
@@ -44,11 +44,19 @@
#include <map>
#include <string>
+#if PN_CPP_SUPPORTS_THREADS
+#include <thread>
+#endif
+
#include "fake_cpp11.hpp"
// This is a simplified model for a message broker, that only allows for messages to go to a
// single receiver.
//
+// This broker is multithread safe and if compiled with C++11 with a multithreaded Proton
+// binding library will use as many threads as there are thread resources available (usually
+// cores)
+//
// Queues are only created and never destroyed
//
// Broker Entities (that need to be individually serialised)
@@ -387,7 +395,12 @@ class broker {
}
void run() {
- container_.run(/* std::thread::hardware_concurrency() */);
+#if PN_CPP_SUPPORTS_THREADS
+ std::cout << "starting " << std::thread::hardware_concurrency() << " listening threads\n";
+ container_.run(std::thread::hardware_concurrency());
+#else
+ container_.run();
+#endif
}
private:
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[02/20] qpid-proton git commit: PROTON-1400: [C++ binding] Make
proactor container thread safe
Posted by as...@apache.org.
PROTON-1400: [C++ binding] Make proactor container thread safe
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/e4eca5c3
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/e4eca5c3
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/e4eca5c3
Branch: refs/heads/master
Commit: e4eca5c3d92b917edca4629c6bc01155c4678baf
Parents: 8aee73b
Author: Andrew Stitcher <as...@apache.org>
Authored: Fri May 26 17:00:31 2017 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
.../bindings/cpp/include/proton/container.hpp | 22 +++-
.../cpp/include/proton/internal/config.hpp | 4 +
proton-c/bindings/cpp/src/container.cpp | 6 +-
.../cpp/src/include/proactor_container_impl.hpp | 28 +++-
.../cpp/src/proactor_container_impl.cpp | 127 +++++++++++++++----
5 files changed, 155 insertions(+), 32 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e4eca5c3/proton-c/bindings/cpp/include/proton/container.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/container.hpp b/proton-c/bindings/cpp/include/proton/container.hpp
index 0739517..8b517bf 100644
--- a/proton-c/bindings/cpp/include/proton/container.hpp
+++ b/proton-c/bindings/cpp/include/proton/container.hpp
@@ -29,11 +29,11 @@
#include "./internal/export.hpp"
#include "./internal/pn_unique_ptr.hpp"
-#ifdef PN_CPP_HAS_STD_FUNCTION
-#include <functional>
-#endif
#include <string>
+/// If the library can support multithreaded containers then PN_CPP_SUPPORTS_THREADS will be set.
+#define PN_CPP_SUPPORTS_THREADS PN_CPP_HAS_STD_THREAD && PN_CPP_HAS_STD_MUTEX && PN_CPP_HAS_STD_ATOMIC
+
namespace proton {
/// A top-level container of connections, sessions, senders, and
@@ -55,6 +55,13 @@ class PN_CPP_CLASS_EXTERN container {
/// Create a container.
PN_CPP_EXTERN container(const std::string& id="");
+ /// Destroy a container.
+ /// Note that you may not delete a container from within any of the threads running
+ /// any of the container's messaging_handlers. Specifically if you delete the container
+ /// from within a handler you cause a deadlock or a crash.
+ ///
+ /// The only safe place to delete a container is after all of the threads running a container
+ /// have finished and all of the run functions have returned.
PN_CPP_EXTERN ~container();
/// Connect to `url` and send an open request to the remote peer.
@@ -95,9 +102,16 @@ class PN_CPP_CLASS_EXTERN container {
/// Returns when the container stops.
/// @see auto_stop() and stop().
///
- /// With a multithreaded container, call run() in multiple threads to create a thread pool.
+ /// If you are using C++11 or later you may use a multithreaded container. In this case you may
+ /// call run() in multiple threads to create a thread pool. Or aternatively call run with an
+ /// integer parameter specifying the number of threads for the thread pool.
PN_CPP_EXTERN void run();
+#if PN_CPP_SUPPORTS_THREADS
+ /// @copydoc run()
+ PN_CPP_EXTERN void run(int threads);
+#endif
+
/// If true, stop the container when all active connections and listeners are closed.
/// If false the container will keep running till stop() is called.
///
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e4eca5c3/proton-c/bindings/cpp/include/proton/internal/config.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/internal/config.hpp b/proton-c/bindings/cpp/include/proton/internal/config.hpp
index 79d201c..54b014b 100644
--- a/proton-c/bindings/cpp/include/proton/internal/config.hpp
+++ b/proton-c/bindings/cpp/include/proton/internal/config.hpp
@@ -103,6 +103,10 @@
#define PN_CPP_HAS_STD_ATOMIC PN_CPP_HAS_CPP11
#endif
+#ifndef PN_CPP_HAS_STD_THREAD
+#define PN_CPP_HAS_STD_THREAD PN_CPP_HAS_CPP11
+#endif
+
#endif // PROTON_INTERNAL_CONFIG_HPP
/// @endcond
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e4eca5c3/proton-c/bindings/cpp/src/container.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/container.cpp b/proton-c/bindings/cpp/src/container.cpp
index c2af659..35f645c 100644
--- a/proton-c/bindings/cpp/src/container.cpp
+++ b/proton-c/bindings/cpp/src/container.cpp
@@ -81,7 +81,11 @@ returned<connection> container::connect(const std::string& url, const connection
listener container::listen(const std::string& url, listen_handler& l) { return impl_->listen(url, l); }
-void container::run() { impl_->run(); }
+void container::run() { impl_->run(1); }
+
+#if PN_CPP_SUPPORTS_THREADS
+void container::run(int threads) { impl_->run(threads); }
+#endif
void container::auto_stop(bool set) { impl_->auto_stop(set); }
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e4eca5c3/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp b/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
index fc963f7..ac54156 100644
--- a/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
+++ b/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
@@ -43,6 +43,21 @@
#include <string>
#include <vector>
+#if PN_CPP_SUPPORTS_THREADS
+#include <atomic>
+#include <mutex>
+# define MUTEX(x) std::mutex x;
+# define GUARD(x) std::lock_guard<std::mutex> g(x)
+# define ONCE_FLAG(x) std::once_flag x;
+# define CALL_ONCE(x, ...) std::call_once(x, __VA_ARGS__)
+# define ATOMIC_INT(x) std::atomic<int> x;
+#else
+# define MUTEX(x)
+# define GUARD(x)
+# define ONCE_FLAG(x)
+# define CALL_ONCE(x, f, o) ((o)->*(f))()
+# define ATOMIC_INT(x) int x;
+#endif
struct pn_proactor_t;
struct pn_listener_t;
struct pn_event_t;
@@ -70,7 +85,7 @@ class container::impl {
class sender_options sender_options() const { return sender_options_; }
void receiver_options(const proton::receiver_options&);
class receiver_options receiver_options() const { return receiver_options_; }
- void run();
+ void run(int threads);
void stop(const error_condition& err);
void auto_stop(bool set);
void schedule(duration, work);
@@ -86,16 +101,23 @@ class container::impl {
connection connect_common(const std::string&, const connection_options&);
// Event loop to run in each container thread
- static void thread(impl&);
+ void thread();
bool handle(pn_event_t*);
void run_timer_jobs();
+ ATOMIC_INT(threads_)
+ MUTEX(lock_)
+ ONCE_FLAG(start_once_)
+ ONCE_FLAG(stop_once_)
container& container_;
typedef std::set<container_work_queue*> work_queues;
work_queues work_queues_;
container_work_queue* add_work_queue();
void remove_work_queue(container_work_queue*);
+ void start_event();
+ void stop_event();
+
struct scheduled {
timestamp time; // duration from epoch for task
work task;
@@ -112,8 +134,8 @@ class container::impl {
connection_options server_connection_options_;
proton::sender_options sender_options_;
proton::receiver_options receiver_options_;
+ error_condition disconnect_error_;
- proton::error_condition stop_err_;
bool auto_stop_;
bool stopping_;
};
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/e4eca5c3/proton-c/bindings/cpp/src/proactor_container_impl.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proactor_container_impl.cpp b/proton-c/bindings/cpp/src/proactor_container_impl.cpp
index 62115fd..b900d6f 100644
--- a/proton-c/bindings/cpp/src/proactor_container_impl.cpp
+++ b/proton-c/bindings/cpp/src/proactor_container_impl.cpp
@@ -41,21 +41,27 @@
#include <algorithm>
#include <vector>
+#if PN_CPP_SUPPORTS_THREADS
+# include <thread>
+#endif
+
namespace proton {
class container::impl::common_work_queue : public work_queue::impl {
public:
- common_work_queue(container::impl& c): container_(c), finished_(false) {}
+ common_work_queue(container::impl& c): container_(c), finished_(false), running_(false) {}
typedef std::vector<work> jobs;
void run_all_jobs();
- void finished() { finished_ = true; }
+ void finished() { GUARD(lock_); finished_ = true; }
void schedule(duration, work);
+ MUTEX(lock_)
container::impl& container_;
jobs jobs_;
bool finished_;
+ bool running_;
};
void container::impl::common_work_queue::schedule(duration d, work f) {
@@ -68,11 +74,22 @@ void container::impl::common_work_queue::schedule(duration d, work f) {
void container::impl::common_work_queue::run_all_jobs() {
jobs j;
// Lock this operation for mt
- std::swap(j, jobs_);
+ {
+ GUARD(lock_);
+ // Ensure that we never run work from this queue concurrently
+ if (running_) return;
+ running_ = true;
+ // But allow adding to the queue concurrently to running
+ std::swap(j, jobs_);
+ }
// Run queued work, but ignore any exceptions
for (jobs::iterator f = j.begin(); f != j.end(); ++f) try {
(*f)();
} catch (...) {};
+ {
+ GUARD(lock_);
+ running_ = false;
+ }
return;
}
@@ -88,6 +105,7 @@ class container::impl::connection_work_queue : public common_work_queue {
bool container::impl::connection_work_queue::add(work f) {
// Note this is an unbounded work queue.
// A resource-safe implementation should be bounded.
+ GUARD(lock_);
if (finished_) return false;
jobs_.push_back(f);
pn_connection_wake(connection_);
@@ -105,6 +123,7 @@ class container::impl::container_work_queue : public common_work_queue {
bool container::impl::container_work_queue::add(work f) {
// Note this is an unbounded work queue.
// A resource-safe implementation should be bounded.
+ GUARD(lock_);
if (finished_) return false;
jobs_.push_back(f);
pn_proactor_set_timeout(container_.proactor_, 0);
@@ -116,15 +135,11 @@ class work_queue::impl* container::impl::make_work_queue(container& c) {
}
container::impl::impl(container& c, const std::string& id, messaging_handler* mh)
- : container_(c), proactor_(pn_proactor()), handler_(mh), id_(id),
+ : threads_(0), container_(c), proactor_(pn_proactor()), handler_(mh), id_(id),
auto_stop_(true), stopping_(false)
{}
container::impl::~impl() {
- try {
- stop(error_condition("exception", "container shut-down"));
- //wait();
- } catch (...) {}
pn_proactor_free(proactor_);
}
@@ -178,6 +193,7 @@ proton::returned<proton::connection> container::impl::connect(
const proton::connection_options& user_opts)
{
connection conn = connect_common(addr, user_opts);
+ GUARD(lock_);
return make_thread_safe(conn);
}
@@ -186,6 +202,7 @@ returned<sender> container::impl::open_sender(const std::string &url, const prot
lopts.update(o1);
connection conn = connect_common(url, o2);
+ GUARD(lock_);
return make_thread_safe(conn.default_session().open_sender(proton::url(url).path(), lopts));
}
@@ -194,6 +211,7 @@ returned<receiver> container::impl::open_receiver(const std::string &url, const
lopts.update(o1);
connection conn = connect_common(url, o2);
+ GUARD(lock_);
return make_thread_safe(
conn.default_session().open_receiver(proton::url(url).path(), lopts));
}
@@ -215,11 +233,13 @@ pn_listener_t* container::impl::listen_common_lh(const std::string& addr) {
}
proton::listener container::impl::listen(const std::string& addr) {
+ GUARD(lock_);
pn_listener_t* listener = listen_common_lh(addr);
return proton::listener(listener);
}
proton::listener container::impl::listen(const std::string& addr, const proton::connection_options& opts) {
+ GUARD(lock_);
pn_listener_t* listener = listen_common_lh(addr);
listener_context& lc=listener_context::get(listener);
lc.connection_options_.reset(new connection_options(opts));
@@ -227,6 +247,7 @@ proton::listener container::impl::listen(const std::string& addr, const proton::
}
proton::listener container::impl::listen(const std::string& addr, proton::listen_handler& lh) {
+ GUARD(lock_);
pn_listener_t* listener = listen_common_lh(addr);
listener_context& lc=listener_context::get(listener);
lc.listen_handler_ = &lh;
@@ -234,6 +255,7 @@ proton::listener container::impl::listen(const std::string& addr, proton::listen
}
void container::impl::schedule(duration delay, work f) {
+ GUARD(lock_);
timestamp now = timestamp::now();
// Record timeout; Add callback to timeout sorted list
@@ -247,18 +269,22 @@ void container::impl::schedule(duration delay, work f) {
}
void container::impl::client_connection_options(const connection_options &opts) {
+ GUARD(lock_);
client_connection_options_ = opts;
}
void container::impl::server_connection_options(const connection_options &opts) {
+ GUARD(lock_);
server_connection_options_ = opts;
}
void container::impl::sender_options(const proton::sender_options &opts) {
+ GUARD(lock_);
sender_options_ = opts;
}
void container::impl::receiver_options(const proton::receiver_options &opts) {
+ GUARD(lock_);
receiver_options_ = opts;
}
@@ -294,13 +320,18 @@ bool container::impl::handle(pn_event_t* event) {
switch (pn_event_type(event)) {
case PN_PROACTOR_INACTIVE: /* listener and all connections closed */
- return auto_stop_;
+ // If we're stopping interrupt all other threads still running
+ if (auto_stop_) pn_proactor_interrupt(proactor_);
+ return false;
- // We never interrupt the proactor so ignore
+ // We only interrupt to stop threads
case PN_PROACTOR_INTERRUPT:
- return false;
+ // Interrupt any other threads still running
+ if (threads_>1) pn_proactor_interrupt(proactor_);
+ return true;
case PN_PROACTOR_TIMEOUT: {
+ GUARD(lock_);
// Can get an immediate timeout, if we have a container event loop inject
if ( deferred_.size()>0 ) {
run_timer_jobs();
@@ -402,30 +433,78 @@ bool container::impl::handle(pn_event_t* event) {
return false;
}
-void container::impl::thread(container::impl& ci) {
- bool finished = false;
- do {
- pn_event_batch_t *events = pn_proactor_wait(ci.proactor_);
- pn_event_t *e;
- while ((e = pn_event_batch_next(events))) {
- finished = ci.handle(e) || finished;
- }
- pn_proactor_done(ci.proactor_, events);
- } while(!finished);
+void container::impl::thread() {
+ ++threads_;
+ bool finished = false;
+ do {
+ pn_event_batch_t *events = pn_proactor_wait(proactor_);
+ pn_event_t *e;
+ try {
+ while ((e = pn_event_batch_next(events))) {
+ finished = handle(e);
+ if (finished) break;
+ }
+ } catch (proton::error& e) {
+ // If we caught an exception then shutdown the (other threads of the) container
+ disconnect_error_ = error_condition("exception", e.what());
+ if (!stopping_) stop(disconnect_error_);
+ finished = true;
+ } catch (...) {
+ // If we caught an exception then shutdown the (other threads of the) container
+ disconnect_error_ = error_condition("exception", "container shut-down by unknown exception");
+ if (!stopping_) stop(disconnect_error_);
+ finished = true;
+ }
+ pn_proactor_done(proactor_, events);
+ } while(!finished);
+ --threads_;
}
-void container::impl::run() {
- // Have to "manually" generate container events
+void container::impl::start_event() {
if (handler_) handler_->on_container_start(container_);
- thread(*this);
+}
+
+void container::impl::stop_event() {
if (handler_) handler_->on_container_stop(container_);
}
+void container::impl::run(int threads) {
+ // Have to "manually" generate container events
+ CALL_ONCE(start_once_, &impl::start_event, this);
+
+#if PN_CPP_SUPPORTS_THREADS
+ // Run handler threads
+ std::vector<std::thread> ts(threads-1);
+ if (threads>1) {
+ for (auto& t : ts) t = std::thread(&impl::thread, this);
+ }
+
+ thread(); // Use this thread too.
+
+ // Wait for the other threads to stop
+ if (threads>1) {
+ for (auto& t : ts) t.join();
+ }
+#else
+ // Run a single handler thread (As we have no threading API)
+ thread();
+#endif
+
+ if (threads_==0) CALL_ONCE(stop_once_, &impl::stop_event, this);
+
+ // Throw an exception if we disconnected the proactor because of an exception
+ if (!disconnect_error_.empty()) {
+ throw proton::error(disconnect_error_.description());
+ };
+}
+
void container::impl::auto_stop(bool set) {
+ GUARD(lock_);
auto_stop_ = set;
}
void container::impl::stop(const proton::error_condition& err) {
+ GUARD(lock_);
auto_stop_ = true;
stopping_ = true;
pn_condition_t* error_condition = pn_condition();
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[17/20] qpid-proton git commit: PROTON-1481: [C++ binding] Further
work on C++03 convenience functions - Propagate the result of work_queue::add
- Fix memory leak of proton::defer if the deferred function can't be called -
Add make_work convenience in pl
Posted by as...@apache.org.
PROTON-1481: [C++ binding] Further work on C++03 convenience functions
- Propagate the result of work_queue::add
- Fix memory leak of proton::defer if the deferred function can't be called
- Add make_work convenience in place of std::bind
- Simplfy defer oveload options - have to specify work_queue
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/bf3a2b4b
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/bf3a2b4b
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/bf3a2b4b
Branch: refs/heads/master
Commit: bf3a2b4bd9c447bc7b28ecd339a7293f1fcf7ac9
Parents: efc899f
Author: Andrew Stitcher <as...@apache.org>
Authored: Thu May 18 13:47:46 2017 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
examples/cpp/broker.cpp | 40 ++---
.../bindings/cpp/include/proton/work_queue.hpp | 170 ++++++++++---------
proton-c/bindings/cpp/src/work_queue.cpp | 2 +
3 files changed, 110 insertions(+), 102 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bf3a2b4b/examples/cpp/broker.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/broker.cpp b/examples/cpp/broker.cpp
index a1ef3a5..09a771c 100644
--- a/examples/cpp/broker.cpp
+++ b/examples/cpp/broker.cpp
@@ -99,8 +99,8 @@ public:
sender_(s), senders_(ss), work_queue_(s.work_queue()), queue_(0), pending_credit_(0)
{}
- void add(proton::work f) {
- work_queue_.add(f);
+ bool add(proton::work f) {
+ return work_queue_.add(f);
}
@@ -139,7 +139,7 @@ class Queue {
DOUT(std::cerr << "(" << current_->second << ") ";);
if (current_->second>0) {
DOUT(std::cerr << current_->first << " ";);
- proton::defer(&Sender::sendMsg, current_->first, messages_.front());
+ proton::defer(current_->first, &Sender::sendMsg, current_->first, messages_.front());
messages_.pop_front();
--current_->second;
++current_;
@@ -155,8 +155,8 @@ public:
work_queue_(c), name_(n), current_(subscriptions_.end())
{}
- void add(proton::work f) {
- work_queue_.add(f);
+ bool add(proton::work f) {
+ return work_queue_.add(f);
}
void queueMsg(proton::message m) {
@@ -178,14 +178,14 @@ public:
// If we're about to erase the current subscription move on
if (current_ != subscriptions_.end() && current_->first==s) ++current_;
subscriptions_.erase(s);
- proton::defer(&Sender::unsubscribed, s);
+ proton::defer(s, &Sender::unsubscribed, s);
}
};
// We have credit to send a message.
void Sender::on_sendable(proton::sender &sender) {
if (queue_) {
- proton::defer(&Queue::flow, queue_, this, sender.credit());
+ proton::defer(queue_, &Queue::flow, queue_, this, sender.credit());
} else {
pending_credit_ = sender.credit();
}
@@ -193,7 +193,7 @@ void Sender::on_sendable(proton::sender &sender) {
void Sender::on_sender_close(proton::sender &sender) {
if (queue_) {
- proton::defer(&Queue::unsubscribe, queue_, this);
+ proton::defer(queue_, &Queue::unsubscribe, queue_, this);
} else {
// TODO: Is it possible to be closed before we get the queue allocated?
// If so, we should have a way to mark the sender deleted, so we can delete
@@ -207,12 +207,12 @@ void Sender::boundQueue(Queue* q, std::string qn) {
queue_ = q;
queue_name_ = qn;
- proton::defer(&Queue::subscribe, q, this);
+ proton::defer(q, &Queue::subscribe, q, this);
sender_.open(proton::sender_options()
.source((proton::source_options().address(queue_name_)))
.handler(*this));
if (pending_credit_>0) {
- proton::defer(&Queue::flow, queue_, this, pending_credit_);
+ proton::defer(queue_, &Queue::flow, queue_, this, pending_credit_);
}
std::cout << "sending from " << queue_name_ << std::endl;
}
@@ -237,7 +237,7 @@ class Receiver : public proton::messaging_handler {
void queueMsgs() {
DOUT(std::cerr << "Receiver: " << this << " queueing " << messages_.size() << " msgs to: " << queue_ << "\n";);
while (!messages_.empty()) {
- proton::defer(&Queue::queueMsg, queue_, messages_.front());
+ proton::defer(queue_, &Queue::queueMsg, queue_, messages_.front());
messages_.pop_front();
}
}
@@ -247,8 +247,8 @@ public:
receiver_(r), work_queue_(r.work_queue()), queue_(0)
{}
- void add(proton::work f) {
- work_queue_.add(f);
+ bool add(proton::work f) {
+ return work_queue_.add(f);
}
void boundQueue(Queue* q, std::string qn) {
@@ -275,8 +275,8 @@ public:
container_(c), work_queue_(c), next_id_(0)
{}
- void add(proton::work f) {
- work_queue_.add(f);
+ bool add(proton::work f) {
+ return work_queue_.add(f);
}
template <class T>
@@ -295,7 +295,7 @@ public:
} else {
q = i->second;
}
- proton::defer(&T::boundQueue, &connection, q, qn);
+ proton::defer(&connection, &T::boundQueue, &connection, q, qn);
}
void findQueueSender(Sender* s, std::string qn) {
@@ -325,7 +325,7 @@ public:
std::string qn = sender.source().dynamic() ? "" : sender.source().address();
Sender* s = new Sender(sender, senders_);
senders_[sender] = s;
- proton::defer(&QueueManager::findQueueSender, &queue_manager_, s, qn);
+ proton::defer(&queue_manager_, &QueueManager::findQueueSender, &queue_manager_, s, qn);
}
// A receiver receives messages from a publisher to a queue.
@@ -341,7 +341,7 @@ public:
DOUT(std::cerr << "ODD - trying to attach to a empty address\n";);
}
Receiver* r = new Receiver(receiver);
- proton::defer(&QueueManager::findQueueReceiver, &queue_manager_, r, qname);
+ proton::defer(&queue_manager_, &QueueManager::findQueueReceiver, &queue_manager_, r, qname);
}
}
@@ -352,7 +352,7 @@ public:
if (j == senders_.end()) continue;
Sender* s = j->second;
if (s->queue_) {
- proton::defer(&Queue::unsubscribe, s->queue_, s);
+ proton::defer(s->queue_, &Queue::unsubscribe, s->queue_, s);
}
senders_.erase(j);
}
@@ -370,7 +370,7 @@ public:
if (j == senders_.end()) continue;
Sender* s = j->second;
if (s->queue_) {
- proton::defer(&Queue::unsubscribe, s->queue_, s);
+ proton::defer(s->queue_, &Queue::unsubscribe, s->queue_, s);
}
}
delete this; // All done.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bf3a2b4b/proton-c/bindings/cpp/include/proton/work_queue.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/work_queue.hpp b/proton-c/bindings/cpp/include/proton/work_queue.hpp
index 1937e11..4d843c2 100644
--- a/proton-c/bindings/cpp/include/proton/work_queue.hpp
+++ b/proton-c/bindings/cpp/include/proton/work_queue.hpp
@@ -100,7 +100,7 @@ class PN_CPP_CLASS_EXTERN work_queue {
/// deferred and possibly in another thread.
///
/// @return true if f() has or will be called, false if the event_loop is ended
- /// and f() cannot be injected.
+ /// or f() cannot be injected for any other reason.
PN_CPP_EXTERN bool add(work f);
private:
@@ -120,10 +120,11 @@ class PN_CPP_CLASS_EXTERN work_queue {
// Utilities to make injecting functions/member functions palatable in C++03
// Lots of repetition to handle functions with up to 3 arguments
#if !PN_CPP_HAS_CPP11
+template <class R>
struct work0 : public proton::void_function0 {
- void (* fn_)();
+ R (* fn_)();
- work0(void (* f)()) :
+ work0(R (* f)()) :
fn_(f) {}
void operator()() {
@@ -132,12 +133,12 @@ struct work0 : public proton::void_function0 {
}
};
-template <class A>
+template <class R, class A>
struct work1 : public proton::void_function0 {
- void (* fn_)(A);
+ R (* fn_)(A);
A a_;
- work1(void (* t)(A), A a) :
+ work1(R (* t)(A), A a) :
fn_(t), a_(a) {}
void operator()() {
@@ -146,13 +147,13 @@ struct work1 : public proton::void_function0 {
}
};
-template <class A, class B>
+template <class R, class A, class B>
struct work2 : public proton::void_function0 {
- void (* fn_)(A, B);
+ R (* fn_)(A, B);
A a_;
B b_;
- work2(void (* t)(A, B), A a, B b) :
+ work2(R (* t)(A, B), A a, B b) :
fn_(t), a_(a), b_(b) {}
void operator()() {
@@ -161,14 +162,14 @@ struct work2 : public proton::void_function0 {
}
};
-template <class A, class B, class C>
+template <class R, class A, class B, class C>
struct work3 : public proton::void_function0 {
- void (* fn_)(A, B, C);
+ R (* fn_)(A, B, C);
A a_;
B b_;
C c_;
- work3(void (* t)(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()() {
@@ -177,12 +178,12 @@ struct work3 : public proton::void_function0 {
}
};
-template <class T>
+template <class R, class T>
struct work_pmf0 : public proton::void_function0 {
T& holder_;
- void (T::* fn_)();
+ R (T::* fn_)();
- work_pmf0(void (T::* a)(), T& h) :
+ work_pmf0(R (T::* a)(), T& h) :
holder_(h), fn_(a) {}
void operator()() {
@@ -191,13 +192,13 @@ struct work_pmf0 : public proton::void_function0 {
}
};
-template <class T, class A>
+template <class R, class T, class A>
struct work_pmf1 : public proton::void_function0 {
T& holder_;
- void (T::* fn_)(A);
+ R (T::* fn_)(A);
A a_;
- work_pmf1(void (T::* t)(A), T& h, A a) :
+ work_pmf1(R (T::* t)(A), T& h, A a) :
holder_(h), fn_(t), a_(a) {}
void operator()() {
@@ -206,14 +207,14 @@ struct work_pmf1 : public proton::void_function0 {
}
};
-template <class T, class A, class B>
+template <class R, class T, class A, class B>
struct work_pmf2 : public proton::void_function0 {
T& holder_;
- void (T::* fn_)(A, B);
+ R (T::* fn_)(A, B);
A a_;
B b_;
- work_pmf2(void (T::* t)(A, B), T& h, 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()() {
@@ -222,15 +223,15 @@ struct work_pmf2 : public proton::void_function0 {
}
};
-template <class T, class A, class B, class C>
+template <class R, class T, class A, class B, class C>
struct work_pmf3 : public proton::void_function0 {
T& holder_;
- void (T::* fn_)(A, B, C);
+ R (T::* fn_)(A, B, C);
A a_;
B b_;
C c_;
- work_pmf3(void (T::* t)(A, B, C), T& h, 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()() {
@@ -239,91 +240,96 @@ struct work_pmf3 : public proton::void_function0 {
}
};
-/// This version of proton::defer defers calling an object's member function to the object's work queue
-template <class T>
-void defer(void (T::*f)(), T* t) {
- work_pmf0<T>* w = new work_pmf0<T>(f, *t);
- t->add(*w);
+/// make_work is the equivalent of C++11 std::bind for C++03
+/// It will bind both free functions and pointers to member functions
+template <class R, class T>
+void_function0& make_work(R (T::*f)(), T* t) {
+ return *new work_pmf0<R, T>(f, *t);
}
-template <class T, class A>
-void defer(void (T::*f)(A), T* t, A a) {
- work_pmf1<T, A>* w = new work_pmf1<T, A>(f, *t, a);
- t->add(*w);
+template <class R, class T, class A>
+void_function0& make_work(R (T::*f)(A), T* t, A a) {
+ return *new work_pmf1<R, T, A>(f, *t, a);
}
-template <class T, class A, class B>
-void defer(void (T::*f)(A, B), T* t, A a, B b) {
- work_pmf2<T, A, B>* w = new work_pmf2<T, A, B>(f, *t, a, b);
- t->add(*w);
+template <class R, class T, class A, class B>
+void_function0& make_work(R (T::*f)(A, B), T* t, A a, B b) {
+ return *new work_pmf2<R, T, A, B>(f, *t, a, b);
}
-template <class T, class A, class B, class C>
-void defer(void (T::*f)(A, B, C), T* t, A a, B b, C c) {
- work_pmf3<T, A, B, C>* w = new work_pmf3<T, A, B, C>(f, *t, a, b, c);
- t->add(*w);
+template <class R, class T, class A, class B, class C>
+void_function0& make_work(R (T::*f)(A, B, C), T* t, A a, B b, C c) {
+ return *new work_pmf3<R, T, A, B, C>(f, *t, a, b, c);
}
-/// This version of proton::defer defers calling a member function to an arbitrary work queue
-template <class T, class U>
-void defer(U* wq, void (T::*f)(), T* t) {
- work_pmf0<T>* w = new work_pmf0<T>(f, *t);
- wq->add(*w);
+template <class R>
+void_function0& make_work(R (*f)()) {
+ return *new work0<R>(f);
}
-template <class T, class U, class A>
-void defer(U* wq, void (T::*f)(A), T* t, A a) {
- work_pmf1<T, A>* w = new work_pmf1<T, A>(f, *t, a);
- wq->add(*w);
+template <class R, class A>
+void_function0& make_work(R (*f)(A), A a) {
+ return *new work1<R, A>(f, a);
}
-template <class T, class U, class A, class B>
-void defer(U* wq, void (T::*f)(A, B), T* t, A a, B b) {
- work_pmf2<T, A, B>* w = new work_pmf2<T, A, B>(f, *t, a, b);
- wq->add(*w);
+template <class R, class A, class B>
+void_function0& make_work(R (*f)(A, B), A a, B b) {
+ return *new work2<R, A, B>(f, a, b);
}
-template <class T, class U, class A, class B, class C>
-void defer(U* wq, void (T::*f)(A, B, C), T* t, A a, B b, C c) {
- work_pmf3<T, A, B, C>* w = new work_pmf3<T, A, B, C>(f, *t, a, b, c);
- wq->add(*w);
+template <class R, class A, class B, class C>
+void_function0& make_work(R (*f)(A, B, C), A a, B b, C c) {
+ return *new work3<R, A, B, C>(f, a, b, c);
}
-/// This version of proton::defer defers calling a free function to an arbitrary work queue
-template <class U>
-void defer(U* wq, void (*f)()) {
- work0* w = new work0(f);
- wq->add(*w);
+namespace {
+template <class T>
+bool defer_helper(T t, void_function0& w) {
+ bool r = t->add(w);
+ if (!r) delete &w;
+ return r;
+}
}
-template <class U, class A>
-void defer(U* wq, void (*f)(A), A a) {
- work1<A>* w = new work1<A>(f, a);
- wq->add(*w);
+/// defer is a convenience that is used for C++03 code to defer function calls
+/// to a work_queue
+template <class WQ, class F>
+bool defer(WQ wq, F f) {
+ return defer_helper(wq, make_work(f));
}
-template <class U, class A, class B>
-void defer(U* wq, void (*f)(A, B), A a, B b) {
- work2<A, B>* w = new work2<A, B>(f, a, b);
- wq->add(*w);
+template <class WQ, class F, class A>
+bool defer(WQ wq, F f, A a) {
+ return defer_helper(wq, make_work(f, a));
}
-template <class U, class A, class B, class C>
-void defer(U* wq, void (*f)(A, B, C), A a, B b, C c) {
- work3<A, B, C>* w = new work3<A, B, C>(f, a, b, c);
- wq->add(*w);
+template <class WQ, class F, class A, class B>
+bool defer(WQ wq, F f, A a, B b) {
+ return defer_helper(wq, make_work(f, a, b));
}
+
+template <class WQ, class F, class A, class B, class C>
+bool defer(WQ wq, F f, A a, B b, C c) {
+ return defer_helper(wq, make_work(f, a, b, c));
+}
+
+template <class WQ, class F, class A, class B, class C, class D>
+bool defer(WQ wq, F f, A a, B b, C c, D d) {
+ return defer_helper(wq, make_work(f, a, b, c, d));
+}
+
+/// This version of proton::defer defers calling a free function to an arbitrary work queue
#else
// The C++11 version is *much* simpler and even so more general!
-// These 2 definitions encompass everything in the C++03 section
-template <class T, class... Rest>
-void defer(void(T::*f)(Rest...), T* t, Rest... r) {
- t->add(std::bind(f, t, r...));
+// These definitions encompass everything in the C++03 section
+template <class WQ, class... Rest>
+bool defer(WQ wq, Rest&&... r) {
+ return wq->add(std::bind(std::forward<Rest>(r)...));
}
-template <class U, class... Rest>
-void defer(U* wq, Rest&&... r) {
- wq->add(std::bind(std::forward<Rest>(r)...));
+template <class... Rest>
+work make_work(Rest&&... r) {
+ return std::bind(std::forward<Rest>(r)...);
}
#endif
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/bf3a2b4b/proton-c/bindings/cpp/src/work_queue.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/work_queue.cpp b/proton-c/bindings/cpp/src/work_queue.cpp
index db95042..77fa3fb 100644
--- a/proton-c/bindings/cpp/src/work_queue.cpp
+++ b/proton-c/bindings/cpp/src/work_queue.cpp
@@ -36,6 +36,8 @@ work_queue::~work_queue() {}
work_queue& work_queue::operator=(impl* i) { impl_.reset(i); return *this; }
bool work_queue::add(work f) {
+ // If we have no actual work queue, then can't defer
+ if (!impl_) return false;
return impl_->add(f);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[13/20] qpid-proton git commit: PROTON-1481: [C++ binding] Added
simpler way to get work_queue from model objects
Posted by as...@apache.org.
PROTON-1481: [C++ binding] Added simpler way to get work_queue from model objects
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/d1c91a42
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/d1c91a42
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/d1c91a42
Branch: refs/heads/master
Commit: d1c91a42e59f618fccb6838ffd30372a179759e2
Parents: 45d5612
Author: Andrew Stitcher <as...@apache.org>
Authored: Fri May 19 12:27:17 2017 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
examples/cpp/broker.cpp | 4 ++--
examples/cpp/scheduled_send.cpp | 12 ++++++++----
examples/cpp/scheduled_send_03.cpp | 2 +-
proton-c/bindings/cpp/include/proton/connection.hpp | 3 +++
proton-c/bindings/cpp/include/proton/link.hpp | 3 +++
proton-c/bindings/cpp/include/proton/session.hpp | 3 +++
proton-c/bindings/cpp/include/proton/transfer.hpp | 3 +++
proton-c/bindings/cpp/src/connection.cpp | 4 ++++
proton-c/bindings/cpp/src/link.cpp | 4 ++++
proton-c/bindings/cpp/src/session.cpp | 4 ++++
proton-c/bindings/cpp/src/transfer.cpp | 2 ++
11 files changed, 37 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d1c91a42/examples/cpp/broker.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/broker.cpp b/examples/cpp/broker.cpp
index 8c2d2ff..d39314c 100644
--- a/examples/cpp/broker.cpp
+++ b/examples/cpp/broker.cpp
@@ -182,7 +182,7 @@ class Sender : public proton::messaging_handler {
public:
Sender(proton::sender s, senders& ss) :
- sender_(s), senders_(ss), work_queue_(make_thread_safe(s).get()->work_queue()), queue_(0), pending_credit_(0)
+ sender_(s), senders_(ss), work_queue_(s.work_queue()), queue_(0), pending_credit_(0)
{}
void add(proton::void_function0& f) {
@@ -330,7 +330,7 @@ class Receiver : public proton::messaging_handler {
public:
Receiver(proton::receiver r) :
- receiver_(r), work_queue_(make_thread_safe(r).get()->work_queue()), queue_(0)
+ receiver_(r), work_queue_(r.work_queue()), queue_(0)
{}
void add(proton::void_function0& f) {
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d1c91a42/examples/cpp/scheduled_send.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/scheduled_send.cpp b/examples/cpp/scheduled_send.cpp
index bbef15b..2914c44 100644
--- a/examples/cpp/scheduled_send.cpp
+++ b/examples/cpp/scheduled_send.cpp
@@ -56,12 +56,16 @@ class scheduled_sender : public proton::messaging_handler {
// The awkward looking double lambda is necessary because the scheduled lambdas run in the container context
// and must arrange lambdas for send and close to happen in the connection context.
void on_container_start(proton::container &c) OVERRIDE {
- sender = c.open_sender(url);
- work_queue = &proton::make_thread_safe(sender).get()->work_queue();
+ c.open_sender(url);
+ }
+
+ void on_sender_open(proton::sender &s) OVERRIDE {
+ sender = s;
+ work_queue = &s.work_queue();
// Call this->cancel after timeout.
- c.schedule(timeout, [this]() { this->work_queue->add( [this]() { this->cancel(); }); });
+ s.container().schedule(timeout, [this]() { this->work_queue->add( [this]() { this->cancel(); }); });
// Start regular ticks every interval.
- c.schedule(interval, [this]() { this->work_queue->add( [this]() { this->tick(); }); });
+ s.container().schedule(interval, [this]() { this->work_queue->add( [this]() { this->tick(); }); });
}
void cancel() {
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d1c91a42/examples/cpp/scheduled_send_03.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/scheduled_send_03.cpp b/examples/cpp/scheduled_send_03.cpp
index 4b1b626..c3c63c8 100644
--- a/examples/cpp/scheduled_send_03.cpp
+++ b/examples/cpp/scheduled_send_03.cpp
@@ -96,7 +96,7 @@ class scheduled_sender : public proton::messaging_handler {
}
void on_sender_open(proton::sender & s) OVERRIDE {
- work_queue = &proton::make_thread_safe(s).get()->work_queue();
+ work_queue = &s.work_queue();
do_cancel = cancel_fn(*this, s);
do_tick = tick_fn(*this, s);
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d1c91a42/proton-c/bindings/cpp/include/proton/connection.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/connection.hpp b/proton-c/bindings/cpp/include/proton/connection.hpp
index 331ba82..ef75a4e 100644
--- a/proton-c/bindings/cpp/include/proton/connection.hpp
+++ b/proton-c/bindings/cpp/include/proton/connection.hpp
@@ -59,6 +59,9 @@ PN_CPP_CLASS_EXTERN connection : public internal::object<pn_connection_t>, publi
/// container
PN_CPP_EXTERN class container &container() const;
+ /// Get the work_queue for the connection.
+ PN_CPP_EXTERN class work_queue& work_queue() const;
+
/// Get the transport for the connection.
PN_CPP_EXTERN class transport transport() const;
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d1c91a42/proton-c/bindings/cpp/include/proton/link.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/link.hpp b/proton-c/bindings/cpp/include/proton/link.hpp
index 8534f21..8627ec9 100644
--- a/proton-c/bindings/cpp/include/proton/link.hpp
+++ b/proton-c/bindings/cpp/include/proton/link.hpp
@@ -78,6 +78,9 @@ PN_CPP_CLASS_EXTERN link : public internal::object<pn_link_t> , public endpoint
/// The container for this link.
PN_CPP_EXTERN class container &container() const;
+ /// Get the work_queue for the link.
+ PN_CPP_EXTERN class work_queue& work_queue() const;
+
/// The connection that owns this link.
PN_CPP_EXTERN class connection connection() const;
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d1c91a42/proton-c/bindings/cpp/include/proton/session.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/session.hpp b/proton-c/bindings/cpp/include/proton/session.hpp
index cbdf1b9..8d4184b 100644
--- a/proton-c/bindings/cpp/include/proton/session.hpp
+++ b/proton-c/bindings/cpp/include/proton/session.hpp
@@ -66,6 +66,9 @@ PN_CPP_CLASS_EXTERN session : public internal::object<pn_session_t>, public endp
/// Get the container for this session.
PN_CPP_EXTERN class container &container() const;
+ /// Get the work_queue for the session.
+ PN_CPP_EXTERN class work_queue& work_queue() const;
+
/// Get the connection this session belongs to.
PN_CPP_EXTERN class connection connection() const;
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d1c91a42/proton-c/bindings/cpp/include/proton/transfer.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/transfer.hpp b/proton-c/bindings/cpp/include/proton/transfer.hpp
index ea073f6..80b0860 100644
--- a/proton-c/bindings/cpp/include/proton/transfer.hpp
+++ b/proton-c/bindings/cpp/include/proton/transfer.hpp
@@ -61,6 +61,9 @@ class transfer : public internal::object<pn_delivery_t> {
/// Return the connection for this transfer.
PN_CPP_EXTERN class connection connection() const;
+ /// Get the work_queue for the transfer.
+ PN_CPP_EXTERN class work_queue& work_queue() const;
+
/// Return the container for this transfer.
PN_CPP_EXTERN class container &container() const;
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d1c91a42/proton-c/bindings/cpp/src/connection.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connection.cpp b/proton-c/bindings/cpp/src/connection.cpp
index 5432a42..a37d3b5 100644
--- a/proton-c/bindings/cpp/src/connection.cpp
+++ b/proton-c/bindings/cpp/src/connection.cpp
@@ -76,6 +76,10 @@ container& connection::container() const {
return *c;
}
+work_queue& connection::work_queue() const {
+ return connection_context::get(pn_object()).work_queue_;
+}
+
session_range connection::sessions() const {
return session_range(session_iterator(make_wrapper(pn_session_head(pn_object(), 0))));
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d1c91a42/proton-c/bindings/cpp/src/link.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/link.cpp b/proton-c/bindings/cpp/src/link.cpp
index eb4ccb1..1cb87ba 100644
--- a/proton-c/bindings/cpp/src/link.cpp
+++ b/proton-c/bindings/cpp/src/link.cpp
@@ -70,6 +70,10 @@ container& link::container() const {
return connection().container();
}
+work_queue& link::work_queue() const {
+ return connection().work_queue();
+}
+
class connection link::connection() const {
return make_wrapper(pn_session_connection(pn_link_session(pn_object())));
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d1c91a42/proton-c/bindings/cpp/src/session.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/session.cpp b/proton-c/bindings/cpp/src/session.cpp
index a2b318e..4c3932b 100644
--- a/proton-c/bindings/cpp/src/session.cpp
+++ b/proton-c/bindings/cpp/src/session.cpp
@@ -54,6 +54,10 @@ container& session::container() const {
return connection().container();
}
+work_queue& session::work_queue() const {
+ return connection().work_queue();
+}
+
connection session::connection() const {
return make_wrapper(pn_session_connection(pn_object()));
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d1c91a42/proton-c/bindings/cpp/src/transfer.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/transfer.cpp b/proton-c/bindings/cpp/src/transfer.cpp
index 78b6c0e..8066dd5 100644
--- a/proton-c/bindings/cpp/src/transfer.cpp
+++ b/proton-c/bindings/cpp/src/transfer.cpp
@@ -36,6 +36,8 @@ namespace proton {
session transfer::session() const { return make_wrapper(pn_link_session(pn_delivery_link(pn_object()))); }
connection transfer::connection() const { return make_wrapper(pn_session_connection(pn_link_session(pn_delivery_link(pn_object())))); }
container& transfer::container() const { return connection().container(); }
+work_queue& transfer::work_queue() const { return connection().work_queue(); }
+
bool transfer::settled() const { return pn_delivery_settled(pn_object()); }
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[08/20] qpid-proton git commit: NO-JIRA: Header file corrections
Posted by as...@apache.org.
NO-JIRA: Header file corrections
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/d168b7be
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/d168b7be
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/d168b7be
Branch: refs/heads/master
Commit: d168b7be34c831494ee172dd216ec7fe438845ce
Parents: 1a513d6
Author: Andrew Stitcher <as...@apache.org>
Authored: Fri Mar 3 15:51:58 2017 -0500
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
proton-c/bindings/cpp/src/connection.cpp | 1 +
proton-c/bindings/cpp/src/connection_options.cpp | 1 +
proton-c/bindings/cpp/src/contexts.cpp | 3 +++
proton-c/bindings/cpp/src/include/contexts.hpp | 10 +++-------
proton-c/bindings/cpp/src/io/connection_driver.cpp | 1 +
proton-c/bindings/cpp/src/io/link_namer.cpp | 5 ++++-
proton-c/bindings/cpp/src/messaging_adapter.cpp | 4 ++++
proton-c/bindings/cpp/src/session.cpp | 1 +
8 files changed, 18 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d168b7be/proton-c/bindings/cpp/src/connection.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connection.cpp b/proton-c/bindings/cpp/src/connection.cpp
index 113a06f..11d5624 100644
--- a/proton-c/bindings/cpp/src/connection.cpp
+++ b/proton-c/bindings/cpp/src/connection.cpp
@@ -22,6 +22,7 @@
#include "proton_bits.hpp"
#include "proton/connection.hpp"
+#include "proton/connection_options.hpp"
#include "proton/container.hpp"
#include "proton/error.hpp"
#include "proton/event_loop.hpp"
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d168b7be/proton-c/bindings/cpp/src/connection_options.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connection_options.cpp b/proton-c/bindings/cpp/src/connection_options.cpp
index 6321df5..0848c73 100644
--- a/proton-c/bindings/cpp/src/connection_options.cpp
+++ b/proton-c/bindings/cpp/src/connection_options.cpp
@@ -19,6 +19,7 @@
*
*/
#include "proton/fwd.hpp"
+#include "proton/connection.hpp"
#include "proton/connection_options.hpp"
#include "proton/messaging_handler.hpp"
#include "proton/reconnect_timer.hpp"
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d168b7be/proton-c/bindings/cpp/src/contexts.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/contexts.cpp b/proton-c/bindings/cpp/src/contexts.cpp
index 81ef5eb..152828a 100644
--- a/proton-c/bindings/cpp/src/contexts.cpp
+++ b/proton-c/bindings/cpp/src/contexts.cpp
@@ -23,6 +23,7 @@
#include "msg.hpp"
#include "proton_bits.hpp"
+#include "proton/connection_options.hpp"
#include "proton/error.hpp"
#include <proton/connection.h>
@@ -69,6 +70,8 @@ connection_context::connection_context() :
container(0), default_session(0), link_gen(0), handler(0), listener_context_(0)
{}
+listener_context::listener_context() : listen_handler_(0) {}
+
connection_context& connection_context::get(pn_connection_t *c) {
return ref<connection_context>(id(pn_connection_attachments(c), CONNECTION_CONTEXT));
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d168b7be/proton-c/bindings/cpp/src/include/contexts.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/contexts.hpp b/proton-c/bindings/cpp/src/include/contexts.hpp
index 637cbec..ab0661a 100644
--- a/proton-c/bindings/cpp/src/include/contexts.hpp
+++ b/proton-c/bindings/cpp/src/include/contexts.hpp
@@ -22,16 +22,10 @@
*
*/
-#include "proton/connection.hpp"
-#include "proton/container.hpp"
-#include "proton/io/connection_driver.hpp"
#include "proton/event_loop.hpp"
-#include "proton/listen_handler.hpp"
#include "proton/message.hpp"
#include "proton/internal/pn_unique_ptr.hpp"
-#include "proton/io/link_namer.hpp"
-
struct pn_record_t;
struct pn_link_t;
struct pn_session_t;
@@ -43,6 +37,8 @@ namespace proton {
class proton_handler;
class reconnect_timer;
+namespace io {class link_namer;}
+
// Base class for C++ classes that are used as proton contexts.
// Contexts are pn_objects managed by pn reference counts, the C++ value is allocated in-place.
class context {
@@ -101,7 +97,7 @@ class connection_context : public context {
class listener_context : public context {
public:
- listener_context() : listen_handler_(0) {}
+ listener_context();
static listener_context& get(pn_listener_t* c);
listen_handler* listen_handler_;
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d168b7be/proton-c/bindings/cpp/src/io/connection_driver.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/io/connection_driver.cpp b/proton-c/bindings/cpp/src/io/connection_driver.cpp
index 0f5bc33..58af052 100644
--- a/proton-c/bindings/cpp/src/io/connection_driver.cpp
+++ b/proton-c/bindings/cpp/src/io/connection_driver.cpp
@@ -19,6 +19,7 @@
#include "proton/io/connection_driver.hpp"
+#include "proton/container.hpp"
#include "proton/event_loop.hpp"
#include "proton/error.hpp"
#include "proton/messaging_handler.hpp"
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d168b7be/proton-c/bindings/cpp/src/io/link_namer.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/io/link_namer.cpp b/proton-c/bindings/cpp/src/io/link_namer.cpp
index 28c35c7..2ac5402 100644
--- a/proton-c/bindings/cpp/src/io/link_namer.cpp
+++ b/proton-c/bindings/cpp/src/io/link_namer.cpp
@@ -18,8 +18,11 @@
*/
#include "proton/io/link_namer.hpp"
-#include "proton_bits.hpp"
+
+#include "proton/connection.hpp"
+
#include "contexts.hpp"
+#include "proton_bits.hpp"
namespace proton {
namespace io {
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d168b7be/proton-c/bindings/cpp/src/messaging_adapter.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/messaging_adapter.cpp b/proton-c/bindings/cpp/src/messaging_adapter.cpp
index 3a16930..521566c 100644
--- a/proton-c/bindings/cpp/src/messaging_adapter.cpp
+++ b/proton-c/bindings/cpp/src/messaging_adapter.cpp
@@ -21,12 +21,16 @@
#include "messaging_adapter.hpp"
+#include "proton/connection.hpp"
+#include "proton/container.hpp"
#include "proton/delivery.hpp"
#include "proton/error.hpp"
#include "proton/messaging_handler.hpp"
+#include "proton/receiver.hpp"
#include "proton/receiver_options.hpp"
#include "proton/sender.hpp"
#include "proton/sender_options.hpp"
+#include "proton/session.hpp"
#include "proton/tracker.hpp"
#include "proton/transport.hpp"
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/d168b7be/proton-c/bindings/cpp/src/session.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/session.cpp b/proton-c/bindings/cpp/src/session.cpp
index 8036d2c..a2b318e 100644
--- a/proton-c/bindings/cpp/src/session.cpp
+++ b/proton-c/bindings/cpp/src/session.cpp
@@ -21,6 +21,7 @@
#include "proton/session.hpp"
#include "proton/connection.hpp"
+#include "proton/io/link_namer.hpp"
#include "proton/receiver_options.hpp"
#include "proton/sender_options.hpp"
#include "proton/session_options.hpp"
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[06/20] qpid-proton git commit: PROTON-1400: [C++ binding] Remove
reactor container implementation files.
Posted by as...@apache.org.
PROTON-1400: [C++ binding] Remove reactor container implementation files.
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/9c1797cb
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/9c1797cb
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/9c1797cb
Branch: refs/heads/master
Commit: 9c1797cbc8451ed65c2e153e0d247783200209ae
Parents: 9fad779
Author: Andrew Stitcher <as...@apache.org>
Authored: Wed Feb 8 20:12:36 2017 -0500
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
.../bindings/cpp/src/connection_options.cpp | 1 -
proton-c/bindings/cpp/src/connector.cpp | 105 ------
proton-c/bindings/cpp/src/container_impl.cpp | 365 -------------------
proton-c/bindings/cpp/src/include/acceptor.hpp | 62 ----
proton-c/bindings/cpp/src/include/connector.hpp | 66 ----
.../bindings/cpp/src/include/container_impl.hpp | 119 ------
.../cpp/src/include/event_loop_impl.hpp | 39 --
.../bindings/cpp/src/include/proton_bits.hpp | 4 -
proton-c/bindings/cpp/src/include/reactor.hpp | 100 -----
proton-c/bindings/cpp/src/reactor.cpp | 95 -----
10 files changed, 956 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c1797cb/proton-c/bindings/cpp/src/connection_options.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connection_options.cpp b/proton-c/bindings/cpp/src/connection_options.cpp
index 4644094..6321df5 100644
--- a/proton-c/bindings/cpp/src/connection_options.cpp
+++ b/proton-c/bindings/cpp/src/connection_options.cpp
@@ -26,7 +26,6 @@
#include "proton/ssl.hpp"
#include "proton/sasl.hpp"
-#include "acceptor.hpp"
#include "contexts.hpp"
#include "messaging_adapter.hpp"
#include "msg.hpp"
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c1797cb/proton-c/bindings/cpp/src/connector.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connector.cpp b/proton-c/bindings/cpp/src/connector.cpp
deleted file mode 100644
index 0467d60..0000000
--- a/proton-c/bindings/cpp/src/connector.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- *
- * 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 "connector.hpp"
-
-#include "proton/connection.hpp"
-#include "proton/transport.hpp"
-#include "proton/container.hpp"
-#include "proton/reconnect_timer.hpp"
-#include "proton/sasl.hpp"
-#include "proton/url.hpp"
-
-#include "container_impl.hpp"
-#include "proton_bits.hpp"
-#include "proton_event.hpp"
-
-#include <proton/connection.h>
-#include <proton/transport.h>
-
-namespace proton {
-
-container::impl::connector::connector(connection&c, const connection_options& options, const url& a) :
- connection_(c), options_(options), address_(a), reconnect_timer_(0)
-{}
-
-container::impl::connector::~connector() { delete reconnect_timer_; }
-
-void container::impl::connector::reconnect_timer(const class reconnect_timer &rt) {
- delete reconnect_timer_;
- reconnect_timer_ = new class reconnect_timer(rt);
-}
-
-void container::impl::connector::connect() {
- pn_transport_t *pnt = pn_transport();
- transport t(make_wrapper(pnt));
- pn_transport_bind(pnt, unwrap(connection_));
- pn_decref(pnt);
- // Apply options to the new transport.
- options_.apply_bound(connection_);
-}
-
-void container::impl::connector::on_connection_local_open(proton_event &) {
- connect();
-}
-
-void container::impl::connector::on_connection_remote_open(proton_event &) {
- if (reconnect_timer_) {
- reconnect_timer_->reset();
- }
-}
-
-void container::impl::connector::on_connection_init(proton_event &) {
-}
-
-void container::impl::connector::on_transport_tail_closed(proton_event &e) {
- on_transport_closed(e);
-}
-
-void container::impl::connector::on_transport_closed(proton_event &) {
- if (!connection_) return;
- if (connection_.active()) {
- if (reconnect_timer_) {
- pn_transport_unbind(unwrap(connection_.transport()));
- int delay = reconnect_timer_->next_delay(timestamp::now());
- if (delay >= 0) {
- if (delay == 0) {
- // log "Disconnected, reconnecting..."
- connect();
- return;
- }
- else {
- // log "Disconnected, reconnecting in " << delay << " milliseconds"
- container::impl::schedule(connection_.container(), delay, this);
- return;
- }
- }
- }
- }
- pn_connection_release(unwrap(connection_));
- connection_ = 0;
-}
-
-void container::impl::connector::on_timer_task(proton_event &) {
- connect();
-}
-
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c1797cb/proton-c/bindings/cpp/src/container_impl.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/container_impl.cpp b/proton-c/bindings/cpp/src/container_impl.cpp
deleted file mode 100644
index e0851a9..0000000
--- a/proton-c/bindings/cpp/src/container_impl.cpp
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- *
- * 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 "proton/connection_options.hpp"
-#include "proton/connection.hpp"
-#include "proton/error.hpp"
-#include "proton/event_loop.hpp"
-#include "proton/listener.hpp"
-#include "proton/receiver.hpp"
-#include "proton/sender.hpp"
-#include "proton/session.hpp"
-#include "proton/ssl.hpp"
-#include "proton/sasl.hpp"
-#include "proton/thread_safe.hpp"
-#include "proton/transport.hpp"
-#include "proton/url.hpp"
-#include "proton/uuid.hpp"
-
-#include "acceptor.hpp"
-#include "connector.hpp"
-#include "container_impl.hpp"
-#include "contexts.hpp"
-#include "event_loop_impl.hpp"
-#include "messaging_adapter.hpp"
-#include "msg.hpp"
-#include "proton_bits.hpp"
-#include "proton_event.hpp"
-
-#include <proton/connection.h>
-#include <proton/handlers.h>
-#include <proton/reactor.h>
-#include <proton/session.h>
-
-namespace proton {
-
-class container::impl::handler_context {
- public:
- static handler_context& get(pn_handler_t* h) {
- return *reinterpret_cast<handler_context*>(pn_handler_mem(h));
- }
- static void cleanup(pn_handler_t*) {}
-
- /*
- * NOTE: this call, at the transition from C to C++ is possibly
- * the biggest performance bottleneck. "Average" clients ignore
- * 90% of these events. Current strategy is to create the
- * messaging_event on the stack. For success, the messaging_event
- * should be small and free of indirect malloc/free/new/delete.
- */
-
- static void dispatch(pn_handler_t *c_handler, pn_event_t *c_event, pn_event_type_t)
- {
- handler_context& hc(handler_context::get(c_handler));
- proton_event pevent(c_event, hc.container_);
- pevent.dispatch(*hc.handler_);
- return;
- }
-
- container *container_;
- proton_handler *handler_;
-};
-
-// Used to sniff for connector events before the reactor's global handler sees them.
-class container::impl::override_handler : public proton_handler
-{
- public:
- internal::pn_ptr<pn_handler_t> base_handler;
- container::impl &container_impl_;
-
- override_handler(pn_handler_t *h, container::impl &c) : base_handler(h), container_impl_(c) {}
-
- virtual void on_unhandled(proton_event &pe) {
- proton_event::event_type type = pe.type();
- if (type==proton_event::EVENT_NONE) return; // Also not from the reactor
-
- pn_event_t *cevent = pe.pn_event();
- pn_connection_t *conn = pn_event_connection(cevent);
- if (conn) {
- proton_handler *oh = connection_context::get(conn).handler.get();
- if (oh && type != proton_event::CONNECTION_INIT) {
- // Send event to connector
- pe.dispatch(*oh);
- }
- else if (!oh && type == proton_event::CONNECTION_INIT) {
- // Newly accepted connection from lister socket
- connection c(make_wrapper(conn));
- container_impl_.configure_server_connection(c);
- }
- }
- pn_handler_dispatch(base_handler.get(), cevent, pn_event_type_t(type));
- }
-};
-
-internal::pn_ptr<pn_handler_t> container::impl::cpp_handler(proton_handler *h) {
- pn_handler_t *handler = h ? pn_handler_new(&handler_context::dispatch,
- sizeof(class handler_context),
- &handler_context::cleanup) : 0;
- if (handler) {
- handler_context &hc = handler_context::get(handler);
- hc.container_ = &container_;
- hc.handler_ = h;
- }
- return internal::take_ownership(handler);
-}
-
-container::impl::impl(container& c, const std::string& id, messaging_handler *mh) :
- container_(c),
- reactor_(reactor::create()),
- id_(id.empty() ? uuid::random().str() : id),
- auto_stop_(true)
-{
- container_context::set(reactor_, container_);
-
- // Set our own global handler that "subclasses" the existing one
- pn_handler_t *global_handler = reactor_.pn_global_handler();
- proton_handler* oh = new override_handler(global_handler, *this);
- handlers_.push_back(oh);
- reactor_.pn_global_handler(cpp_handler(oh).get());
- if (mh) {
- proton_handler* h = new messaging_adapter(*mh);
- handlers_.push_back(h);
- reactor_.pn_handler(cpp_handler(h).get());
- }
-
- // Note: we have just set up the following handlers that see
- // events in this order: messaging_adapter, connector override,
- // the reactor's default globalhandler (pn_iohandler)
-}
-
-namespace {
-void close_acceptor(acceptor a) {
- listen_handler*& lh = listener_context::get(unwrap(a)).listen_handler_;
- if (lh) {
- lh->on_close();
- lh = 0;
- }
- a.close();
-}
-}
-
-container::impl::~impl() {
- for (acceptors::iterator i = acceptors_.begin(); i != acceptors_.end(); ++i)
- close_acceptor(i->second);
-}
-
-// TODO aconway 2016-06-07: this is not thread safe. It is sufficient for using
-// default_container::schedule() inside a handler but not for inject() from
-// another thread.
-bool event_loop::impl::inject(void_function0& f) {
- try { f(); } catch(...) {}
- return true;
-}
-
-#if PN_CPP_HAS_STD_FUNCTION
-bool event_loop::impl::inject(std::function<void()> f) {
- try { f(); } catch(...) {}
- return true;
-}
-#endif
-
-returned<connection> container::impl::connect(const std::string &urlstr, const connection_options &user_opts) {
- connection_options opts = client_connection_options(); // Defaults
- opts.update(user_opts);
- messaging_handler* mh = opts.handler();
- internal::pn_ptr<pn_handler_t> chandler;
- if (mh) {
- proton_handler* h = new messaging_adapter(*mh);
- handlers_.push_back(h);
- chandler = cpp_handler(h);
- }
-
- proton::url url(urlstr);
- connection conn(reactor_.connection_to_host(url.host(), url.port(), chandler.get()));
- internal::pn_unique_ptr<connector> ctor(new connector(conn, opts, url));
- connection_context& cc(connection_context::get(unwrap(conn)));
- cc.handler.reset(ctor.release());
- cc.event_loop_ = new event_loop::impl;
-
- pn_connection_t *pnc = unwrap(conn);
- pn_connection_set_container(pnc, id_.c_str());
- pn_connection_set_hostname(pnc, url.host().c_str());
- if (!url.user().empty())
- pn_connection_set_user(pnc, url.user().c_str());
- if (!url.password().empty())
- pn_connection_set_password(pnc, url.password().c_str());
-
- conn.open(opts);
- return make_thread_safe(conn);
-}
-
-returned<sender> container::impl::open_sender(const std::string &url, const proton::sender_options &o1, const connection_options &o2) {
- proton::sender_options lopts(sender_options_);
- lopts.update(o1);
- connection_options copts(client_connection_options_);
- copts.update(o2);
- connection conn = connect(url, copts);
- return make_thread_safe(conn.default_session().open_sender(proton::url(url).path(), lopts));
-}
-
-returned<receiver> container::impl::open_receiver(const std::string &url, const proton::receiver_options &o1, const connection_options &o2) {
- proton::receiver_options lopts(receiver_options_);
- lopts.update(o1);
- connection_options copts(client_connection_options_);
- copts.update(o2);
- connection conn = connect(url, copts);
- return make_thread_safe(
- conn.default_session().open_receiver(proton::url(url).path(), lopts));
-}
-
-listener container::impl::listen(const std::string& url, listen_handler& lh) {
- if (acceptors_.find(url) != acceptors_.end())
- throw error("already listening on " + url);
- connection_options opts = server_connection_options(); // Defaults
-
- messaging_handler* mh = opts.handler();
- internal::pn_ptr<pn_handler_t> chandler;
- if (mh) {
- proton_handler* h = new messaging_adapter(*mh);
- handlers_.push_back(h);
- chandler = cpp_handler(h);
- }
-
- proton::url u(url);
- pn_acceptor_t *acptr = pn_reactor_acceptor(
- unwrap(reactor_), u.host().c_str(), u.port().c_str(), chandler.get());
- if (!acptr) {
- std::string err(pn_error_text(pn_reactor_error(unwrap(reactor_))));
- lh.on_error(err);
- lh.on_close();
- throw error(err);
- }
- // Do not use pn_acceptor_set_ssl_domain(). Manage the incoming connections ourselves for
- // more flexibility (i.e. ability to change the server cert for a long running listener).
- listener_context& lc(listener_context::get(acptr));
- lc.listen_handler_ = &lh;
- lc.ssl = u.scheme() == url::AMQPS;
- listener_context::get(acptr).listen_handler_ = &lh;
- acceptors_[url] = make_wrapper(acptr);
- return listener(container_, url);
-}
-
-void container::impl::stop_listening(const std::string& url) {
- acceptors::iterator i = acceptors_.find(url);
- if (i != acceptors_.end())
- close_acceptor(i->second);
-}
-
-void container::impl::schedule(impl& ci, int delay, proton_handler *h) {
- internal::pn_ptr<pn_handler_t> task_handler;
- if (h)
- task_handler = ci.cpp_handler(h);
- ci.reactor_.schedule(delay, task_handler.get());
-}
-
-void container::impl::schedule(container& c, int delay, proton_handler *h) {
- schedule(*c.impl_.get(), delay, h);
-}
-
-namespace {
-// Abstract base for timer_handler_std and timer_handler_03
-struct timer_handler : public proton_handler, public void_function0 {
- void on_timer_task(proton_event& ) PN_CPP_OVERRIDE {
- (*this)();
- delete this;
- }
- void on_reactor_final(proton_event&) PN_CPP_OVERRIDE {
- delete this;
- }
-};
-
-struct timer_handler_03 : public timer_handler {
- void_function0& func;
- timer_handler_03(void_function0& f): func(f) {}
- void operator()() PN_CPP_OVERRIDE { func(); }
-};
-}
-
-void container::impl::schedule(duration delay, void_function0& f) {
- schedule(*this, delay.milliseconds(), new timer_handler_03(f));
-}
-
-#if PN_CPP_HAS_STD_FUNCTION
-namespace {
-struct timer_handler_std : public timer_handler {
- std::function<void()> func;
- timer_handler_std(std::function<void()> f): func(f) {}
- void operator()() PN_CPP_OVERRIDE { func(); }
-};
-}
-
-void container::impl::schedule(duration delay, std::function<void()> f) {
- schedule(*this, delay.milliseconds(), new timer_handler_std(f));
-}
-#endif
-
-void container::impl::client_connection_options(const connection_options &opts) {
- client_connection_options_ = opts;
-}
-
-void container::impl::server_connection_options(const connection_options &opts) {
- server_connection_options_ = opts;
-}
-
-void container::impl::sender_options(const proton::sender_options &opts) {
- sender_options_ = opts;
-}
-
-void container::impl::receiver_options(const proton::receiver_options &opts) {
- receiver_options_ = opts;
-}
-
-void container::impl::configure_server_connection(connection &c) {
- pn_acceptor_t *pnp = pn_connection_acceptor(unwrap(c));
- listener_context &lc(listener_context::get(pnp));
- pn_connection_set_container(unwrap(c), id_.c_str());
- connection_options opts = server_connection_options_;
- opts.update(lc.get_options());
- // Unbound options don't apply to server connection
- opts.apply_bound(c);
- // Handler applied separately
- messaging_handler* mh = opts.handler();
- if (mh) {
- proton_handler* h = new messaging_adapter(*mh);
- handlers_.push_back(h);
- internal::pn_ptr<pn_handler_t> chandler = cpp_handler(h);
- pn_record_t *record = pn_connection_attachments(unwrap(c));
- pn_record_set_handler(record, chandler.get());
- }
- connection_context::get(unwrap(c)).event_loop_ = new event_loop::impl;
-}
-
-void container::impl::run() {
- do {
- reactor_.run();
- } while (!auto_stop_);
-}
-
-void container::impl::stop(const error_condition&) {
- reactor_.stop();
- auto_stop_ = true;
-}
-
-void container::impl::auto_stop(bool set) {
- auto_stop_ = set;
-}
-
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c1797cb/proton-c/bindings/cpp/src/include/acceptor.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/acceptor.hpp b/proton-c/bindings/cpp/src/include/acceptor.hpp
deleted file mode 100644
index 9a25592..0000000
--- a/proton-c/bindings/cpp/src/include/acceptor.hpp
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef PROTON_ACCEPTOR_HPP
-#define PROTON_ACCEPTOR_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 "proton/internal/export.hpp"
-#include "proton/internal/object.hpp"
-
-#include <proton/reactor.h>
-
-struct pn_acceptor_t;
-
-namespace proton {
-
-/// A context for accepting inbound connections.
-///
-/// @see container::listen
-class acceptor : public internal::object<pn_acceptor_t> {
- /// @cond INTERNAL
- acceptor(pn_acceptor_t* a) : internal::object<pn_acceptor_t>(a) {}
- /// @endcond
-
- public:
- acceptor() : internal::object<pn_acceptor_t>(0) {}
-
- /// Close the acceptor.
- PN_CPP_EXTERN void close();
-
- /// Return the current set of connection options applied to
- /// inbound connectons by the acceptor.
- ///
- /// Note that changes made to the connection options only affect
- /// connections accepted after this call returns.
- PN_CPP_EXTERN class connection_options &connection_options();
-
- /// @cond INTERNAL
- friend class internal::factory<acceptor>;
- /// @endcond
-};
-
-} // proton
-
-#endif // PROTON_ACCEPTOR_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c1797cb/proton-c/bindings/cpp/src/include/connector.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/connector.hpp b/proton-c/bindings/cpp/src/include/connector.hpp
deleted file mode 100644
index 6bcd0db..0000000
--- a/proton-c/bindings/cpp/src/include/connector.hpp
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef PROTON_CPP_CONNECTOR_HANDLER_H
-#define PROTON_CPP_CONNECTOR_HANDLER_H
-
-/*
- *
- * 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 "proton/connection.hpp"
-#include "proton/connection_options.hpp"
-#include <proton/event.h>
-#include <proton/reactor.h>
-#include "proton/url.hpp"
-
-#include "container_impl.hpp"
-#include "proton_handler.hpp"
-
-#include <string>
-
-
-namespace proton {
-
-class reconnect_timer;
-
-class container::impl::connector : public proton_handler
-{
- public:
- connector(connection &c, const connection_options &options, const url&);
- ~connector();
- const url &address() const { return address_; }
- void connect();
- void reconnect_timer(const class reconnect_timer &);
- virtual void on_connection_local_open(proton_event &e);
- virtual void on_connection_remote_open(proton_event &e);
- virtual void on_connection_init(proton_event &e);
- virtual void on_transport_closed(proton_event &e);
- virtual void on_transport_tail_closed(proton_event &e);
- virtual void on_timer_task(proton_event &e);
-
- private:
- connection connection_;
- const connection_options options_;
- const url address_;
- class reconnect_timer *reconnect_timer_;
-};
-
-
-}
-
-#endif /*!PROTON_CPP_CONNECTOR_HANDLER_H*/
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c1797cb/proton-c/bindings/cpp/src/include/container_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/container_impl.hpp b/proton-c/bindings/cpp/src/include/container_impl.hpp
deleted file mode 100644
index 7443150..0000000
--- a/proton-c/bindings/cpp/src/include/container_impl.hpp
+++ /dev/null
@@ -1,119 +0,0 @@
-#ifndef PROTON_CPP_CONTAINERIMPL_H
-#define PROTON_CPP_CONTAINERIMPL_H
-
-/*
- *
- * 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 "proton/fwd.hpp"
-#include "proton/container.hpp"
-#include "proton/connection.hpp"
-#include "proton/connection_options.hpp"
-#include "proton/duration.hpp"
-#include "proton/sender.hpp"
-#include "proton/sender_options.hpp"
-#include "proton/receiver.hpp"
-#include "proton/receiver_options.hpp"
-
-#include "messaging_adapter.hpp"
-#include "reactor.hpp"
-#include "proton_bits.hpp"
-#include "proton_handler.hpp"
-
-#include <list>
-#include <map>
-#include <string>
-
-namespace proton {
-
-class dispatch_helper;
-class connector;
-class acceptor;
-class url;
-class listen_handler;
-
-class container::impl {
- public:
- impl(container& c, const std::string& id, messaging_handler* = 0);
- ~impl();
- std::string id() const { return id_; }
- returned<connection> connect(const std::string&, const connection_options&);
- returned<sender> open_sender(
- const std::string&, const proton::sender_options &, const connection_options &);
- returned<receiver> open_receiver(
- const std::string&, const proton::receiver_options &, const connection_options &);
- listener listen(const std::string&, listen_handler& lh);
- void stop_listening(const std::string&);
- void client_connection_options(const connection_options &);
- connection_options client_connection_options() const { return client_connection_options_; }
- void server_connection_options(const connection_options &);
- connection_options server_connection_options() const { return server_connection_options_; }
- void sender_options(const proton::sender_options&);
- class sender_options sender_options() const { return sender_options_; }
- void receiver_options(const proton::receiver_options&);
- class receiver_options receiver_options() const { return receiver_options_; }
- void run();
- void stop(const error_condition& err);
- void auto_stop(bool set);
- void schedule(duration, void_function0&);
-#if PN_CPP_HAS_STD_FUNCTION
- void schedule(duration, std::function<void()>);
-#endif
-
- // non-interface functionality
- class connector;
-
- void configure_server_connection(connection &c);
- static void schedule(impl& ci, int delay, proton_handler *h);
- static void schedule(container& c, int delay, proton_handler *h);
- template <class T> static void set_handler(T s, messaging_handler* h);
-
- private:
- class handler_context;
- class override_handler;
-
- internal::pn_ptr<pn_handler_t> cpp_handler(proton_handler *h);
-
- container& container_;
- reactor reactor_;
- // Keep a list of all the handlers used by the container so they last as long as the container
- std::list<internal::pn_unique_ptr<proton_handler> > handlers_;
- std::string id_;
- connection_options client_connection_options_;
- connection_options server_connection_options_;
- proton::sender_options sender_options_;
- proton::receiver_options receiver_options_;
- typedef std::map<std::string, acceptor> acceptors;
- acceptors acceptors_;
- bool auto_stop_;
-};
-
-template <class T>
-void container::impl::set_handler(T s, messaging_handler* mh) {
- pn_record_t *record = internal::get_attachments(unwrap(s));
- proton_handler* h = new messaging_adapter(*mh);
- impl* ci = s.container().impl_.get();
- ci->handlers_.push_back(h);
- pn_record_set_handler(record, ci->cpp_handler(h).get());
-}
-
-}
-
-#endif /*!PROTON_CPP_CONTAINERIMPL_H*/
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c1797cb/proton-c/bindings/cpp/src/include/event_loop_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/event_loop_impl.hpp b/proton-c/bindings/cpp/src/include/event_loop_impl.hpp
deleted file mode 100644
index b34a981..0000000
--- a/proton-c/bindings/cpp/src/include/event_loop_impl.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef PROTON_CPP_EVENT_LOOP_IMPL_HPP
-#define PROTON_CPP_EVENT_LOOP_IMPL_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 "proton/fwd.hpp"
-
-namespace proton {
-
-class event_loop::impl {
- public:
- bool inject(void_function0& f);
-#if PN_CPP_HAS_CPP11
- bool inject(std::function<void()> f);
-#endif
-};
-
-}
-
-#endif // PROTON_CPP_EVENT_LOOP_IMPL_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c1797cb/proton-c/bindings/cpp/src/include/proton_bits.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proton_bits.hpp b/proton-c/bindings/cpp/src/include/proton_bits.hpp
index e72f343..fdd79b5 100644
--- a/proton-c/bindings/cpp/src/include/proton_bits.hpp
+++ b/proton-c/bindings/cpp/src/include/proton_bits.hpp
@@ -102,11 +102,9 @@ template <> struct wrapped<transfer> { typedef pn_delivery_t type; };
template <> struct wrapped<tracker> { typedef pn_delivery_t type; };
template <> struct wrapped<delivery> { typedef pn_delivery_t type; };
template <> struct wrapped<error_condition> { typedef pn_condition_t type; };
-template <> struct wrapped<acceptor> { typedef pn_acceptor_t type; }; // TODO aconway 2016-05-13: reactor only
template <> struct wrapped<terminus> { typedef pn_terminus_t type; };
template <> struct wrapped<source> { typedef pn_terminus_t type; };
template <> struct wrapped<target> { typedef pn_terminus_t type; };
-template <> struct wrapped<reactor> { typedef pn_reactor_t type; };
template <class T> struct wrapper {};
template <> struct wrapper<pn_data_t> { typedef internal::data type; };
@@ -118,9 +116,7 @@ template <> struct wrapper<pn_session_t> { typedef session type; };
template <> struct wrapper<pn_link_t> { typedef link type; };
template <> struct wrapper<pn_delivery_t> { typedef transfer type; };
template <> struct wrapper<pn_condition_t> { typedef error_condition type; };
-template <> struct wrapper<pn_acceptor_t> { typedef acceptor type; };
template <> struct wrapper<pn_terminus_t> { typedef terminus type; };
-template <> struct wrapper<pn_reactor_t> { typedef reactor type; };
// Factory for wrapper types
template <class T>
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c1797cb/proton-c/bindings/cpp/src/include/reactor.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/reactor.hpp b/proton-c/bindings/cpp/src/include/reactor.hpp
deleted file mode 100644
index 07678e4..0000000
--- a/proton-c/bindings/cpp/src/include/reactor.hpp
+++ /dev/null
@@ -1,100 +0,0 @@
-#ifndef REACTOR_HPP
-#define REACTOR_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.
- */
-
-/// @cond INTERNAL
-/// XXX remove
-
-#include "proton/fwd.hpp"
-#include "proton/internal/object.hpp"
-#include "proton/duration.hpp"
-#include "proton/timestamp.hpp"
-
-struct pn_reactor_t;
-struct pn_handler_t;
-struct pn_io_t;
-
-namespace proton {
-
-class acceptor;
-
-class reactor : public internal::object<pn_reactor_t> {
- public:
- reactor(pn_reactor_t* r = 0) : internal::object<pn_reactor_t>(r) {}
-
- /** Create a new reactor. */
- static reactor create();
-
- /** Open a connection to url and create a receiver with source=url.path() */
- acceptor listen(const proton::url &);
-
- /** Run the event loop, return when all connections and acceptors are closed. */
- void run();
-
- /** Start the reactor, you must call process() to process events */
- void start();
-
- /** Process events, return true if there are more events to process. */
- bool process();
-
- /** Stop the reactor, causes run() to return and process() to return false. */
- void stop();
-
- /// Identifier for the container
- std::string id() const;
-
- /// Get timeout, process() will return if there is no activity within the timeout.
- duration timeout();
-
- /// Set timeout, process() will return if there is no activity within the timeout.
- void timeout(duration timeout);
-
- timestamp mark();
- timestamp now();
-
- void schedule(int, pn_handler_t*);
-
- class connection connection(pn_handler_t*) const;
-
- class connection connection_to_host(const std::string &host, const std::string &port, pn_handler_t*) const;
-
- pn_handler_t* pn_handler() const;
-
- void pn_handler(pn_handler_t* );
-
- pn_handler_t* pn_global_handler() const;
-
- void pn_global_handler(pn_handler_t* );
-
- pn_io_t* pn_io() const;
-
- void wakeup();
- bool quiesced();
- void yield();
-
- friend class internal::factory<reactor>;
-};
-
-}
-
-/// @endcond
-
-#endif // REACTOR_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9c1797cb/proton-c/bindings/cpp/src/reactor.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/reactor.cpp b/proton-c/bindings/cpp/src/reactor.cpp
deleted file mode 100644
index 39f670f..0000000
--- a/proton-c/bindings/cpp/src/reactor.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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 "reactor.hpp"
-#include "acceptor.hpp"
-
-#include "proton/connection.hpp"
-#include "proton/url.hpp"
-
-#include "contexts.hpp"
-#include "proton_bits.hpp"
-
-#include <proton/reactor.h>
-
-namespace proton {
-
-reactor reactor::create() {
- return internal::take_ownership(pn_reactor()).get();
-}
-
-void reactor::run() { pn_reactor_run(pn_object()); }
-void reactor::start() { pn_reactor_start(pn_object()); }
-bool reactor::process() { return pn_reactor_process(pn_object()); }
-void reactor::stop() { pn_reactor_stop(pn_object()); }
-void reactor::wakeup() { pn_reactor_wakeup(pn_object()); }
-bool reactor::quiesced() { return pn_reactor_quiesced(pn_object()); }
-void reactor::yield() { pn_reactor_yield(pn_object()); }
-timestamp reactor::mark() { return timestamp(pn_reactor_mark(pn_object())); }
-timestamp reactor::now() { return timestamp(pn_reactor_now(pn_object())); }
-
-void acceptor::close() { pn_acceptor_close(pn_object()); }
-
-acceptor reactor::listen(const url& url){
- return make_wrapper(pn_reactor_acceptor(pn_object(), url.host().c_str(), url.port().c_str(), 0));
-}
-
-void reactor::schedule(int delay, pn_handler_t* handler) {
- pn_reactor_schedule(pn_object(), delay, handler);
-}
-
-connection reactor::connection(pn_handler_t* h) const {
- return make_wrapper(pn_reactor_connection(pn_object(), h));
-}
-
-connection reactor::connection_to_host(const std::string &host, const std::string &port, pn_handler_t* h) const {
- return make_wrapper(pn_reactor_connection_to_host(pn_object(), host.c_str(), port.c_str(), h));
-}
-
-void reactor::pn_handler(pn_handler_t* h) {
- pn_reactor_set_handler(pn_object(), h);
-}
-
-pn_handler_t* reactor::pn_handler() const {
- return pn_reactor_get_handler(pn_object());
-}
-
-void reactor::pn_global_handler(pn_handler_t* h) {
- pn_reactor_set_global_handler(pn_object(), h);
-}
-
-pn_handler_t* reactor::pn_global_handler() const {
- return pn_reactor_get_global_handler(pn_object());
-}
-
-duration reactor::timeout() {
- pn_millis_t tmo = pn_reactor_get_timeout(pn_object());
- if (tmo == PN_MILLIS_MAX)
- return duration::FOREVER;
- return duration(tmo);
-}
-
-void reactor::timeout(duration timeout) {
- if (timeout == duration::FOREVER || timeout.milliseconds() > PN_MILLIS_MAX)
- pn_reactor_set_timeout(pn_object(), PN_MILLIS_MAX);
- else
- pn_reactor_set_timeout(pn_object(), timeout.milliseconds());
-}
-
-}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[16/20] qpid-proton git commit: PROTON-1482: [C++ binding]
Implemented scheduling delaying work on a work_queue
Posted by as...@apache.org.
PROTON-1482: [C++ binding] Implemented scheduling delaying work on a work_queue
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/88c2d7d4
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/88c2d7d4
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/88c2d7d4
Branch: refs/heads/master
Commit: 88c2d7d481a6da96f85a6781ae27b488cfacd801
Parents: ca446ea
Author: Andrew Stitcher <as...@apache.org>
Authored: Fri May 19 00:59:55 2017 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
proton-c/bindings/cpp/include/proton/fwd.hpp | 1 +
.../bindings/cpp/include/proton/work_queue.hpp | 8 ++++++++
.../src/include/proactor_work_queue_impl.hpp | 3 +--
.../cpp/src/proactor_container_impl.cpp | 21 +++++++++++++-------
proton-c/bindings/cpp/src/work_queue.cpp | 8 ++++++++
5 files changed, 32 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/88c2d7d4/proton-c/bindings/cpp/include/proton/fwd.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/fwd.hpp b/proton-c/bindings/cpp/include/proton/fwd.hpp
index b839f42..5ade5fd 100644
--- a/proton-c/bindings/cpp/include/proton/fwd.hpp
+++ b/proton-c/bindings/cpp/include/proton/fwd.hpp
@@ -29,6 +29,7 @@ class connection;
class connection_options;
class container;
class delivery;
+class duration;
class error_condition;
class event;
class message;
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/88c2d7d4/proton-c/bindings/cpp/include/proton/work_queue.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/work_queue.hpp b/proton-c/bindings/cpp/include/proton/work_queue.hpp
index fe739f5..bef041c 100644
--- a/proton-c/bindings/cpp/include/proton/work_queue.hpp
+++ b/proton-c/bindings/cpp/include/proton/work_queue.hpp
@@ -94,6 +94,14 @@ class PN_CPP_CLASS_EXTERN work_queue {
/// or f() cannot be injected for any other reason.
PN_CPP_EXTERN bool add(work f);
+ /// Add work to the work queue after duration: f() will be called after the duration
+ /// serialised with other work in the queue: possibly in another thread.
+ ///
+ /// The scheduled execution is "best effort" and it is possible that after the elapsed duration
+ /// the work will not be able to be injected into the serialised context - there will be no
+ /// indication of this.
+ PN_CPP_EXTERN void schedule(duration, work);
+
private:
PN_CPP_EXTERN static work_queue& get(pn_connection_t*);
PN_CPP_EXTERN static work_queue& get(pn_session_t*);
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/88c2d7d4/proton-c/bindings/cpp/src/include/proactor_work_queue_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proactor_work_queue_impl.hpp b/proton-c/bindings/cpp/src/include/proactor_work_queue_impl.hpp
index ac0f803..1c94254 100644
--- a/proton-c/bindings/cpp/src/include/proactor_work_queue_impl.hpp
+++ b/proton-c/bindings/cpp/src/include/proactor_work_queue_impl.hpp
@@ -23,8 +23,6 @@
*/
#include "proton/fwd.hpp"
-#include "proton/internal/config.hpp"
-#include "proton/work_queue.hpp"
namespace proton {
@@ -32,6 +30,7 @@ class work_queue::impl {
public:
virtual ~impl() {};
virtual bool add(work f) = 0;
+ virtual void schedule(duration, work) = 0;
virtual void run_all_jobs() = 0;
virtual void finished() = 0;
};
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/88c2d7d4/proton-c/bindings/cpp/src/proactor_container_impl.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proactor_container_impl.cpp b/proton-c/bindings/cpp/src/proactor_container_impl.cpp
index 0135c08..62115fd 100644
--- a/proton-c/bindings/cpp/src/proactor_container_impl.cpp
+++ b/proton-c/bindings/cpp/src/proactor_container_impl.cpp
@@ -45,17 +45,26 @@ namespace proton {
class container::impl::common_work_queue : public work_queue::impl {
public:
- common_work_queue(): finished_(false) {}
+ common_work_queue(container::impl& c): container_(c), finished_(false) {}
typedef std::vector<work> jobs;
void run_all_jobs();
void finished() { finished_ = true; }
+ void schedule(duration, work);
+ container::impl& container_;
jobs jobs_;
bool finished_;
};
+void container::impl::common_work_queue::schedule(duration d, work f) {
+ // Note this is an unbounded work queue.
+ // A resource-safe implementation should be bounded.
+ if (finished_) return;
+ container_.schedule(d, make_work(&work_queue::impl::add, (work_queue::impl*)this, f));
+}
+
void container::impl::common_work_queue::run_all_jobs() {
jobs j;
// Lock this operation for mt
@@ -69,7 +78,7 @@ void container::impl::common_work_queue::run_all_jobs() {
class container::impl::connection_work_queue : public common_work_queue {
public:
- connection_work_queue(pn_connection_t* c): connection_(c) {}
+ connection_work_queue(container::impl& ct, pn_connection_t* c): common_work_queue(ct), connection_(c) {}
bool add(work f);
@@ -87,12 +96,10 @@ bool container::impl::connection_work_queue::add(work f) {
class container::impl::container_work_queue : public common_work_queue {
public:
- container_work_queue(container::impl& c): container_(c) {}
+ container_work_queue(container::impl& c): common_work_queue(c) {}
~container_work_queue() { container_.remove_work_queue(this); }
bool add(work f);
-
- container::impl& container_;
};
bool container::impl::container_work_queue::add(work f) {
@@ -147,7 +154,7 @@ proton::connection container::impl::connect_common(
connection_context& cc(connection_context::get(pnc));
cc.container = &container_;
cc.handler = mh;
- cc.work_queue_ = new container::impl::connection_work_queue(pnc);
+ cc.work_queue_ = new container::impl::connection_work_queue(*container_.impl_, pnc);
pn_connection_set_container(pnc, id_.c_str());
pn_connection_set_hostname(pnc, url.host().c_str());
@@ -327,7 +334,7 @@ bool container::impl::handle(pn_event_t* event) {
cc.container = &container_;
cc.listener_context_ = &lc;
cc.handler = opts.handler();
- cc.work_queue_ = new container::impl::connection_work_queue(c);
+ cc.work_queue_ = new container::impl::connection_work_queue(*container_.impl_, c);
pn_listener_accept(l, c);
return false;
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/88c2d7d4/proton-c/bindings/cpp/src/work_queue.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/work_queue.cpp b/proton-c/bindings/cpp/src/work_queue.cpp
index 77fa3fb..f8fc45c 100644
--- a/proton-c/bindings/cpp/src/work_queue.cpp
+++ b/proton-c/bindings/cpp/src/work_queue.cpp
@@ -19,6 +19,8 @@
#include "proton/work_queue.hpp"
+#include "proton/duration.hpp"
+
#include "contexts.hpp"
#include "proactor_container_impl.hpp"
#include "proactor_work_queue_impl.hpp"
@@ -41,6 +43,12 @@ bool work_queue::add(work f) {
return impl_->add(f);
}
+void work_queue::schedule(duration d, work f) {
+ // If we have no actual work queue, then can't defer
+ if (!impl_) return;
+ return impl_->schedule(d, f);
+}
+
work_queue& work_queue::get(pn_connection_t* c) {
return connection_context::get(c).work_queue_;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[05/20] qpid-proton git commit: PROTON-1400: [C++ binding] Proactor
container implementation - Remove all reactor use - Rearrange object context
code - Change container includes to proactor container includes - Add
sender/receiver options API to connecti
Posted by as...@apache.org.
PROTON-1400: [C++ binding] Proactor container implementation
- Remove all reactor use
- Rearrange object context code
- Change container includes to proactor container includes
- Add sender/receiver options API to connection so we never need container in handlers
- Rework connection_driver remove all use of container
- Change signature of listener_handler callbacks to supply the listener
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/9fad779c
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/9fad779c
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/9fad779c
Branch: refs/heads/master
Commit: 9fad779c98dcc2ccc75e5055d7333e9dd862c235
Parents: 6f88f52
Author: Andrew Stitcher <as...@apache.org>
Authored: Wed Feb 8 02:32:36 2017 -0500
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
examples/cpp/ssl.cpp | 9 +-
proton-c/bindings/cpp/CMakeLists.txt | 6 +-
.../bindings/cpp/include/proton/connection.hpp | 6 +
.../bindings/cpp/include/proton/container.hpp | 6 -
.../cpp/include/proton/internal/config.hpp | 8 +
.../cpp/include/proton/io/connection_driver.hpp | 25 +-
.../include/proton/io/container_impl_base.hpp | 144 -------
.../cpp/include/proton/listen_handler.hpp | 6 +-
.../bindings/cpp/include/proton/listener.hpp | 18 +-
proton-c/bindings/cpp/src/connection.cpp | 27 +-
.../bindings/cpp/src/connection_driver_test.cpp | 11 +-
.../bindings/cpp/src/connection_options.cpp | 30 +-
proton-c/bindings/cpp/src/container.cpp | 20 +-
proton-c/bindings/cpp/src/container_test.cpp | 11 +-
proton-c/bindings/cpp/src/contexts.cpp | 55 +--
proton-c/bindings/cpp/src/event_loop.cpp | 2 +-
proton-c/bindings/cpp/src/include/contexts.hpp | 56 +--
.../cpp/src/include/messaging_adapter.hpp | 2 -
.../cpp/src/include/proactor_container_impl.hpp | 133 ++++++
.../src/include/proactor_event_loop_impl.hpp | 54 +++
.../bindings/cpp/src/include/proton_bits.hpp | 18 +-
.../bindings/cpp/src/include/proton_event.hpp | 16 +-
.../cpp/src/include/test_dummy_container.hpp | 82 ----
.../bindings/cpp/src/io/connection_driver.cpp | 31 +-
proton-c/bindings/cpp/src/listener.cpp | 11 +-
proton-c/bindings/cpp/src/messaging_adapter.cpp | 21 +-
.../cpp/src/proactor_container_impl.cpp | 419 +++++++++++++++++++
proton-c/bindings/cpp/src/receiver.cpp | 1 -
proton-c/bindings/cpp/src/receiver_options.cpp | 2 +-
proton-c/bindings/cpp/src/reconnect_timer.cpp | 1 -
proton-c/bindings/cpp/src/sender_options.cpp | 2 +-
proton-c/bindings/cpp/src/session_options.cpp | 2 +-
32 files changed, 765 insertions(+), 470 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/examples/cpp/ssl.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/ssl.cpp b/examples/cpp/ssl.cpp
index 2e901c2..00bbccd 100644
--- a/examples/cpp/ssl.cpp
+++ b/examples/cpp/ssl.cpp
@@ -66,16 +66,16 @@ namespace {
struct server_handler : public proton::messaging_handler {
- std::string url;
+ proton::listener listener;
void on_connection_open(proton::connection &c) OVERRIDE {
std::cout << "Inbound server connection connected via SSL. Protocol: " <<
c.transport().ssl().protocol() << std::endl;
- c.container().stop_listening(url); // Just expecting the one connection.
+ listener.stop(); // Just expecting the one connection.
}
void on_transport_error(proton::transport &t) OVERRIDE {
- t.connection().container().stop_listening(url);
+ listener.stop();
}
void on_message(proton::delivery &, proton::message &m) OVERRIDE {
@@ -122,8 +122,7 @@ class hello_world_direct : public proton::messaging_handler {
} else throw std::logic_error("bad verify mode: " + verify);
c.client_connection_options(client_opts);
- s_handler.url = url;
- c.listen(url);
+ s_handler.listener = c.listen(url);
c.open_sender(url);
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/CMakeLists.txt b/proton-c/bindings/cpp/CMakeLists.txt
index d1c6fd1..295a99e 100644
--- a/proton-c/bindings/cpp/CMakeLists.txt
+++ b/proton-c/bindings/cpp/CMakeLists.txt
@@ -32,9 +32,8 @@ set(qpid-proton-cpp-source
src/map.cpp
src/connection.cpp
src/connection_options.cpp
- src/connector.cpp
src/container.cpp
- src/container_impl.cpp
+ src/proactor_container_impl.cpp
src/contexts.cpp
src/data.cpp
src/decimal.cpp
@@ -58,7 +57,6 @@ set(qpid-proton-cpp-source
src/proton_bits.cpp
src/proton_event.cpp
src/proton_handler.cpp
- src/reactor.cpp
src/receiver.cpp
src/receiver_options.cpp
src/reconnect_timer.cpp
@@ -91,7 +89,7 @@ set_source_files_properties (
add_library(qpid-proton-cpp SHARED ${qpid-proton-cpp-source})
-target_link_libraries (qpid-proton-cpp ${PLATFORM_LIBS} qpid-proton)
+target_link_libraries (qpid-proton-cpp ${PLATFORM_LIBS} qpid-proton-core qpid-proton-proactor)
set_target_properties (
qpid-proton-cpp
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/include/proton/connection.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/connection.hpp b/proton-c/bindings/cpp/include/proton/connection.hpp
index a4046be..331ba82 100644
--- a/proton-c/bindings/cpp/include/proton/connection.hpp
+++ b/proton-c/bindings/cpp/include/proton/connection.hpp
@@ -106,6 +106,12 @@ PN_CPP_CLASS_EXTERN connection : public internal::object<pn_connection_t>, publi
PN_CPP_EXTERN receiver open_receiver(const std::string &addr,
const receiver_options &);
+ /// @copydoc container::sender_options
+ PN_CPP_EXTERN class sender_options sender_options() const;
+
+ /// @copydoc container::receiver_options
+ PN_CPP_EXTERN class receiver_options receiver_options() const;
+
/// Return all sessions on this connection.
PN_CPP_EXTERN session_range sessions() const;
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/include/proton/container.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/container.hpp b/proton-c/bindings/cpp/include/proton/container.hpp
index 6f10c3c..be83e5e 100644
--- a/proton-c/bindings/cpp/include/proton/container.hpp
+++ b/proton-c/bindings/cpp/include/proton/container.hpp
@@ -73,12 +73,6 @@ class PN_CPP_CLASS_EXTERN container {
/// Connect to `url` and send an open request to the remote peer.
PN_CPP_EXTERN returned<connection> connect(const std::string& url);
- /// @cond INTERNAL
- /// Stop listening on url, must match the url string given to listen().
- /// You can also use the proton::listener object returned by listen()
- PN_CPP_EXTERN void stop_listening(const std::string& url);
- /// @endcond
-
/// Start listening on url.
///
/// Calls to the @ref listen_handler are serialized for this listener,
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/include/proton/internal/config.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/internal/config.hpp b/proton-c/bindings/cpp/include/proton/internal/config.hpp
index da7f480..79d201c 100644
--- a/proton-c/bindings/cpp/include/proton/internal/config.hpp
+++ b/proton-c/bindings/cpp/include/proton/internal/config.hpp
@@ -95,6 +95,14 @@
#define PN_CPP_HAS_CHRONO PN_CPP_HAS_CPP11
#endif
+#ifndef PN_CPP_HAS_STD_MUTEX
+#define PN_CPP_HAS_STD_MUTEX PN_CPP_HAS_CPP11
+#endif
+
+#ifndef PN_CPP_HAS_STD_ATOMIC
+#define PN_CPP_HAS_STD_ATOMIC PN_CPP_HAS_CPP11
+#endif
+
#endif // PROTON_INTERNAL_CONFIG_HPP
/// @endcond
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/include/proton/io/connection_driver.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/io/connection_driver.hpp b/proton-c/bindings/cpp/include/proton/io/connection_driver.hpp
index 56deb00..8d0be85 100644
--- a/proton-c/bindings/cpp/include/proton/io/connection_driver.hpp
+++ b/proton-c/bindings/cpp/include/proton/io/connection_driver.hpp
@@ -94,28 +94,11 @@ struct const_buffer {
class
PN_CPP_CLASS_EXTERN connection_driver {
public:
- /// An engine that is not associated with a proton::container or
- /// proton::event_loop.
- ///
- /// Accessing the container or event_loop for this connection in
- /// a proton::messaging_handler will throw a proton::error exception.
- ///
+ /// An engine without a container id.
PN_CPP_EXTERN connection_driver();
- /// Create a connection driver associated with a proton::container and
- /// optional event_loop. If the event_loop is not provided attempts to use
- /// it will throw proton::error.
- ///
- /// Takes ownership of the event_loop. Note the proton::connection created
- /// by this connection_driver can outlive the connection_driver itself if
- /// the user pins it in memory using the proton::thread_safe<> template.
- /// The event_loop is deleted when, and only when, the proton::connection is.
- ///
- PN_CPP_EXTERN connection_driver(proton::container&);
-#if PN_CPP_HAS_RVALUE_REFERENCES
- /// @copydoc connection_driver()
- PN_CPP_EXTERN connection_driver(proton::container&, event_loop&& loop);
-#endif
+ /// Create a connection driver associated with a container id.
+ PN_CPP_EXTERN connection_driver(const std::string&);
PN_CPP_EXTERN ~connection_driver();
@@ -207,8 +190,8 @@ PN_CPP_CLASS_EXTERN connection_driver {
connection_driver(const connection_driver&);
connection_driver& operator=(const connection_driver&);
+ std::string container_id_;
messaging_handler* handler_;
- proton::container* container_;
pn_connection_driver_t driver_;
};
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/include/proton/io/container_impl_base.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/io/container_impl_base.hpp b/proton-c/bindings/cpp/include/proton/io/container_impl_base.hpp
deleted file mode 100644
index a04b4ff..0000000
--- a/proton-c/bindings/cpp/include/proton/io/container_impl_base.hpp
+++ /dev/null
@@ -1,144 +0,0 @@
-#ifndef PROTON_IO_CONTAINER_IMPL_BASE_HPP
-#define PROTON_IO_CONTAINER_IMPL_BASE_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 "../container.hpp"
-
-#include <future>
-#include <mutex>
-#include <sstream>
-
-namespace proton {
-namespace io {
-
-/// **Experimental** - A base container implementation.
-///
-/// This is a thread-safe partial implementation of the
-/// proton::container interface to reduce boilerplate code in
-/// container implementations. Requires C++11.
-///
-/// You can ignore this class if you want to implement the functions
-/// in a different way.
-class container_impl_base : public standard_container {
- public:
- // Pull in base class functions here so that name search finds all the overloads
- using standard_container::open_receiver;
- using standard_container::open_sender;
-
- /// @see proton::container::client_connection_options
- void client_connection_options(const connection_options & opts) {
- store(client_copts_, opts);
- }
-
- /// @see proton::container::client_connection_options
- connection_options client_connection_options() const {
- return load(client_copts_);
- }
-
- /// @see proton::container::server_connection_options
- void server_connection_options(const connection_options & opts) {
- store(server_copts_, opts);
- }
-
- /// @see proton::container::server_connection_options
- connection_options server_connection_options() const {
- return load(server_copts_);
- }
-
- /// @see proton::container::sender_options
- void sender_options(const class sender_options & opts) {
- store(sender_opts_, opts);
- }
-
- /// @see proton::container::sender_options
- class sender_options sender_options() const {
- return load(sender_opts_);
- }
-
- /// @see proton::container::receiver_options
- void receiver_options(const class receiver_options & opts) {
- store(receiver_opts_, opts);
- }
-
- /// @see proton::container::receiver_options
- class receiver_options receiver_options() const {
- return load(receiver_opts_);
- }
-
- /// @see proton::container::open_sender
- returned<sender> open_sender(
- const std::string &url, const class sender_options &opts, const connection_options &copts)
- {
- return open_link<sender, class sender_options>(url, opts, copts, &connection::open_sender);
- }
-
- /// @see proton::container::open_receiver
- returned<receiver> open_receiver(
- const std::string &url, const class receiver_options &opts, const connection_options &copts)
- {
- return open_link<receiver>(url, opts, copts, &connection::open_receiver);
- }
-
- private:
- template<class T, class Opts>
- returned<T> open_link(
- const std::string &url_str, const Opts& opts, const connection_options& copts,
- T (connection::*open_fn)(const std::string&, const Opts&))
- {
- std::string addr = url(url_str).path();
- std::shared_ptr<thread_safe<connection> > ts_connection = connect(url_str, copts);
- std::promise<returned<T> > result_promise;
- auto do_open = [ts_connection, addr, opts, open_fn, &result_promise]() {
- try {
- connection c = ts_connection->unsafe();
- returned<T> s = make_thread_safe((c.*open_fn)(addr, opts));
- result_promise.set_value(s);
- } catch (...) {
- result_promise.set_exception(std::current_exception());
- }
- };
- ts_connection->event_loop()->inject(do_open);
- std::future<returned<T> > result_future = result_promise.get_future();
- if (!result_future.valid())
- throw error(url_str+": connection closed");
- return result_future.get();
- }
-
- mutable std::mutex lock_;
- template <class T> T load(const T& v) const {
- std::lock_guard<std::mutex> g(lock_);
- return v;
- }
- template <class T> void store(T& v, const T& x) const {
- std::lock_guard<std::mutex> g(lock_);
- v = x;
- }
- connection_options client_copts_, server_copts_;
- class receiver_options receiver_opts_;
- class sender_options sender_opts_;
-};
-
-} // io
-} // proton
-
-#endif // PROTON_IO_CONTAINER_IMPL_BASE_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/include/proton/listen_handler.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/listen_handler.hpp b/proton-c/bindings/cpp/include/proton/listen_handler.hpp
index 99f7558..08d5e76 100644
--- a/proton-c/bindings/cpp/include/proton/listen_handler.hpp
+++ b/proton-c/bindings/cpp/include/proton/listen_handler.hpp
@@ -41,14 +41,14 @@ class listen_handler {
/// the connection. messaging_handler::on_connection_open() will be called with
/// the proton::connection, it can call connection::open() to accept or
/// connection::close() to reject the connection.
- virtual connection_options on_accept()= 0;
+ virtual connection_options on_accept(listener&)= 0;
/// Called if there is a listening error, with an error message.
/// close() will also be called.
- virtual void on_error(const std::string&) {}
+ virtual void on_error(listener&, const std::string&) {}
/// Called when this listen_handler is no longer needed, and can be deleted.
- virtual void on_close() {}
+ virtual void on_close(listener&) {}
};
} // proton
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/include/proton/listener.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/listener.hpp b/proton-c/bindings/cpp/include/proton/listener.hpp
index 4b4ca24..c7f95a7 100644
--- a/proton-c/bindings/cpp/include/proton/listener.hpp
+++ b/proton-c/bindings/cpp/include/proton/listener.hpp
@@ -20,30 +20,30 @@
* under the License.
*/
-#include "./fwd.hpp"
#include "./internal/export.hpp"
-#include <string>
+struct pn_listener_t;
namespace proton {
/// A listener for incoming connections.
class PN_CPP_CLASS_EXTERN listener {
+ /// @cond INTERNAL
+ listener(pn_listener_t*);
+ /// @endcond
+
public:
/// Create an empty listener.
PN_CPP_EXTERN listener();
- /// @cond INTERNAL
- PN_CPP_EXTERN listener(container&, const std::string&);
- /// @endcond
-
/// Stop listening on the address provided to the call to
/// container::listen that returned this listener.
PN_CPP_EXTERN void stop();
- private:
- std::string url_;
- container* container_;
+ private:
+ pn_listener_t* listener_;
+
+ friend class container;
};
} // proton
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/connection.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connection.cpp b/proton-c/bindings/cpp/src/connection.cpp
index f706df4..113a06f 100644
--- a/proton-c/bindings/cpp/src/connection.cpp
+++ b/proton-c/bindings/cpp/src/connection.cpp
@@ -38,7 +38,6 @@
#include <proton/connection.h>
#include <proton/session.h>
#include <proton/transport.h>
-#include <proton/reactor.h>
#include <proton/object.h>
namespace proton {
@@ -72,13 +71,7 @@ std::string connection::user() const {
container& connection::container() const {
class container* c = connection_context::get(pn_object()).container;
- if (!c) {
- pn_reactor_t *r = pn_object_reactor(pn_object());
- if (r)
- c = &container_context::get(r);
- }
- if (!c)
- throw proton::error("connection does not have a container");
+ if (!c) throw proton::error("No container");
return *c;
}
@@ -133,7 +126,7 @@ sender connection::open_sender(const std::string &addr) {
return open_sender(addr, sender_options());
}
-sender connection::open_sender(const std::string &addr, const sender_options &opts) {
+sender connection::open_sender(const std::string &addr, const class sender_options &opts) {
return default_session().open_sender(addr, opts);
}
@@ -141,11 +134,25 @@ receiver connection::open_receiver(const std::string &addr) {
return open_receiver(addr, receiver_options());
}
-receiver connection::open_receiver(const std::string &addr, const receiver_options &opts)
+receiver connection::open_receiver(const std::string &addr, const class receiver_options &opts)
{
return default_session().open_receiver(addr, opts);
}
+class sender_options connection::sender_options() const {
+ connection_context& ctx = connection_context::get(pn_object());
+ return ctx.container ?
+ ctx.container->sender_options() :
+ proton::sender_options();
+}
+
+class receiver_options connection::receiver_options() const {
+ connection_context& ctx = connection_context::get(pn_object());
+ return ctx.container ?
+ ctx.container->receiver_options() :
+ proton::receiver_options();
+}
+
error_condition connection::error() const {
return make_wrapper(pn_connection_remote_condition(pn_object()));
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/connection_driver_test.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connection_driver_test.cpp b/proton-c/bindings/cpp/src/connection_driver_test.cpp
index a5771f9..ae18ebe 100644
--- a/proton-c/bindings/cpp/src/connection_driver_test.cpp
+++ b/proton-c/bindings/cpp/src/connection_driver_test.cpp
@@ -31,6 +31,7 @@
#include "proton/sender.hpp"
#include "proton/sender_options.hpp"
#include "proton/source_options.hpp"
+#include "proton/thread_safe.hpp"
#include "proton/types_fwd.hpp"
#include "proton/uuid.hpp"
@@ -57,8 +58,8 @@ struct in_memory_driver : public connection_driver {
byte_stream& writes;
int spinning;
- in_memory_driver(byte_stream& rd, byte_stream& wr) :
- reads(rd), writes(wr), spinning(0) {}
+ in_memory_driver(byte_stream& rd, byte_stream& wr, const std::string& name) :
+ connection_driver(name), reads(rd), writes(wr), spinning(0) {}
void do_read() {
mutable_buffer rbuf = read_buffer();
@@ -102,8 +103,10 @@ struct driver_pair {
byte_stream ab, ba;
in_memory_driver a, b;
- driver_pair(const connection_options& oa, const connection_options& ob)
- : a(ba, ab), b(ab, ba)
+ driver_pair(const connection_options& oa, const connection_options& ob,
+ const std::string& name=""
+ ) :
+ a(ba, ab, name+"a"), b(ab, ba, name+"b")
{
a.connect(oa);
b.accept(ob);
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/connection_options.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connection_options.cpp b/proton-c/bindings/cpp/src/connection_options.cpp
index 506e84e..4644094 100644
--- a/proton-c/bindings/cpp/src/connection_options.cpp
+++ b/proton-c/bindings/cpp/src/connection_options.cpp
@@ -18,6 +18,7 @@
* under the License.
*
*/
+#include "proton/fwd.hpp"
#include "proton/connection_options.hpp"
#include "proton/messaging_handler.hpp"
#include "proton/reconnect_timer.hpp"
@@ -27,12 +28,12 @@
#include "acceptor.hpp"
#include "contexts.hpp"
-#include "connector.hpp"
#include "messaging_adapter.hpp"
#include "msg.hpp"
#include "proton_bits.hpp"
#include <proton/connection.h>
+#include <proton/proactor.h>
#include <proton/transport.h>
namespace proton {
@@ -74,15 +75,14 @@ class connection_options::impl {
*/
void apply_unbound(connection& c) {
pn_connection_t *pnc = unwrap(c);
- container::impl::connector *outbound = dynamic_cast<container::impl::connector*>(
- connection_context::get(unwrap(c)).handler.get());
// Only apply connection options if uninit.
bool uninit = c.uninitialized();
if (!uninit) return;
+ bool outbound = !connection_context::get(pnc).listener_context_;
if (reconnect.set && outbound)
- outbound->reconnect_timer(reconnect.value);
+ connection_context::get(pnc).reconnect.reset(new reconnect_timer(reconnect.value));
if (container_id.set)
pn_connection_set_container(pnc, container_id.value.c_str());
if (virtual_host.set)
@@ -97,31 +97,23 @@ class connection_options::impl {
// Transport options. pnt is NULL between reconnect attempts
// and if there is a pipelined open frame.
pn_connection_t *pnc = unwrap(c);
- container::impl::connector *outbound = dynamic_cast<container::impl::connector*>(
- connection_context::get(unwrap(c)).handler.get());
-
pn_transport_t *pnt = pn_connection_transport(pnc);
if (!pnt) return;
// SSL
- if (outbound && outbound->address().scheme() == url::AMQPS) {
+ connection_context& cc = connection_context::get(pnc);
+ bool outbound = !cc.listener_context_;
+ if (outbound && ssl_client_options.set) {
// A side effect of pn_ssl() is to set the ssl peer
// hostname to the connection hostname, which has
// already been adjusted for the virtual_host option.
pn_ssl_t *ssl = pn_ssl(pnt);
if (pn_ssl_init(ssl, ssl_client_options.value.pn_domain(), NULL))
throw error(MSG("client SSL/TLS initialization error"));
- } else if (!outbound) {
- // TODO aconway 2016-05-13: reactor only
- pn_acceptor_t *pnp = pn_connection_acceptor(pnc);
- if (pnp) {
- listener_context &lc(listener_context::get(pnp));
- if (lc.ssl) {
- pn_ssl_t *ssl = pn_ssl(pnt);
- if (pn_ssl_init(ssl, ssl_server_options.value.pn_domain(), NULL))
- throw error(MSG("server SSL/TLS initialization error"));
- }
- }
+ } else if (!outbound && ssl_server_options.set) {
+ pn_ssl_t *ssl = pn_ssl(pnt);
+ if (pn_ssl_init(ssl, ssl_server_options.value.pn_domain(), NULL))
+ throw error(MSG("server SSL/TLS initialization error"));
}
// SASL
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/container.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/container.cpp b/proton-c/bindings/cpp/src/container.cpp
index 3daa925..b98da78 100644
--- a/proton-c/bindings/cpp/src/container.cpp
+++ b/proton-c/bindings/cpp/src/container.cpp
@@ -27,7 +27,7 @@
#include "proton/listener.hpp"
#include "proton/thread_safe.hpp"
-#include "container_impl.hpp"
+#include "proactor_container_impl.hpp"
namespace proton {
@@ -65,24 +65,12 @@ returned<receiver> container::open_receiver(const std::string &url, const proton
return open_receiver(url, receiver_options(), co);
}
-namespace{
- struct listen_opts : public listen_handler {
- connection_options opts;
- listen_opts(const connection_options& o) : opts(o) {}
- connection_options on_accept() { return opts; }
- void on_close() { delete this; }
- };
-}
-
listener container::listen(const std::string& url, const connection_options& opts) {
- // Note: listen_opts::on_close() calls delete(this) so this is not a leak.
- // The container will always call on_closed() even if there are errors or exceptions.
- listen_opts* lh = new listen_opts(opts);
- return listen(url, *lh);
+ return impl_->listen(url, opts);
}
listener container::listen(const std::string &url) {
- return listen(url, connection_options());
+ return impl_->listen(url);
}
void container::stop() { stop(error_condition()); }
@@ -93,8 +81,6 @@ returned<connection> container::connect(const std::string& url, const connection
listener container::listen(const std::string& url, listen_handler& l) { return impl_->listen(url, l); }
-void container::stop_listening(const std::string& url) { impl_->stop_listening(url); }
-
void container::run() { impl_->run(); }
void container::auto_stop(bool set) { impl_->auto_stop(set); }
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/container_test.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/container_test.cpp b/proton-c/bindings/cpp/src/container_test.cpp
index e02aff5..d210268 100644
--- a/proton-c/bindings/cpp/src/container_test.cpp
+++ b/proton-c/bindings/cpp/src/container_test.cpp
@@ -124,12 +124,12 @@ struct test_listener : public proton::listen_handler {
bool on_accept_, on_close_;
std::string on_error_;
test_listener() : on_accept_(false), on_close_(false) {}
- proton::connection_options on_accept() PN_CPP_OVERRIDE {
+ proton::connection_options on_accept(proton::listener&) PN_CPP_OVERRIDE {
on_accept_ = true;
return proton::connection_options();
}
- void on_close() PN_CPP_OVERRIDE { on_close_ = true; }
- void on_error(const std::string& e) PN_CPP_OVERRIDE { on_error_ = e; }
+ void on_close(proton::listener&) PN_CPP_OVERRIDE { on_close_ = true; }
+ void on_error(proton::listener&, const std::string& e) PN_CPP_OVERRIDE { on_error_ = e; }
};
int test_container_bad_address() {
@@ -179,6 +179,11 @@ class stop_tester : public proton::messaging_handler {
state = 5;
}
+ void on_transport_error(proton::transport & t) PN_CPP_OVERRIDE {
+ // Do nothing - ignore transport errors - we're going to get one when
+ // the container stops.
+ }
+
public:
stop_tester(): state(0) {}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/contexts.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/contexts.cpp b/proton-c/bindings/cpp/src/contexts.cpp
index b1a234f..81ef5eb 100644
--- a/proton-c/bindings/cpp/src/contexts.cpp
+++ b/proton-c/bindings/cpp/src/contexts.cpp
@@ -21,7 +21,6 @@
#include "contexts.hpp"
#include "msg.hpp"
-#include "reactor.hpp"
#include "proton_bits.hpp"
#include "proton/error.hpp"
@@ -29,8 +28,9 @@
#include <proton/connection.h>
#include <proton/object.h>
#include <proton/link.h>
+#include <proton/listener.h>
#include <proton/message.h>
-#include <proton/reactor.h>
+#include "proton/reconnect_timer.hpp"
#include <proton/session.h>
#include <typeinfo>
@@ -48,16 +48,10 @@ pn_class_t cpp_context_class = PN_CLASS(cpp_context);
// Handles
PN_HANDLE(CONNECTION_CONTEXT)
-PN_HANDLE(CONTAINER_CONTEXT)
PN_HANDLE(LISTENER_CONTEXT)
+PN_HANDLE(SESSION_CONTEXT)
PN_HANDLE(LINK_CONTEXT)
-void set_context(pn_record_t* record, pn_handle_t handle, const pn_class_t *clazz, void* value)
-{
- pn_record_def(record, handle, clazz);
- pn_record_set(record, handle, value);
-}
-
template <class T>
T* get_context(pn_record_t* record, pn_handle_t handle) {
return reinterpret_cast<T*>(pn_record_get(record, handle));
@@ -71,45 +65,24 @@ void *context::alloc(size_t n) { return pn_object_new(&cpp_context_class, n); }
pn_class_t* context::pn_class() { return &cpp_context_class; }
+connection_context::connection_context() :
+ container(0), default_session(0), link_gen(0), handler(0), listener_context_(0)
+{}
-context::id connection_context::id(pn_connection_t* c) {
- return context::id(pn_connection_attachments(c), CONNECTION_CONTEXT);
-}
-
-void container_context::set(const reactor& r, container& c) {
- set_context(pn_reactor_attachments(unwrap(r)), CONTAINER_CONTEXT, PN_VOID, &c);
+connection_context& connection_context::get(pn_connection_t *c) {
+ return ref<connection_context>(id(pn_connection_attachments(c), CONNECTION_CONTEXT));
}
-container &container_context::get(pn_reactor_t *pn_reactor) {
- container *ctx = get_context<container>(pn_reactor_attachments(pn_reactor), CONTAINER_CONTEXT);
- if (!ctx) throw error(MSG("Reactor has no C++ container context"));
- return *ctx;
+listener_context& listener_context::get(pn_listener_t* l) {
+ return ref<listener_context>(id(pn_listener_attachments(l), LISTENER_CONTEXT));
}
-listener_context& listener_context::get(pn_acceptor_t* a) {
- // TODO aconway 2016-05-13: reactor only
- // A Proton C pn_acceptor_t is really just a selectable
- pn_selectable_t *sel = reinterpret_cast<pn_selectable_t*>(a);
-
- listener_context* ctx =
- get_context<listener_context>(pn_selectable_attachments(sel), LISTENER_CONTEXT);
- if (!ctx) {
- ctx = context::create<listener_context>();
- set_context(pn_selectable_attachments(sel), LISTENER_CONTEXT, context::pn_class(), ctx);
- pn_decref(ctx);
- }
- return *ctx;
+link_context& link_context::get(pn_link_t* l) {
+ return ref<link_context>(id(pn_link_attachments(l), LINK_CONTEXT));
}
-link_context& link_context::get(pn_link_t* l) {
- link_context* ctx =
- get_context<link_context>(pn_link_attachments(l), LINK_CONTEXT);
- if (!ctx) {
- ctx = context::create<link_context>();
- set_context(pn_link_attachments(l), LINK_CONTEXT, context::pn_class(), ctx);
- pn_decref(ctx);
- }
- return *ctx;
+session_context& session_context::get(pn_session_t* s) {
+ return ref<session_context>(id(pn_session_attachments(s), SESSION_CONTEXT));
}
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/event_loop.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/event_loop.cpp b/proton-c/bindings/cpp/src/event_loop.cpp
index ea4ee71..ab39aa7 100644
--- a/proton-c/bindings/cpp/src/event_loop.cpp
+++ b/proton-c/bindings/cpp/src/event_loop.cpp
@@ -20,7 +20,7 @@
#include "proton/event_loop.hpp"
#include "contexts.hpp"
-#include "event_loop_impl.hpp"
+#include "proactor_event_loop_impl.hpp"
#include <proton/session.h>
#include <proton/link.h>
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/include/contexts.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/contexts.hpp b/proton-c/bindings/cpp/src/include/contexts.hpp
index 742b346..c096a6e 100644
--- a/proton-c/bindings/cpp/src/include/contexts.hpp
+++ b/proton-c/bindings/cpp/src/include/contexts.hpp
@@ -34,16 +34,16 @@
#include "proton_handler.hpp"
-struct pn_session_t;
-struct pn_event_t;
-struct pn_reactor_t;
struct pn_record_t;
-struct pn_acceptor_t;
+struct pn_link_t;
+struct pn_session_t;
+struct pn_connection_t;
+struct pn_listener_t;
namespace proton {
class proton_handler;
-class reactor;
+class reconnect_timer;
// Base class for C++ classes that are used as proton contexts.
// Contexts are pn_objects managed by pn reference counts, the C++ value is allocated in-place.
@@ -82,51 +82,53 @@ class context {
static void *alloc(size_t n);
};
+class listener_context;
+
// Connection context used by all connections.
class connection_context : public context {
public:
- connection_context() : container(0), default_session(0), link_gen(0) {}
+ connection_context();
+ static connection_context& get(pn_connection_t *c);
class container* container;
pn_session_t *default_session; // Owned by connection.
message event_message; // re-used by messaging_adapter for performance.
io::link_namer* link_gen; // Link name generator.
- internal::pn_unique_ptr<proton_handler> handler;
+ messaging_handler* handler;
+ internal::pn_unique_ptr<reconnect_timer> reconnect;
+ listener_context* listener_context_;
event_loop event_loop_;
-
- static connection_context& get(pn_connection_t *c) { return ref<connection_context>(id(c)); }
-
- protected:
- static context::id id(pn_connection_t*);
-};
-
-void container_context(const reactor&, container&);
-
-class container_context {
- public:
- static void set(const reactor& r, container& c);
- static container& get(pn_reactor_t*);
};
class listener_context : public context {
public:
- static listener_context& get(pn_acceptor_t* c);
- listener_context() : listen_handler_(0), ssl(false) {}
- connection_options get_options() { return listen_handler_->on_accept(); }
- class listen_handler* listen_handler_;
- bool ssl;
+ listener_context() : listen_handler_(0) {}
+ static listener_context& get(pn_listener_t* c);
+
+ listen_handler* listen_handler_;
+ internal::pn_unique_ptr<const connection_options> connection_options_;
};
class link_context : public context {
public:
+ link_context() : handler(0), credit_window(10), pending_credit(0), auto_accept(true), auto_settle(true), draining(false) {}
static link_context& get(pn_link_t* l);
- link_context() : credit_window(10), auto_accept(true), auto_settle(true), draining(false), pending_credit(0) {}
+
+ messaging_handler* handler;
int credit_window;
+ uint32_t pending_credit;
bool auto_accept;
bool auto_settle;
bool draining;
- uint32_t pending_credit;
+};
+
+class session_context : public context {
+ public:
+ session_context() : handler(0) {}
+ static session_context& get(pn_session_t* s);
+
+ messaging_handler* handler;
};
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/include/messaging_adapter.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/messaging_adapter.hpp b/proton-c/bindings/cpp/src/include/messaging_adapter.hpp
index 5371eec..d7eb6a0 100644
--- a/proton-c/bindings/cpp/src/include/messaging_adapter.hpp
+++ b/proton-c/bindings/cpp/src/include/messaging_adapter.hpp
@@ -39,8 +39,6 @@ class messaging_adapter : public proton_handler
public:
messaging_adapter(messaging_handler &delegate) : delegate_(delegate) {}
- void on_reactor_init(proton_event &e);
- void on_reactor_final(proton_event & e);
void on_link_flow(proton_event &e);
void on_delivery(proton_event &e);
void on_connection_remote_open(proton_event &e);
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp b/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
new file mode 100644
index 0000000..8c12c02
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
@@ -0,0 +1,133 @@
+#ifndef PROTON_CPP_PROACTOR_CONTAINERIMPL_H
+#define PROTON_CPP_PROACTOR_CONTAINERIMPL_H
+
+/*
+ *
+ * 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 "proton/fwd.hpp"
+#include "proton/container.hpp"
+#include "proton/connection.hpp"
+#include "proton/connection_options.hpp"
+#include "proton/duration.hpp"
+#include "proton/error_condition.hpp"
+#include "proton/messaging_handler.hpp"
+#include "proton/receiver.hpp"
+#include "proton/receiver_options.hpp"
+#include "proton/sender.hpp"
+#include "proton/sender_options.hpp"
+
+#include "proton_bits.hpp"
+#include "proton_handler.hpp"
+
+#include <list>
+#include <map>
+#include <string>
+#include <vector>
+
+struct pn_proactor_t;
+struct pn_listener_t;
+struct pn_event_t;
+
+namespace proton {
+
+class container::impl {
+ public:
+ impl(container& c, const std::string& id, messaging_handler* = 0);
+ ~impl();
+ std::string id() const { return id_; }
+ returned<connection> connect(const std::string&, const connection_options&);
+ returned<sender> open_sender(
+ const std::string&, const proton::sender_options &, const connection_options &);
+ returned<receiver> open_receiver(
+ const std::string&, const proton::receiver_options &, const connection_options &);
+ listener listen(const std::string&);
+ listener listen(const std::string&, const connection_options& lh);
+ listener listen(const std::string&, listen_handler& lh);
+ void client_connection_options(const connection_options &);
+ connection_options client_connection_options() const { return client_connection_options_; }
+ void server_connection_options(const connection_options &);
+ connection_options server_connection_options() const { return server_connection_options_; }
+ void sender_options(const proton::sender_options&);
+ class sender_options sender_options() const { return sender_options_; }
+ void receiver_options(const proton::receiver_options&);
+ class receiver_options receiver_options() const { return receiver_options_; }
+ void run();
+ void stop(const error_condition& err);
+ void auto_stop(bool set);
+ void schedule(duration, void_function0&);
+#if PN_CPP_HAS_STD_FUNCTION
+ void schedule(duration, std::function<void()>);
+#endif
+ template <class T> static void set_handler(T s, messaging_handler* h);
+ template <class T> static messaging_handler* get_handler(T s);
+
+ private:
+ pn_listener_t* listen_common_lh(const std::string&);
+ connection connect_common(const std::string&, const connection_options&);
+
+ // Event loop to run in each container thread
+ static void thread(impl&);
+ bool handle(pn_event_t*);
+ void run_timer_jobs();
+
+ container& container_;
+
+ struct scheduled {
+ timestamp time; // duration from epoch for task
+#if PN_CPP_HAS_STD_FUNCTION
+ std::function<void()> task;
+#else
+ void_function0* task_;
+ void task();
+#endif
+
+ // We want to get to get the *earliest* first so test is "reversed"
+ bool operator < (const scheduled& r) const { return r.time < time; }
+ };
+ std::vector<scheduled> deferred_; // This vector is kept as a heap
+
+ pn_proactor_t* proactor_;
+ messaging_handler* handler_;
+ std::string id_;
+ connection_options client_connection_options_;
+ connection_options server_connection_options_;
+ proton::sender_options sender_options_;
+ proton::receiver_options receiver_options_;
+
+ proton::error_condition stop_err_;
+ bool auto_stop_;
+ bool stopping_;
+};
+
+template <class T>
+void container::impl::set_handler(T s, messaging_handler* mh) {
+ internal::set_messaging_handler(s, mh);
+}
+
+template <class T>
+messaging_handler* container::impl::get_handler(T s) {
+ return internal::get_messaging_handler(s);
+}
+
+
+}
+
+#endif /*!PROTON_CPP_PROACTOR_CONTAINERIMPL_H*/
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/include/proactor_event_loop_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proactor_event_loop_impl.hpp b/proton-c/bindings/cpp/src/include/proactor_event_loop_impl.hpp
new file mode 100644
index 0000000..8fa7acf
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/proactor_event_loop_impl.hpp
@@ -0,0 +1,54 @@
+#ifndef PROTON_CPP_EVENT_LOOP_IMPL_HPP
+#define PROTON_CPP_EVENT_LOOP_IMPL_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 "proton/fwd.hpp"
+
+struct pn_connection_t;
+
+namespace proton {
+
+class event_loop::impl {
+ public:
+ impl(pn_connection_t*);
+
+ bool inject(void_function0& f);
+#if PN_CPP_HAS_STD_FUNCTION
+ bool inject(std::function<void()> f);
+ typedef std::vector<std::function<void()> > jobs;
+#else
+ typedef std::vector<void_function0*> jobs;
+#endif
+
+
+ void run_all_jobs();
+ void finished();
+
+ jobs jobs_;
+ pn_connection_t* connection_;
+ bool finished_;
+};
+
+}
+
+#endif // PROTON_CPP_EVENT_LOOP_IMPL_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/include/proton_bits.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proton_bits.hpp b/proton-c/bindings/cpp/src/include/proton_bits.hpp
index 53f2230..e72f343 100644
--- a/proton-c/bindings/cpp/src/include/proton_bits.hpp
+++ b/proton-c/bindings/cpp/src/include/proton_bits.hpp
@@ -24,6 +24,8 @@
#include <string>
#include <iosfwd>
+#include "contexts.hpp"
+
/**@file
*
* Assorted internal proton utilities.
@@ -65,6 +67,7 @@ class terminus;
class source;
class target;
class reactor;
+class messaging_handler;
std::string error_str(long code);
@@ -127,12 +130,19 @@ public:
static typename wrapped<T>::type* unwrap(const T& t) { return t.pn_object(); }
};
-// Get attachments for various proton-c types
+template <class T> struct context {};
+template <> struct context<link> {typedef link_context type; };
+template <> struct context<receiver> {typedef link_context type; };
+template <> struct context<sender> {typedef link_context type; };
+template <> struct context<session> {typedef session_context type; };
+template <> struct context<connection> {typedef connection_context type; };
+
+template <class T>
+inline void set_messaging_handler(T t, messaging_handler* mh) { context<T>::type::get(factory<T>::unwrap(t)).handler = mh; }
+
template <class T>
-inline pn_record_t* get_attachments(T*);
+inline messaging_handler* get_messaging_handler(T* t) { return context<typename internal::wrapper<T>::type>::type::get(t).handler; }
-template <> inline pn_record_t* get_attachments(pn_session_t* s) { return pn_session_attachments(s); }
-template <> inline pn_record_t* get_attachments(pn_link_t* l) { return pn_link_attachments(l); }
}
template <class T>
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/include/proton_event.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proton_event.hpp b/proton-c/bindings/cpp/src/include/proton_event.hpp
index 374da85..be324e7 100644
--- a/proton-c/bindings/cpp/src/include/proton_event.hpp
+++ b/proton-c/bindings/cpp/src/include/proton_event.hpp
@@ -266,23 +266,12 @@ class proton_event
};
///@}
- proton_event(pn_event_t *ce, class container* cont) :
- pn_event_(ce),
- container_(cont)
+ proton_event(pn_event_t *ce) :
+ pn_event_(ce)
{}
pn_event_t* pn_event() const { return pn_event_; }
- /** Return a reference to the container, throws proton::error if there is none. */
- class container& container() const {
- if (!container_)
- throw proton::error("event does not have a container");
- return *container_;
- }
-
- /** Return a pointer to the container if there is one, NULL otherwise. */
- class container* container_ptr() const { return container_; }
-
/// Get type of event
event_type type() const { return event_type(pn_event_type(pn_event_)); }
@@ -290,7 +279,6 @@ class proton_event
private:
pn_event_t *pn_event_;
- class container* container_;
};
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/include/test_dummy_container.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/test_dummy_container.hpp b/proton-c/bindings/cpp/src/include/test_dummy_container.hpp
deleted file mode 100644
index daed435..0000000
--- a/proton-c/bindings/cpp/src/include/test_dummy_container.hpp
+++ /dev/null
@@ -1,82 +0,0 @@
-#ifndef TEST_DUMMY_CONTAINER_HPP
-#define TEST_DUMMY_CONTAINER_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 "proton/container.hpp"
-#include "proton/event_loop.hpp"
-#include "proton/thread_safe.hpp"
-
-namespace test {
-
-using namespace proton;
-
-class dummy_container : public standard_container {
- public:
- dummy_container(const std::string cid="") :
- id_(cid), fail("not implemented for dummy_container") {}
-
- // Pull in base class functions here so that name search finds all the overloads
- using standard_container::stop;
- using standard_container::connect;
- using standard_container::listen;
- using standard_container::open_receiver;
- using standard_container::open_sender;
-
- returned<connection> connect(const std::string&, const connection_options&) { throw fail; }
- listener listen(const std::string& , listen_handler& ) { throw fail; }
- void stop_listening(const std::string&) { throw fail; }
- void run() { throw fail; }
- void auto_stop(bool) { throw fail; }
- void stop(const proton::error_condition& ) { throw fail; }
- returned<sender> open_sender(const std::string &, const proton::sender_options &, const connection_options&) { throw fail; }
- returned<receiver> open_receiver( const std::string &, const proton::receiver_options &, const connection_options &) { throw fail; }
- std::string id() const { return id_; }
- void client_connection_options(const connection_options &o) { ccopts_ = o; }
- connection_options client_connection_options() const { return ccopts_; }
- void server_connection_options(const connection_options &o) { scopts_ = o; }
- connection_options server_connection_options() const { return scopts_; }
- void sender_options(const class sender_options &o) { sopts_ = o; }
- class sender_options sender_options() const { return sopts_; }
- void receiver_options(const class receiver_options &o) { ropts_ = o; }
- class receiver_options receiver_options() const { return ropts_; }
-#if PN_CPP_HAS_STD_FUNCTION
- void schedule(duration, std::function<void()>) { throw fail; }
-#endif
- void schedule(duration, void_function0&) { throw fail; }
-
- private:
- std::string id_;
- connection_options ccopts_, scopts_;
- class sender_options sopts_;
- class receiver_options ropts_;
- std::runtime_error fail;
-};
-
-class dummy_event_loop : public event_loop {
-#if PN_CPP_HAS_CPP11
- bool inject(std::function<void()> f) PN_CPP_OVERRIDE { f(); return true; }
-#endif
- bool inject(proton::void_function0& h) PN_CPP_OVERRIDE { h(); return true; }
-};
-
-}
-
-#endif // TEST_DUMMY_CONTAINER_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/io/connection_driver.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/io/connection_driver.cpp b/proton-c/bindings/cpp/src/io/connection_driver.cpp
index da8c2a4..d7c5e5c 100644
--- a/proton-c/bindings/cpp/src/io/connection_driver.cpp
+++ b/proton-c/bindings/cpp/src/io/connection_driver.cpp
@@ -47,23 +47,12 @@ void connection_driver::init() {
}
}
-connection_driver::connection_driver() : handler_(0), container_(0) { init(); }
+connection_driver::connection_driver() : handler_(0) { init(); }
-connection_driver::connection_driver(class container& cont) : handler_(0), container_(&cont) {
+connection_driver::connection_driver(const std::string& id) : container_id_(id), handler_(0) {
init();
- connection_context& ctx = connection_context::get(unwrap(connection()));
- ctx.container = container_;
}
-#if PN_CPP_HAS_RVALUE_REFERENCES
-connection_driver::connection_driver(class container& cont, event_loop&& loop) : handler_(0), container_(&cont) {
- init();
- connection_context& ctx = connection_context::get(unwrap(connection()));
- ctx.container = container_;
- ctx.event_loop_ = loop.impl_.get();
-}
-#endif
-
connection_driver::~connection_driver() {
pn_connection_driver_destroy(&driver_);
}
@@ -79,10 +68,7 @@ void connection_driver::configure(const connection_options& opts, bool server) {
void connection_driver::connect(const connection_options& opts) {
connection_options all;
- if (container_) {
- all.container_id(container_->id());
- all.update(container_->client_connection_options());
- }
+ all.container_id(container_id_);
all.update(opts);
configure(all, false);
connection().open();
@@ -90,10 +76,7 @@ void connection_driver::connect(const connection_options& opts) {
void connection_driver::accept(const connection_options& opts) {
connection_options all;
- if (container_) {
- all.container_id(container_->id());
- all.update(container_->server_connection_options());
- }
+ all.container_id(container_id_);
all.update(opts);
configure(all, true);
}
@@ -105,7 +88,7 @@ bool connection_driver::has_events() const {
bool connection_driver::dispatch() {
pn_event_t* c_event;
while ((c_event = pn_connection_driver_next_event(&driver_)) != NULL) {
- proton_event cpp_event(c_event, container_);
+ proton_event cpp_event(c_event);
try {
if (handler_ != 0) {
messaging_adapter adapter(*handler_);
@@ -163,8 +146,4 @@ proton::transport connection_driver::transport() const {
return make_wrapper(driver_.transport);
}
-proton::container* connection_driver::container() const {
- return container_;
-}
-
}}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/listener.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/listener.cpp b/proton-c/bindings/cpp/src/listener.cpp
index 2639f5e..a9ca53d 100644
--- a/proton-c/bindings/cpp/src/listener.cpp
+++ b/proton-c/bindings/cpp/src/listener.cpp
@@ -18,12 +18,15 @@
*/
#include "proton/listener.hpp"
-#include "proton/container.hpp"
+
+#include <proton/listener.h>
+
+#include "contexts.hpp"
namespace proton {
-listener::listener() : container_(0) {}
-listener::listener(container& c, const std::string& u) : url_(u), container_(&c) {}
-void listener::stop() { if (container_) container_->stop_listening(url_); }
+listener::listener(): listener_(0) {}
+listener::listener(pn_listener_t* l) : listener_(l) {}
+void listener::stop() { if (listener_) pn_listener_close(listener_); }
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/messaging_adapter.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/messaging_adapter.cpp b/proton-c/bindings/cpp/src/messaging_adapter.cpp
index a70703e..613808b 100644
--- a/proton-c/bindings/cpp/src/messaging_adapter.cpp
+++ b/proton-c/bindings/cpp/src/messaging_adapter.cpp
@@ -58,16 +58,6 @@ void credit_topup(pn_link_t *link) {
}
}
-void messaging_adapter::on_reactor_init(proton_event &pe) {
- container* c = pe.container_ptr();
- if (c) delegate_.on_container_start(*c);
-}
-
-void messaging_adapter::on_reactor_final(proton_event &pe) {
- container* c = pe.container_ptr();
- if (c) delegate_.on_container_stop(*c);
-}
-
void messaging_adapter::on_link_flow(proton_event &pe) {
pn_event_t *pne = pe.pn_event();
pn_link_t *lnk = pn_event_link(pne);
@@ -281,24 +271,17 @@ void messaging_adapter::on_link_local_open(proton_event &pe) {
void messaging_adapter::on_link_remote_open(proton_event &pe) {
pn_link_t *lnk = pn_event_link(pe.pn_event());
- container* c = pe.container_ptr();
if (pn_link_is_receiver(lnk)) {
receiver r(make_wrapper<receiver>(lnk));
delegate_.on_receiver_open(r);
if (is_local_unititialised(pn_link_state(lnk))) {
- if (c)
- r.open(c->receiver_options());
- else
- r.open();
+ r.open(r.connection().receiver_options());
}
} else {
sender s(make_wrapper<sender>(lnk));
delegate_.on_sender_open(s);
if (is_local_unititialised(pn_link_state(lnk))) {
- if (c)
- s.open(c->sender_options());
- else
- s.open();
+ s.open(s.connection().sender_options());
}
}
credit_topup(lnk);
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/proactor_container_impl.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proactor_container_impl.cpp b/proton-c/bindings/cpp/src/proactor_container_impl.cpp
new file mode 100644
index 0000000..2b6b1de
--- /dev/null
+++ b/proton-c/bindings/cpp/src/proactor_container_impl.cpp
@@ -0,0 +1,419 @@
+/*
+ * 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 "proactor_container_impl.hpp"
+#include "proactor_event_loop_impl.hpp"
+
+#include "proton/error_condition.hpp"
+#include "proton/function.hpp"
+#include "proton/listener.hpp"
+#include "proton/listen_handler.hpp"
+#include "proton/thread_safe.hpp"
+#include "proton/url.hpp"
+
+#include "proton/connection.h"
+#include "proton/listener.h"
+#include "proton/proactor.h"
+#include "proton/transport.h"
+
+#include "contexts.hpp"
+#include "messaging_adapter.hpp"
+#include "proton_bits.hpp"
+#include "proton_event.hpp"
+
+#include <assert.h>
+
+#include <algorithm>
+#include <vector>
+
+namespace proton {
+
+event_loop::impl::impl(pn_connection_t* c)
+ : connection_(c), finished_(false)
+{}
+
+void event_loop::impl::finished() {
+ finished_ = true;
+}
+
+#if PN_CPP_HAS_STD_FUNCTION
+bool event_loop::impl::inject(std::function<void()> f) {
+ // Note this is an unbounded work queue.
+ // A resource-safe implementation should be bounded.
+ if (finished_)
+ return false;
+ jobs_.push_back(f);
+ pn_connection_wake(connection_);
+ return true;
+}
+
+bool event_loop::impl::inject(proton::void_function0& f) {
+ return inject([&f]() { f(); });
+}
+
+void event_loop::impl::run_all_jobs() {
+ decltype(jobs_) j;
+ {
+ std::swap(j, jobs_);
+ }
+ // Run queued work, but ignore any exceptions
+ for (auto& f : j) try {
+ f();
+ } catch (...) {};
+}
+#else
+bool event_loop::impl::inject(proton::void_function0& f) {
+ // Note this is an unbounded work queue.
+ // A resource-safe implementation should be bounded.
+ if (finished_)
+ return false;
+ jobs_.push_back(&f);
+ pn_connection_wake(connection_);
+ return true;
+}
+
+void event_loop::impl::run_all_jobs() {
+ // Run queued work, but ignore any exceptions
+ for (event_loop::impl::jobs::iterator f = jobs_.begin(); f != jobs_.end(); ++f) try {
+ (**f)();
+ } catch (...) {};
+ jobs_.clear();
+ return;
+}
+#endif
+container::impl::impl(container& c, const std::string& id, messaging_handler* mh)
+ : container_(c), proactor_(pn_proactor()), handler_(mh), id_(id),
+ auto_stop_(true), stopping_(false)
+{}
+
+container::impl::~impl() {
+ try {
+ stop(error_condition("exception", "container shut-down"));
+ //wait();
+ } catch (...) {}
+ pn_proactor_free(proactor_);
+}
+
+proton::connection container::impl::connect_common(
+ const std::string& addr,
+ const proton::connection_options& user_opts)
+{
+ if (stopping_)
+ throw proton::error("container is stopping");
+
+ connection_options opts = client_connection_options_; // Defaults
+ opts.update(user_opts);
+ messaging_handler* mh = opts.handler();
+
+ proton::url url(addr);
+ pn_connection_t *pnc = pn_connection();
+ connection_context& cc(connection_context::get(pnc));
+ cc.container = &container_;
+ cc.handler = mh;
+ cc.event_loop_ = new event_loop::impl(pnc);
+
+ pn_connection_set_container(pnc, id_.c_str());
+ pn_connection_set_hostname(pnc, url.host().c_str());
+ if (!url.user().empty())
+ pn_connection_set_user(pnc, url.user().c_str());
+ if (!url.password().empty())
+ pn_connection_set_password(pnc, url.password().c_str());
+
+ connection conn = make_wrapper(pnc);
+ conn.open(opts);
+ // Figure out correct string len then create connection address
+ int len = pn_proactor_addr(0, 0, url.host().c_str(), url.port().c_str());
+ std::vector<char> caddr(len+1);
+ pn_proactor_addr(&caddr[0], len+1, url.host().c_str(), url.port().c_str());
+ pn_proactor_connect(proactor_, pnc, &caddr[0]);
+ return conn;
+}
+
+proton::returned<proton::connection> container::impl::connect(
+ const std::string& addr,
+ const proton::connection_options& user_opts)
+{
+ connection conn = connect_common(addr, user_opts);
+ return make_thread_safe(conn);
+}
+
+returned<sender> container::impl::open_sender(const std::string &url, const proton::sender_options &o1, const connection_options &o2) {
+ proton::sender_options lopts(sender_options_);
+ lopts.update(o1);
+ connection conn = connect_common(url, o2);
+
+ return make_thread_safe(conn.default_session().open_sender(proton::url(url).path(), lopts));
+}
+
+returned<receiver> container::impl::open_receiver(const std::string &url, const proton::receiver_options &o1, const connection_options &o2) {
+ proton::receiver_options lopts(receiver_options_);
+ lopts.update(o1);
+ connection conn = connect_common(url, o2);
+
+ return make_thread_safe(
+ conn.default_session().open_receiver(proton::url(url).path(), lopts));
+}
+
+pn_listener_t* container::impl::listen_common_lh(const std::string& addr) {
+ if (stopping_)
+ throw proton::error("container is stopping");
+
+ proton::url url(addr);
+
+ // Figure out correct string len then create connection address
+ int len = pn_proactor_addr(0, 0, url.host().c_str(), url.port().c_str());
+ std::vector<char> caddr(len+1);
+ pn_proactor_addr(&caddr[0], len+1, url.host().c_str(), url.port().c_str());
+
+ pn_listener_t* listener = pn_listener();
+ pn_proactor_listen(proactor_, listener, &caddr[0], 16);
+ return listener;
+}
+
+proton::listener container::impl::listen(const std::string& addr) {
+ pn_listener_t* listener = listen_common_lh(addr);
+ return proton::listener(listener);
+}
+
+proton::listener container::impl::listen(const std::string& addr, const proton::connection_options& opts) {
+ pn_listener_t* listener = listen_common_lh(addr);
+ listener_context& lc=listener_context::get(listener);
+ lc.connection_options_.reset(new connection_options(opts));
+ return proton::listener(listener);
+}
+
+proton::listener container::impl::listen(const std::string& addr, proton::listen_handler& lh) {
+ pn_listener_t* listener = listen_common_lh(addr);
+ listener_context& lc=listener_context::get(listener);
+ lc.listen_handler_ = &lh;
+ return proton::listener(listener);
+}
+
+#if PN_CPP_HAS_STD_FUNCTION
+void container::impl::schedule(duration delay, void_function0& f) {
+ schedule(delay, [&f](){ f(); } );
+}
+
+void container::impl::schedule(duration delay, std::function<void()> f) {
+ // Set timeout
+ pn_proactor_set_timeout(proactor_, delay.milliseconds());
+
+ // Record timeout; Add callback to timeout sorted list
+ deferred_.emplace_back(scheduled{timestamp::now()+delay, f});
+ std::push_heap(deferred_.begin(), deferred_.end());
+}
+#else
+void container::impl::scheduled::task() {(*task_)();}
+
+void container::impl::schedule(duration delay, void_function0& f) {
+ // Set timeout
+ pn_proactor_set_timeout(proactor_, delay.milliseconds());
+
+ // Record timeout; Add callback to timeout sorted list
+ scheduled s={timestamp::now()+delay, &f};
+ deferred_.push_back(s);
+ std::push_heap(deferred_.begin(), deferred_.end());
+}
+#endif
+
+void container::impl::client_connection_options(const connection_options &opts) {
+ client_connection_options_ = opts;
+}
+
+void container::impl::server_connection_options(const connection_options &opts) {
+ server_connection_options_ = opts;
+}
+
+void container::impl::sender_options(const proton::sender_options &opts) {
+ sender_options_ = opts;
+}
+
+void container::impl::receiver_options(const proton::receiver_options &opts) {
+ receiver_options_ = opts;
+}
+
+void container::impl::run_timer_jobs() {
+ // Check head of timer queue
+ timestamp now = timestamp::now();
+ scheduled* next = &deferred_.front();
+
+ // So every scheduled element that has past run and remove head
+ while ( next->time<=now ) {
+ next->task();
+ std::pop_heap(deferred_.begin(), deferred_.end());
+ deferred_.pop_back();
+ // If there are no more scheduled items finish now
+ if ( deferred_.size()==0 ) return;
+ next = &deferred_.front();
+ };
+
+ // To get here we know we must have at least one more thing scheduled
+ pn_proactor_set_timeout(proactor_, (next->time-now).milliseconds());
+}
+
+bool container::impl::handle(pn_event_t* event) {
+
+ // If we have any pending connection work, do it now
+ pn_connection_t* c = pn_event_connection(event);
+ if (c) {
+ event_loop::impl* loop = connection_context::get(c).event_loop_.impl_.get();
+ loop->run_all_jobs();
+ }
+
+ // Process events that shouldn't be sent to messaging_handler
+ switch (pn_event_type(event)) {
+
+ case PN_PROACTOR_INACTIVE: /* listener and all connections closed */
+ return auto_stop_;
+
+ // We never interrupt the proactor so ignore
+ case PN_PROACTOR_INTERRUPT:
+ return false;
+
+ case PN_PROACTOR_TIMEOUT:
+ // Maybe we got a timeout and have nothing scheduled (not sure if this is possible)
+ if ( deferred_.size()==0 ) return false;
+
+ run_timer_jobs();
+ return false;
+
+ case PN_LISTENER_OPEN:
+ return false;
+
+ case PN_LISTENER_ACCEPT: {
+ pn_listener_t* l = pn_event_listener(event);
+ pn_connection_t* c = pn_connection();
+ listener_context &lc(listener_context::get(l));
+ pn_connection_set_container(c, id_.c_str());
+ connection_options opts = server_connection_options_;
+ if (lc.listen_handler_) {
+ listener lstr(l);
+ opts.update(lc.listen_handler_->on_accept(lstr));
+ }
+ else if (!!lc.connection_options_) opts.update(*lc.connection_options_);
+ lc.connection_options_.reset(new connection_options(opts));
+ // Handler applied separately
+ connection_context& cc = connection_context::get(c);
+ cc.container = &container_;
+ cc.listener_context_ = &lc;
+ cc.handler = opts.handler();
+ cc.event_loop_ = new event_loop::impl(c);
+ pn_listener_accept(l, c);
+ return false;
+ }
+ case PN_LISTENER_CLOSE: {
+ pn_listener_t* l = pn_event_listener(event);
+ listener_context &lc(listener_context::get(l));
+ listener lstnr(l);
+ if (lc.listen_handler_) {
+ pn_condition_t* c = pn_listener_condition(l);
+ if (pn_condition_is_set(c)) {
+ lc.listen_handler_->on_error(lstnr, make_wrapper(c).what());
+ }
+ lc.listen_handler_->on_close(lstnr);
+ }
+ return false;
+ }
+ // If the event was just connection wake then there isn't anything more to do
+ case PN_CONNECTION_WAKE:
+ return false;
+
+ // Connection driver will bind a new transport to the connection at this point
+ case PN_CONNECTION_INIT:
+ return false;
+
+ case PN_CONNECTION_BOUND: {
+ // Need to apply post bind connection options
+ pn_connection_t* c = pn_event_connection(event);
+ connection conn = make_wrapper(c);
+ connection_context& cc = connection_context::get(c);
+ if (cc.listener_context_) {
+ cc.listener_context_->connection_options_->apply_bound(conn);
+ } else {
+ client_connection_options_.apply_bound(conn);
+ }
+
+ return false;
+ }
+ default:
+ break;
+ }
+
+ // Figure out the handler for the primary object for event
+ messaging_handler* mh = 0;
+
+ // First try for a link (send/receiver) handler
+ pn_link_t *link = pn_event_link(event);
+ if (link) mh = get_handler(link);
+
+ // Try for session handler if no link handler
+ pn_session_t *session = pn_event_session(event);
+ if (session && !mh) mh = get_handler(session);
+
+ // Try for connection handler if none of the above
+ pn_connection_t *connection = pn_event_connection(event);
+ if (connection && !mh) mh = get_handler(connection);
+
+ // Use container handler if nothing more specific (must be a container handler)
+ if (!mh) mh = handler_;
+
+ // If we still have no handler don't do anything!
+ // This is pretty unusual, but possible if we use the default constructor for container
+ if (!mh) return false;
+
+ // TODO: Currently create a throwaway messaging_adapter and proton_event so we can call dispatch, a bit inefficient
+ messaging_adapter ma(*mh);
+ proton_event pe(event);
+ pe.dispatch(ma);
+ return false;
+}
+
+void container::impl::thread(container::impl& ci) {
+ bool finished = false;
+ do {
+ pn_event_batch_t *events = pn_proactor_wait(ci.proactor_);
+ pn_event_t *e;
+ while ((e = pn_event_batch_next(events))) {
+ finished = ci.handle(e) || finished;
+ }
+ pn_proactor_done(ci.proactor_, events);
+ } while(!finished);
+}
+
+void container::impl::run() {
+ // Have to "manually" generate container events
+ if (handler_) handler_->on_container_start(container_);
+ thread(*this);
+ if (handler_) handler_->on_container_stop(container_);
+}
+
+void container::impl::auto_stop(bool set) {
+ auto_stop_ = set;
+}
+
+void container::impl::stop(const proton::error_condition& err) {
+ auto_stop_ = true;
+ stopping_ = true;
+ pn_condition_t* error_condition = pn_condition();
+ set_error_condition(err, error_condition);
+ pn_proactor_disconnect(proactor_, error_condition);
+ pn_condition_free(error_condition);
+}
+
+}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/receiver.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/receiver.cpp b/proton-c/bindings/cpp/src/receiver.cpp
index 68d55d0..b7239a5 100644
--- a/proton-c/bindings/cpp/src/receiver.cpp
+++ b/proton-c/bindings/cpp/src/receiver.cpp
@@ -34,7 +34,6 @@
#include <proton/session.h>
#include <proton/link.h>
#include <proton/event.h>
-#include <proton/reactor.h>
namespace proton {
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/receiver_options.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/receiver_options.cpp b/proton-c/bindings/cpp/src/receiver_options.cpp
index 4a4d80f..2b134bc 100644
--- a/proton-c/bindings/cpp/src/receiver_options.cpp
+++ b/proton-c/bindings/cpp/src/receiver_options.cpp
@@ -27,7 +27,7 @@
#include <proton/link.h>
#include "contexts.hpp"
-#include "container_impl.hpp"
+#include "proactor_container_impl.hpp"
#include "messaging_adapter.hpp"
#include "proton_bits.hpp"
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/reconnect_timer.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/reconnect_timer.cpp b/proton-c/bindings/cpp/src/reconnect_timer.cpp
index c63f8a1..a299b0e 100644
--- a/proton-c/bindings/cpp/src/reconnect_timer.cpp
+++ b/proton-c/bindings/cpp/src/reconnect_timer.cpp
@@ -23,7 +23,6 @@
#include "proton/error.hpp"
#include "msg.hpp"
#include <proton/types.h>
-#include <proton/reactor.h>
namespace proton {
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/sender_options.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/sender_options.cpp b/proton-c/bindings/cpp/src/sender_options.cpp
index 4f501e6..9305666 100644
--- a/proton-c/bindings/cpp/src/sender_options.cpp
+++ b/proton-c/bindings/cpp/src/sender_options.cpp
@@ -24,7 +24,7 @@
#include "proton/source_options.hpp"
#include "proton/target_options.hpp"
-#include "container_impl.hpp"
+#include "proactor_container_impl.hpp"
#include "contexts.hpp"
#include "messaging_adapter.hpp"
#include "proton_bits.hpp"
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9fad779c/proton-c/bindings/cpp/src/session_options.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/session_options.cpp b/proton-c/bindings/cpp/src/session_options.cpp
index 2147fd4..fc03ebb 100644
--- a/proton-c/bindings/cpp/src/session_options.cpp
+++ b/proton-c/bindings/cpp/src/session_options.cpp
@@ -27,7 +27,7 @@
#include <proton/session.h>
#include "messaging_adapter.hpp"
-#include "container_impl.hpp"
+#include "proactor_container_impl.hpp"
#include "proton_bits.hpp"
namespace proton {
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[10/20] qpid-proton git commit: PROTON-1400: WIP Use the mt broker
example as the example instead of the previous st broker - The st broker
didn't correctly respect the object access constraints from within handlers
Posted by as...@apache.org.
PROTON-1400: WIP Use the mt broker example as the example instead of the previous st broker
- The st broker didn't correctly respect the object access constraints from within handlers
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/4eba80ee
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/4eba80ee
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/4eba80ee
Branch: refs/heads/master
Commit: 4eba80ee8527ab3145427803ad3bfdf801d79229
Parents: d168b7b
Author: Andrew Stitcher <as...@apache.org>
Authored: Tue Jan 24 23:36:03 2017 -0500
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
examples/cpp/broker.cpp | 352 +++++++++++---------
examples/cpp/broker.hpp | 236 --------------
examples/cpp/mt/broker.cpp | 318 ------------------
examples/cpp/mt/epoll_container.cpp | 541 -------------------------------
examples/cpp/mt/mt_container.hpp | 29 --
5 files changed, 190 insertions(+), 1286 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4eba80ee/examples/cpp/broker.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/broker.cpp b/examples/cpp/broker.cpp
index 97ef206..e47a2a6 100644
--- a/examples/cpp/broker.cpp
+++ b/examples/cpp/broker.cpp
@@ -1,5 +1,4 @@
/*
- *
* 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
@@ -16,271 +15,300 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
- *
*/
#include "options.hpp"
#include <proton/connection.hpp>
+#include <proton/connection_options.hpp>
#include <proton/container.hpp>
#include <proton/default_container.hpp>
#include <proton/delivery.hpp>
#include <proton/error_condition.hpp>
+#include <proton/listen_handler.hpp>
#include <proton/listener.hpp>
-#include <proton/messaging_handler.hpp>
#include <proton/message.hpp>
-#include <proton/receiver_options.hpp>
-#include <proton/sender.hpp>
+#include <proton/messaging_handler.hpp>
#include <proton/sender_options.hpp>
#include <proton/source_options.hpp>
-#include <proton/target_options.hpp>
+#include <proton/target.hpp>
+#include <proton/thread_safe.hpp>
#include <proton/tracker.hpp>
-#include <proton/transport.hpp>
-#include <proton/url.hpp>
+#include <atomic>
#include <deque>
+#include <functional>
#include <iostream>
-#include <list>
#include <map>
+#include <mutex>
#include <string>
#include "fake_cpp11.hpp"
-/// A simple implementation of a queue.
+// Thread safe queue.
+// Stores messages, notifies subscribed connections when there is data.
class queue {
public:
- queue(const std::string &name, bool dynamic = false) : name_(name), dynamic_(dynamic) {}
+ queue(const std::string& name) : name_(name) {}
std::string name() const { return name_; }
- void subscribe(proton::sender s) {
- consumers_.push_back(s);
- }
-
- // Return true if queue can be deleted.
- bool unsubscribe(proton::sender s) {
- consumers_.remove(s);
- return (consumers_.size() == 0 && (dynamic_ || messages_.size() == 0));
- }
-
- void publish(const proton::message &m) {
+ // Push a message onto the queue.
+ // If the queue was previously empty, notify subscribers it has messages.
+ // Called from receiver's connection.
+ void push(const proton::message &m) {
+ std::lock_guard<std::mutex> g(lock_);
messages_.push_back(m);
- dispatch(0);
- }
-
- void dispatch(proton::sender *s) {
- while (deliver_to(s)) {}
- }
-
- bool deliver_to(proton::sender *s) {
- // Deliver to single sender if supplied, else all consumers
- int count = s ? 1 : consumers_.size();
-
- if (!count) return false;
-
- bool result = false;
- sender_list::iterator it = consumers_.begin();
-
- if (!s && count) {
- s = &*it;
+ if (messages_.size() == 1) { // Non-empty, notify subscribers
+ for (auto cb : callbacks_)
+ cb(this);
+ callbacks_.clear();
}
+ }
- while (messages_.size()) {
- if (s->credit()) {
- const proton::message& m = messages_.front();
-
- s->send(m);
- messages_.pop_front();
- result = true;
- }
-
- if (--count) {
- it++;
- } else {
- return result;
- }
+ // If the queue is not empty, pop a message into m and return true.
+ // Otherwise save callback to be called when there are messages and return false.
+ // Called from sender's connection.
+ bool pop(proton::message& m, std::function<void(queue*)> callback) {
+ std::lock_guard<std::mutex> g(lock_);
+ if (messages_.empty()) {
+ callbacks_.push_back(callback);
+ return false;
+ } else {
+ m = std::move(messages_.front());
+ messages_.pop_front();
+ return true;
}
-
- return false;
}
private:
- typedef std::deque<proton::message> message_queue;
- typedef std::list<proton::sender> sender_list;
-
- std::string name_;
- bool dynamic_;
- message_queue messages_;
- sender_list consumers_;
+ const std::string name_;
+ std::mutex lock_;
+ std::deque<proton::message> messages_;
+ std::vector<std::function<void(queue*)> > callbacks_;
};
-/// A collection of queues and queue factory, used by a broker.
+/// Thread safe map of queues.
class queues {
public:
queues() : next_id_(0) {}
- virtual ~queues() {}
- // Get or create a queue.
- virtual queue &get(const std::string &address) {
- if (address.empty()) {
- throw std::runtime_error("empty queue name");
- }
-
- queue*& q = queues_[address];
-
- if (!q) q = new queue(address);
-
- return *q;
+ // Get or create the named queue.
+ queue* get(const std::string& name) {
+ std::lock_guard<std::mutex> g(lock_);
+ auto i = queues_.insert(queue_map::value_type(name, nullptr)).first;
+ if (!i->second)
+ i->second.reset(new queue(name));
+ return i->second.get();
}
// Create a dynamic queue with a unique name.
- virtual queue &dynamic() {
+ queue* dynamic() {
std::ostringstream os;
- os << "q" << next_id_++;
- queue *q = queues_[os.str()] = new queue(os.str(), true);
-
- return *q;
+ os << "_dynamic_" << next_id_++;
+ return get(os.str());
}
- // Delete the named queue
- virtual void erase(std::string &name) {
- delete queues_[name];
- queues_.erase(name);
- }
+ private:
+ typedef std::map<std::string, std::unique_ptr<queue> > queue_map;
- protected:
- typedef std::map<std::string, queue *> queue_map;
+ std::mutex lock_;
queue_map queues_;
- int next_id_; // Use to generate unique queue IDs.
+ std::atomic<int> next_id_; // Use to generate unique queue IDs.
};
-// A handler to implement broker logic
-class broker_handler : public proton::messaging_handler {
+/// Broker connection handler. Things to note:
+///
+/// 1. Each handler manages a single connection.
+///
+/// 2. For a *single connection* calls to proton::handler functions and calls to
+/// function objects passed to proton::event_loop::inject() are serialized,
+/// i.e. never called concurrently. Handlers can have per-connection state
+/// without needing locks.
+///
+/// 3. Handler/injected functions for *different connections* can be called
+/// concurrently. Resources used by multiple connections (e.g. the queues in
+/// this example) must be thread-safe.
+///
+/// 4. You can 'inject' work to be done sequentially using a connection's
+/// proton::event_loop. In this example, we create a std::function callback
+/// that we pass to queues, so they can notify us when they have messages.
+///
+class broker_connection_handler : public proton::messaging_handler {
public:
- broker_handler(queues& qs) : queues_(qs) {}
+ broker_connection_handler(queues& qs) : queues_(qs) {}
+
+ void on_connection_open(proton::connection& c) OVERRIDE {
+ // Create the has_messages callback for queue subscriptions.
+ //
+ // Make a std::shared_ptr to a thread_safe handle for our proton::connection.
+ // The connection's proton::event_loop will remain valid as a shared_ptr exists.
+ std::shared_ptr<proton::thread_safe<proton::connection> > ts_c = make_shared_thread_safe(c);
+
+ // Make a lambda function to inject a call to this->has_messages() via the proton::event_loop.
+ // The function is bound to a shared_ptr so this is safe. If the connection has already closed
+ // proton::event_loop::inject() will drop the callback.
+ has_messages_callback_ = [this, ts_c](queue* q) mutable {
+ ts_c->event_loop().inject(
+ std::bind(&broker_connection_handler::has_messages, this, q));
+ };
+
+ c.open(); // Accept the connection
+ }
+ // A sender sends messages from a queue to a subscriber.
void on_sender_open(proton::sender &sender) OVERRIDE {
- proton::source src(sender.source());
- queue *q;
- if (src.dynamic()) {
- q = &queues_.dynamic();
- } else if (!src.address().empty()) {
- q = &queues_.get(src.address());
- } else {
- sender.close(proton::error_condition("No queue address supplied"));
- return;
- }
- sender.open(proton::sender_options().source(proton::source_options().address(q->name())));
- q->subscribe(sender);
- std::cout << "broker outgoing link from " << q->name() << std::endl;
+ queue *q = sender.source().dynamic() ?
+ queues_.dynamic() : queues_.get(sender.source().address());
+ sender.open(proton::sender_options().source((proton::source_options().address(q->name()))));
+ std::cout << "sending from " << q->name() << std::endl;
+ }
+
+ // We have credit to send a message.
+ void on_sendable(proton::sender &s) OVERRIDE {
+ queue* q = sender_queue(s);
+ if (!do_send(q, s)) // Queue is empty, save ourselves in the blocked set.
+ blocked_.insert(std::make_pair(q, s));
}
- void on_receiver_open(proton::receiver &receiver) OVERRIDE {
- std::string address = receiver.target().address();
- if (!address.empty()) {
- receiver.open(proton::receiver_options().target(proton::target_options().address(address)));
- std::cout << "broker incoming link to " << address << std::endl;
+ // A receiver receives messages from a publisher to a queue.
+ void on_receiver_open(proton::receiver &r) OVERRIDE {
+ std::string qname = r.target().address();
+ if (qname == "shutdown") {
+ std::cout << "broker shutting down" << std::endl;
+ // Sending to the special "shutdown" queue stops the broker.
+ r.connection().container().stop(
+ proton::error_condition("shutdown", "stop broker"));
} else {
- receiver.close(proton::error_condition("No queue address supplied"));
+ std::cout << "receiving to " << qname << std::endl;
}
}
- void unsubscribe(proton::sender lnk) {
- std::string address = lnk.source().address();
+ // A message is received.
+ void on_message(proton::delivery &d, proton::message &m) OVERRIDE {
+ std::string qname = d.receiver().target().address();
+ queues_.get(qname)->push(m);
+ }
- if (queues_.get(address).unsubscribe(lnk)) {
- queues_.erase(address);
- }
+ void on_session_close(proton::session &session) OVERRIDE {
+ // Erase all blocked senders that belong to session.
+ auto predicate = [session](const proton::sender& s) {
+ return s.session() == session;
+ };
+ erase_sender_if(blocked_.begin(), blocked_.end(), predicate);
}
void on_sender_close(proton::sender &sender) OVERRIDE {
- unsubscribe(sender);
+ // Erase sender from the blocked set.
+ auto range = blocked_.equal_range(sender_queue(sender));
+ auto predicate = [sender](const proton::sender& s) { return s == sender; };
+ erase_sender_if(range.first, range.second, predicate);
}
- void on_connection_close(proton::connection &c) OVERRIDE {
- remove_stale_consumers(c);
+ void on_error(const proton::error_condition& e) OVERRIDE {
+ std::cerr << "error: " << e.what() << std::endl;
}
-
- void on_transport_close(proton::transport &t) OVERRIDE {
- remove_stale_consumers(t.connection());
+ // The container calls on_transport_close() last.
+ void on_transport_close(proton::transport&) OVERRIDE {
+ delete this; // All done.
}
- void on_transport_error(proton::transport &t) OVERRIDE {
- std::cout << "broker client disconnect: " << t.error().what() << std::endl;
- }
+ private:
+ typedef std::multimap<queue*, proton::sender> blocked_map;
- void on_error(const proton::error_condition &c) OVERRIDE {
- std::cerr << "broker error: " << c.what() << std::endl;
+ // Get the queue associated with a sender.
+ queue* sender_queue(const proton::sender& s) {
+ return queues_.get(s.source().address()); // Thread safe.
}
- void remove_stale_consumers(proton::connection connection) {
- proton::sender_range r = connection.senders();
- for (proton::sender_iterator i = r.begin(); i != r.end(); ++i) {
- if (i->active())
- unsubscribe(*i);
- }
+ // Only called if we have credit. Return true if we sent a message.
+ bool do_send(queue* q, proton::sender &s) {
+ proton::message m;
+ bool popped = q->pop(m, has_messages_callback_);
+ if (popped)
+ s.send(m);
+ /// if !popped the queue has saved the callback for later.
+ return popped;
}
- void on_sendable(proton::sender &s) OVERRIDE {
- std::string address = s.source().address();
-
- queues_.get(address).dispatch(&s);
+ // Called via the connection's proton::event_loop when q has messages.
+ // Try all the blocked senders.
+ void has_messages(queue* q) {
+ auto range = blocked_.equal_range(q);
+ for (auto i = range.first; i != range.second;) {
+ if (i->second.credit() <= 0 || do_send(q, i->second))
+ i = blocked_.erase(i); // No credit or send was successful, stop blocked.
+ else
+ ++i; // have credit, didn't send, keep blocked
+ }
}
- void on_message(proton::delivery &d, proton::message &m) OVERRIDE {
- std::string address = d.receiver().target().address();
- queues_.get(address).publish(m);
+ // Use to erase closed senders from blocked_ set.
+ template <class Predicate>
+ void erase_sender_if(blocked_map::iterator begin, blocked_map::iterator end, Predicate p) {
+ for (auto i = begin; i != end; ) {
+ if (p(i->second))
+ i = blocked_.erase(i);
+ else
+ ++i;
+ }
}
- protected:
queues& queues_;
+ blocked_map blocked_;
+ std::function<void(queue*)> has_messages_callback_;
+ proton::connection connection_;
};
-// The broker
class broker {
public:
- broker(const std::string& url) : handler_(url, queues_) {}
+ broker(const std::string addr) :
+ container_("mt_broker"), listener_(queues_)
+ {
+ container_.listen(addr, listener_);
+ std::cout << "broker listening on " << addr << std::endl;
+ }
- proton::messaging_handler& handler() { return handler_; }
+ void run() {
+ container_.run(/* std::thread::hardware_concurrency() */);
+ }
private:
- class my_handler : public broker_handler {
- public:
- my_handler(const std::string& u, queues& qs) : broker_handler(qs), url_(u) {}
+ struct listener : public proton::listen_handler {
+ listener(queues& qs) : queues_(qs) {}
- void on_container_start(proton::container &c) OVERRIDE {
- c.listen(url_);
- std::cout << "broker listening on " << url_ << std::endl;
+ proton::connection_options on_accept(proton::listener&) OVERRIDE{
+ return proton::connection_options().handler(*(new broker_connection_handler(queues_)));
}
- private:
- const std::string& url_;
+ void on_error(proton::listener&, const std::string& s) OVERRIDE {
+ std::cerr << "listen error: " << s << std::endl;
+ throw std::runtime_error(s);
+ }
+ queues& queues_;
};
- private:
queues queues_;
- my_handler handler_;
+ proton::container container_;
+ listener listener_;
};
int main(int argc, char **argv) {
- std::string url("0.0.0.0");
+ // Command line options
+ std::string address("0.0.0.0");
example::options opts(argc, argv);
- opts.add_value(url, 'a', "address", "listen on URL", "URL");
+ opts.add_value(address, 'a', "address", "listen on URL", "URL");
try {
opts.parse();
-
- broker b(url);
- proton::default_container(b.handler()).run();
-
+ broker(address).run();
return 0;
} catch (const example::bad_option& e) {
std::cout << opts << std::endl << e.what() << std::endl;
} catch (const std::exception& e) {
- std::cerr << e.what() << std::endl;
+ std::cerr << "broker shutdown: " << e.what() << std::endl;
}
-
return 1;
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4eba80ee/examples/cpp/broker.hpp
----------------------------------------------------------------------
diff --git a/examples/cpp/broker.hpp b/examples/cpp/broker.hpp
deleted file mode 100644
index 953713f..0000000
--- a/examples/cpp/broker.hpp
+++ /dev/null
@@ -1,236 +0,0 @@
-#ifndef BROKER_HPP
-#define BROKER_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.
- */
-
-/// @file
-///
-/// Common code used by different broker examples.
-///
-/// The examples add functionality as needed, this helps to make it
-/// easier to see the important differences between the examples.
-
-#include <proton/connection.hpp>
-#include <proton/delivery.hpp>
-#include <proton/messaging_handler.hpp>
-#include <proton/message.hpp>
-#include <proton/sasl.hpp>
-#include <proton/sender.hpp>
-#include <proton/tracker.hpp>
-#include <proton/transport.hpp>
-#include <proton/sender_options.hpp>
-#include <proton/receiver_options.hpp>
-#include <proton/source_options.hpp>
-#include <proton/target_options.hpp>
-
-#include <iostream>
-#include <deque>
-#include <map>
-#include <list>
-#include <sstream>
-
-/// A simple implementation of a queue.
-class queue {
- public:
- queue(const std::string &name, bool dynamic = false) : name_(name), dynamic_(dynamic) {}
-
- std::string name() const { return name_; }
-
- void subscribe(proton::sender s) {
- consumers_.push_back(s);
- }
-
- // Return true if queue can be deleted.
- bool unsubscribe(proton::sender s) {
- consumers_.remove(s);
- return (consumers_.size() == 0 && (dynamic_ || messages_.size() == 0));
- }
-
- void publish(const proton::message &m) {
- messages_.push_back(m);
- dispatch(0);
- }
-
- void dispatch(proton::sender *s) {
- while (deliver_to(s)) {}
- }
-
- bool deliver_to(proton::sender *s) {
- // Deliver to single sender if supplied, else all consumers
- int count = s ? 1 : consumers_.size();
-
- if (!count) return false;
-
- bool result = false;
- sender_list::iterator it = consumers_.begin();
-
- if (!s && count) {
- s = &*it;
- }
-
- while (messages_.size()) {
- if (s->credit()) {
- const proton::message& m = messages_.front();
-
- s->send(m);
- messages_.pop_front();
- result = true;
- }
-
- if (--count) {
- it++;
- } else {
- return result;
- }
- }
-
- return false;
- }
-
- private:
- typedef std::deque<proton::message> message_queue;
- typedef std::list<proton::sender> sender_list;
-
- std::string name_;
- bool dynamic_;
- message_queue messages_;
- sender_list consumers_;
-};
-
-/// A collection of queues and queue factory, used by a broker.
-class queues {
- public:
- queues() : next_id_(0) {}
- virtual ~queues() {}
-
- // Get or create a queue.
- virtual queue &get(const std::string &address = std::string()) {
- if (address.empty()) {
- throw std::runtime_error("empty queue name");
- }
-
- queue*& q = queues_[address];
-
- if (!q) q = new queue(address);
-
- return *q;
- }
-
- // Create a dynamic queue with a unique name.
- virtual queue &dynamic() {
- std::ostringstream os;
- os << "q" << next_id_++;
- queue *q = queues_[os.str()] = new queue(os.str(), true);
-
- return *q;
- }
-
- // Delete the named queue
- virtual void erase(std::string &name) {
- delete queues_[name];
- queues_.erase(name);
- }
-
- protected:
- typedef std::map<std::string, queue *> queue_map;
- queue_map queues_;
- int next_id_; // Use to generate unique queue IDs.
-};
-
-#include <proton/config.hpp>
-
-/** Common handler logic for brokers. */
-class broker_handler : public proton::messaging_handler {
- public:
- broker_handler(queues& qs) : queues_(qs) {}
-
- void on_transport_open(proton::transport &t) OVERRIDE {
- std::cout << "Connection from user: " << t.sasl().user() << " (mechanism: " << t.sasl().mech() << ")" << std::endl;
- }
-
- void on_sender_open(proton::sender &sender) OVERRIDE {
- proton::source src(sender.source());
- queue &q = src.dynamic() ?
- queues_.dynamic() : queues_.get(src.address());
- sender.open(proton::sender_options().source(proton::source_options().address(q.name())));
- q.subscribe(sender);
- std::cout << "broker outgoing link from " << q.name() << std::endl;
- }
-
- void on_receiver_open(proton::receiver &receiver) OVERRIDE {
- std::string address = receiver.target().address();
- if (!address.empty()) {
- receiver.open(proton::receiver_options().target(proton::target_options().address(address)));
- std::cout << "broker incoming link to " << address << std::endl;
- }
- }
-
- void unsubscribe(proton::sender lnk) {
- std::string address = lnk.source().address();
-
- if (queues_.get(address).unsubscribe(lnk)) {
- queues_.erase(address);
- }
- }
-
- void on_sender_close(proton::sender &sender) OVERRIDE {
- unsubscribe(sender);
- }
-
- void on_connection_close(proton::connection &c) OVERRIDE {
- remove_stale_consumers(c);
- }
-
- void on_transport_close(proton::transport &t) OVERRIDE {
- remove_stale_consumers(t.connection());
- }
-
- void on_transport_error(proton::transport &t) OVERRIDE {
- std::cout << "broker client disconnect: " << t.error().what() << std::endl;
- }
-
- void on_error(const proton::error_condition &c) OVERRIDE {
- std::cerr << "broker error: " << c.what() << std::endl;
- }
-
- void remove_stale_consumers(proton::connection connection) {
- proton::sender_range sr = connection.senders();
- for (proton::sender_iterator i = sr.begin(); i != sr.end(); ++i) {
- if (i->active())
- unsubscribe(*i);
- }
- }
-
- void on_sendable(proton::sender &s) OVERRIDE {
- std::string address = s.source().address();
-
- queues_.get(address).dispatch(&s);
- }
-
- void on_message(proton::delivery &d, proton::message &m) OVERRIDE {
- std::string address = d.receiver().target().address();
- queues_.get(address).publish(m);
- }
-
- protected:
- queues& queues_;
-};
-
-#endif // BROKER_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4eba80ee/examples/cpp/mt/broker.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/mt/broker.cpp b/examples/cpp/mt/broker.cpp
deleted file mode 100644
index 83b7005..0000000
--- a/examples/cpp/mt/broker.cpp
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * 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 "../options.hpp"
-#include "mt_container.hpp"
-
-#include <proton/connection.hpp>
-#include <proton/connection_options.hpp>
-#include <proton/container.hpp>
-#include <proton/default_container.hpp>
-#include <proton/delivery.hpp>
-#include <proton/error_condition.hpp>
-#include <proton/listen_handler.hpp>
-#include <proton/listener.hpp>
-#include <proton/message.hpp>
-#include <proton/messaging_handler.hpp>
-#include <proton/sender_options.hpp>
-#include <proton/source_options.hpp>
-#include <proton/target.hpp>
-#include <proton/thread_safe.hpp>
-#include <proton/tracker.hpp>
-
-#include <atomic>
-#include <deque>
-#include <functional>
-#include <iostream>
-#include <map>
-#include <mutex>
-#include <thread>
-
-#include "../fake_cpp11.hpp"
-
-// Thread safe queue.
-// Stores messages, notifies subscribed connections when there is data.
-class queue {
- public:
- queue(const std::string& name) : name_(name) {}
-
- std::string name() const { return name_; }
-
- // Push a message onto the queue.
- // If the queue was previously empty, notify subscribers it has messages.
- // Called from receiver's connection.
- void push(const proton::message &m) {
- std::lock_guard<std::mutex> g(lock_);
- messages_.push_back(m);
- if (messages_.size() == 1) { // Non-empty, notify subscribers
- for (auto cb : callbacks_)
- cb(this);
- callbacks_.clear();
- }
- }
-
- // If the queue is not empty, pop a message into m and return true.
- // Otherwise save callback to be called when there are messages and return false.
- // Called from sender's connection.
- bool pop(proton::message& m, std::function<void(queue*)> callback) {
- std::lock_guard<std::mutex> g(lock_);
- if (messages_.empty()) {
- callbacks_.push_back(callback);
- return false;
- } else {
- m = std::move(messages_.front());
- messages_.pop_front();
- return true;
- }
- }
-
- private:
- const std::string name_;
- std::mutex lock_;
- std::deque<proton::message> messages_;
- std::vector<std::function<void(queue*)> > callbacks_;
-};
-
-/// Thread safe map of queues.
-class queues {
- public:
- queues() : next_id_(0) {}
-
- // Get or create the named queue.
- queue* get(const std::string& name) {
- std::lock_guard<std::mutex> g(lock_);
- auto i = queues_.insert(queue_map::value_type(name, nullptr)).first;
- if (!i->second)
- i->second.reset(new queue(name));
- return i->second.get();
- }
-
- // Create a dynamic queue with a unique name.
- queue* dynamic() {
- std::ostringstream os;
- os << "_dynamic_" << next_id_++;
- return get(os.str());
- }
-
- private:
- typedef std::map<std::string, std::unique_ptr<queue> > queue_map;
-
- std::mutex lock_;
- queue_map queues_;
- std::atomic<int> next_id_; // Use to generate unique queue IDs.
-};
-
-/// Broker connection handler. Things to note:
-///
-/// 1. Each handler manages a single connection.
-///
-/// 2. For a *single connection* calls to proton::handler functions and calls to
-/// function objects passed to proton::event_loop::inject() are serialized,
-/// i.e. never called concurrently. Handlers can have per-connection state
-/// without needing locks.
-///
-/// 3. Handler/injected functions for *different connections* can be called
-/// concurrently. Resources used by multiple connections (e.g. the queues in
-/// this example) must be thread-safe.
-///
-/// 4. You can 'inject' work to be done sequentially using a connection's
-/// proton::event_loop. In this example, we create a std::function callback
-/// that we pass to queues, so they can notify us when they have messages.
-///
-class broker_connection_handler : public proton::messaging_handler {
- public:
- broker_connection_handler(queues& qs) : queues_(qs) {}
-
- void on_connection_open(proton::connection& c) OVERRIDE {
- // Create the has_messages callback for queue subscriptions.
- //
- // Make a std::shared_ptr to a thread_safe handle for our proton::connection.
- // The connection's proton::event_loop will remain valid as a shared_ptr exists.
- std::shared_ptr<proton::thread_safe<proton::connection> > ts_c = make_shared_thread_safe(c);
-
- // Make a lambda function to inject a call to this->has_messages() via the proton::event_loop.
- // The function is bound to a shared_ptr so this is safe. If the connection has already closed
- // proton::event_loop::inject() will drop the callback.
- has_messages_callback_ = [this, ts_c](queue* q) mutable {
- ts_c->event_loop()->inject(
- std::bind(&broker_connection_handler::has_messages, this, q));
- };
-
- c.open(); // Accept the connection
- }
-
- // A sender sends messages from a queue to a subscriber.
- void on_sender_open(proton::sender &sender) OVERRIDE {
- queue *q = sender.source().dynamic() ?
- queues_.dynamic() : queues_.get(sender.source().address());
- sender.open(proton::sender_options().source((proton::source_options().address(q->name()))));
- std::cout << "sending from " << q->name() << std::endl;
- }
-
- // We have credit to send a message.
- void on_sendable(proton::sender &s) OVERRIDE {
- queue* q = sender_queue(s);
- if (!do_send(q, s)) // Queue is empty, save ourselves in the blocked set.
- blocked_.insert(std::make_pair(q, s));
- }
-
- // A receiver receives messages from a publisher to a queue.
- void on_receiver_open(proton::receiver &r) OVERRIDE {
- std::string qname = r.target().address();
- if (qname == "shutdown") {
- std::cout << "broker shutting down" << std::endl;
- // Sending to the special "shutdown" queue stops the broker.
- r.connection().container().stop(
- proton::error_condition("shutdown", "stop broker"));
- } else {
- std::cout << "receiving to " << qname << std::endl;
- }
- }
-
- // A message is received.
- void on_message(proton::delivery &d, proton::message &m) OVERRIDE {
- std::string qname = d.receiver().target().address();
- queues_.get(qname)->push(m);
- }
-
- void on_session_close(proton::session &session) OVERRIDE {
- // Erase all blocked senders that belong to session.
- auto predicate = [session](const proton::sender& s) {
- return s.session() == session;
- };
- erase_sender_if(blocked_.begin(), blocked_.end(), predicate);
- }
-
- void on_sender_close(proton::sender &sender) OVERRIDE {
- // Erase sender from the blocked set.
- auto range = blocked_.equal_range(sender_queue(sender));
- auto predicate = [sender](const proton::sender& s) { return s == sender; };
- erase_sender_if(range.first, range.second, predicate);
- }
-
- void on_error(const proton::error_condition& e) OVERRIDE {
- std::cerr << "error: " << e.what() << std::endl;
- }
- // The container calls on_transport_close() last.
- void on_transport_close(proton::transport&) OVERRIDE {
- delete this; // All done.
- }
-
- private:
- typedef std::multimap<queue*, proton::sender> blocked_map;
-
- // Get the queue associated with a sender.
- queue* sender_queue(const proton::sender& s) {
- return queues_.get(s.source().address()); // Thread safe.
- }
-
- // Only called if we have credit. Return true if we sent a message.
- bool do_send(queue* q, proton::sender &s) {
- proton::message m;
- bool popped = q->pop(m, has_messages_callback_);
- if (popped)
- s.send(m);
- /// if !popped the queue has saved the callback for later.
- return popped;
- }
-
- // Called via the connection's proton::event_loop when q has messages.
- // Try all the blocked senders.
- void has_messages(queue* q) {
- auto range = blocked_.equal_range(q);
- for (auto i = range.first; i != range.second;) {
- if (i->second.credit() <= 0 || do_send(q, i->second))
- i = blocked_.erase(i); // No credit or send was successful, stop blocked.
- else
- ++i; // have credit, didn't send, keep blocked
- }
- }
-
- // Use to erase closed senders from blocked_ set.
- template <class Predicate>
- void erase_sender_if(blocked_map::iterator begin, blocked_map::iterator end, Predicate p) {
- for (auto i = begin; i != end; ) {
- if (p(i->second))
- i = blocked_.erase(i);
- else
- ++i;
- }
- }
-
- queues& queues_;
- blocked_map blocked_;
- std::function<void(queue*)> has_messages_callback_;
- proton::connection connection_;
-};
-
-
-class broker {
- public:
- broker(const std::string addr) :
- container_(make_mt_container("mt_broker")), listener_(queues_)
- {
- container_->listen(addr, listener_);
- std::cout << "broker listening on " << addr << std::endl;
- }
-
- void run() {
- std::vector<std::thread> threads(std::thread::hardware_concurrency()-1);
- for (auto& t : threads)
- t = std::thread(&proton::container::run, container_.get());
- container_->run(); // Use this thread too.
- for (auto& t : threads)
- t.join();
- }
-
- private:
- struct listener : public proton::listen_handler {
- listener(queues& qs) : queues_(qs) {}
-
- proton::connection_options on_accept() OVERRIDE{
- return proton::connection_options().handler(*(new broker_connection_handler(queues_)));
- }
-
- void on_error(const std::string& s) OVERRIDE {
- std::cerr << "listen error: " << s << std::endl;
- throw std::runtime_error(s);
- }
- queues& queues_;
- };
-
- queues queues_;
- std::unique_ptr<proton::container> container_;
- listener listener_;
-};
-
-int main(int argc, char **argv) {
- // Command line options
- std::string address("0.0.0.0");
- example::options opts(argc, argv);
- opts.add_value(address, 'a', "address", "listen on URL", "URL");
- try {
- opts.parse();
- broker(address).run();
- return 0;
- } catch (const example::bad_option& e) {
- std::cout << opts << std::endl << e.what() << std::endl;
- } catch (const std::exception& e) {
- std::cerr << "broker shutdown: " << e.what() << std::endl;
- }
- return 1;
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4eba80ee/examples/cpp/mt/epoll_container.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/mt/epoll_container.cpp b/examples/cpp/mt/epoll_container.cpp
deleted file mode 100644
index 5643fcc..0000000
--- a/examples/cpp/mt/epoll_container.cpp
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- * 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 "mt_container.hpp"
-
-#include <proton/default_container.hpp>
-#include <proton/event_loop.hpp>
-#include <proton/listen_handler.hpp>
-#include <proton/url.hpp>
-
-#include <proton/io/container_impl_base.hpp>
-#include <proton/io/connection_driver.hpp>
-#include <proton/io/link_namer.hpp>
-
-#include <atomic>
-#include <memory>
-#include <mutex>
-#include <condition_variable>
-#include <thread>
-#include <set>
-#include <sstream>
-#include <system_error>
-
-// Linux native IO
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <sys/epoll.h>
-#include <sys/eventfd.h>
-#include <unistd.h>
-
-#include "../fake_cpp11.hpp"
-
-// Private implementation
-namespace {
-
-
-using lock_guard = std::lock_guard<std::mutex>;
-
-// Get string from errno
-std::string errno_str(const std::string& msg) {
- return std::system_error(errno, std::system_category(), msg).what();
-}
-
-// Throw proton::error(errno_str(msg)) if result < 0
-int check(int result, const std::string& msg) {
- if (result < 0)
- throw proton::error(errno_str(msg));
- return result;
-}
-
-// Wrapper for getaddrinfo() that cleans up in destructor.
-class unique_addrinfo {
- public:
- unique_addrinfo(const std::string& addr) : addrinfo_(0) {
- proton::url u(addr);
- int result = ::getaddrinfo(char_p(u.host()), char_p(u.port()), 0, &addrinfo_);
- if (result)
- throw proton::error(std::string("bad address: ") + gai_strerror(result));
- }
- ~unique_addrinfo() { if (addrinfo_) ::freeaddrinfo(addrinfo_); }
-
- ::addrinfo* operator->() const { return addrinfo_; }
-
- private:
- static const char* char_p(const std::string& s) { return s.empty() ? 0 : s.c_str(); }
- ::addrinfo *addrinfo_;
-};
-
-// File descriptor wrapper that calls ::close in destructor.
-class unique_fd {
- public:
- unique_fd(int fd) : fd_(fd) {}
- ~unique_fd() { if (fd_ >= 0) ::close(fd_); }
- operator int() const { return fd_; }
- int release() { int ret = fd_; fd_ = -1; return ret; }
-
- protected:
- int fd_;
-};
-
-class pollable;
-class pollable_driver;
-class pollable_listener;
-
-class epoll_container : public proton::io::container_impl_base {
- public:
- epoll_container(const std::string& id);
- ~epoll_container();
-
- // Pull in base class functions here so that name search finds all the overloads
- using standard_container::stop;
- using standard_container::connect;
- using standard_container::listen;
-
- proton::returned<proton::connection> connect(
- const std::string& addr, const proton::connection_options& opts) OVERRIDE;
-
- proton::listener listen(const std::string& addr, proton::listen_handler&) OVERRIDE;
-
- void stop_listening(const std::string& addr) OVERRIDE;
-
- void run() OVERRIDE;
- void auto_stop(bool) OVERRIDE;
- void stop(const proton::error_condition& err) OVERRIDE;
-
- std::string id() const OVERRIDE { return id_; }
-
- // Functions used internally.
- proton::connection add_driver(proton::connection_options opts, int fd, bool server);
- void erase(pollable*);
-
- // Link names must be unique per container.
- // Generate unique names with a simple atomic counter.
- class atomic_link_namer : public proton::io::link_namer {
- public:
- std::string link_name() {
- std::ostringstream o;
- o << std::hex << ++count_;
- return o.str();
- }
- private:
- std::atomic<int> count_;
- };
-
- // TODO aconway 2016-06-07: Unfinished
- void schedule(proton::duration, std::function<void()>) OVERRIDE { throw std::logic_error("not implemented"); }
- void schedule(proton::duration, proton::void_function0&) OVERRIDE { throw std::logic_error("not implemented"); }
- atomic_link_namer link_namer;
-
- private:
- template <class T> void store(T& v, const T& x) const { lock_guard g(lock_); v = x; }
-
- void idle_check(const lock_guard&);
- void interrupt();
- void wait();
-
- const std::string id_;
- const unique_fd epoll_fd_;
- const unique_fd interrupt_fd_;
-
- mutable std::mutex lock_;
-
- proton::connection_options options_;
- std::map<std::string, std::unique_ptr<pollable_listener> > listeners_;
- std::map<pollable*, std::unique_ptr<pollable_driver> > drivers_;
-
- std::condition_variable stopped_;
- bool stopping_;
- proton::error_condition stop_err_;
- std::atomic<size_t> threads_;
-};
-
-// Base class for pollable file-descriptors. Manages epoll interaction,
-// subclasses implement virtual work() to do their serialized work.
-class pollable {
- public:
- pollable(int fd, int epoll_fd) : fd_(fd), epoll_fd_(epoll_fd), notified_(false), working_(false)
- {
- int flags = check(::fcntl(fd, F_GETFL, 0), "non-blocking");
- check(::fcntl(fd, F_SETFL, flags | O_NONBLOCK), "non-blocking");
- ::epoll_event ev = {};
- ev.data.ptr = this;
- ::epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd_, &ev);
- }
-
- virtual ~pollable() {
- ::epoll_event ev = {};
- ::epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd_, &ev); // Ignore errors.
- }
-
- bool do_work(uint32_t events) {
- {
- lock_guard g(lock_);
- if (working_)
- return true; // Another thread is already working.
- working_ = true;
- notified_ = false;
- }
- uint32_t new_events = work(events); // Serialized, outside the lock.
- if (new_events) {
- lock_guard g(lock_);
- rearm(notified_ ? EPOLLIN|EPOLLOUT : new_events);
- }
- return new_events;
- }
-
- // Called from any thread to wake up the connection handler.
- void notify() {
- lock_guard g(lock_);
- if (!notified_) {
- notified_ = true;
- if (!working_) // No worker thread, rearm now.
- rearm(EPOLLIN|EPOLLOUT);
- }
- }
-
- protected:
-
- // Subclass implements work.
- // Returns epoll events to re-enable or 0 if finished.
- virtual uint32_t work(uint32_t events) = 0;
-
- const unique_fd fd_;
- const int epoll_fd_;
-
- private:
-
- void rearm(uint32_t events) {
- epoll_event ev;
- ev.data.ptr = this;
- ev.events = EPOLLONESHOT | events;
- check(::epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, fd_, &ev), "re-arm epoll");
- working_ = false;
- }
-
- std::mutex lock_;
- bool notified_;
- bool working_;
-};
-
-class epoll_event_loop : public proton::event_loop {
- public:
- typedef std::vector<std::function<void()> > jobs;
-
- epoll_event_loop(pollable& p) : pollable_(p), closed_(false) {}
-
- bool inject(std::function<void()> f) OVERRIDE {
- // Note this is an unbounded work queue.
- // A resource-safe implementation should be bounded.
- lock_guard g(lock_);
- if (closed_)
- return false;
- jobs_.push_back(f);
- pollable_.notify();
- return true;
- }
-
- bool inject(proton::void_function0& f) OVERRIDE {
- return inject([&f]() { f(); });
- }
-
- jobs pop_all() {
- lock_guard g(lock_);
- return std::move(jobs_);
- }
-
- void close() {
- lock_guard g(lock_);
- closed_ = true;
- }
-
- private:
- std::mutex lock_;
- pollable& pollable_;
- jobs jobs_;
- bool closed_;
-};
-
-// Handle epoll wakeups for a connection_driver.
-class pollable_driver : public pollable {
- public:
- pollable_driver(epoll_container& c, int fd, int epoll_fd) :
- pollable(fd, epoll_fd),
- loop_(new epoll_event_loop(*this)),
- driver_(c, loop_)
- {
- proton::connection conn = driver_.connection();
- proton::io::set_link_namer(conn, c.link_namer);
- }
-
- ~pollable_driver() {
- loop_->close(); // No calls to notify() after this.
- driver_.dispatch(); // Run any final events.
- try { write(); } catch(...) {} // Write connection close if we can.
- for (auto f : loop_->pop_all()) {// Run final queued work for side-effects.
- try { f(); } catch(...) {}
- }
- }
-
- uint32_t work(uint32_t events) {
- try {
- bool can_read = events & EPOLLIN, can_write = events & EPOLLOUT;
- do {
- can_write = can_write && write();
- can_read = can_read && read();
- for (auto f : loop_->pop_all()) // Run queued work
- f();
- driver_.dispatch();
- } while (can_read || can_write);
- return (driver_.read_buffer().size ? EPOLLIN:0) |
- (driver_.write_buffer().size ? EPOLLOUT:0);
- } catch (const std::exception& e) {
- driver_.disconnected(proton::error_condition("exception", e.what()));
- }
- return 0; // Ending
- }
-
- proton::io::connection_driver& driver() { return driver_; }
-
- private:
- static bool try_again(int e) {
- // These errno values from read or write mean "try again"
- return (e == EAGAIN || e == EWOULDBLOCK || e == EINTR);
- }
-
- bool write() {
- proton::io::const_buffer wbuf(driver_.write_buffer());
- if (wbuf.size) {
- ssize_t n = ::write(fd_, wbuf.data, wbuf.size);
- if (n > 0) {
- driver_.write_done(n);
- return true;
- } else if (n < 0 && !try_again(errno)) {
- check(n, "write");
- }
- }
- return false;
- }
-
- bool read() {
- proton::io::mutable_buffer rbuf(driver_.read_buffer());
- if (rbuf.size) {
- ssize_t n = ::read(fd_, rbuf.data, rbuf.size);
- if (n > 0) {
- driver_.read_done(n);
- return true;
- }
- else if (n == 0)
- driver_.read_close();
- else if (!try_again(errno))
- check(n, "read");
- }
- return false;
- }
-
- // Lifecycle note: loop_ belongs to the proton::connection, which can live
- // longer than the driver if the application holds a reference to it, we
- // disconnect ourselves with loop_->close() in ~connection_driver()
- epoll_event_loop* loop_;
- proton::io::connection_driver driver_;
-};
-
-// A pollable listener fd that creates pollable_driver for incoming connections.
-class pollable_listener : public pollable {
- public:
- pollable_listener(
- const std::string& addr,
- proton::listen_handler& l,
- int epoll_fd,
- epoll_container& c
- ) :
- pollable(socket_listen(addr), epoll_fd),
- addr_(addr),
- container_(c),
- listener_(l)
- {}
-
- uint32_t work(uint32_t events) {
- if (events & EPOLLRDHUP) {
- try { listener_.on_close(); } catch (...) {}
- return 0;
- }
- try {
- int accepted = check(::accept(fd_, NULL, 0), "accept");
- container_.add_driver(listener_.on_accept(), accepted, true);
- return EPOLLIN;
- } catch (const std::exception& e) {
- listener_.on_error(e.what());
- return 0;
- }
- }
-
- std::string addr() { return addr_; }
-
- private:
-
- static int socket_listen(const std::string& addr) {
- std::string msg = "listen on "+addr;
- unique_addrinfo ainfo(addr);
- unique_fd fd(check(::socket(ainfo->ai_family, SOCK_STREAM, 0), msg));
- int yes = 1;
- check(::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)), msg);
- check(::bind(fd, ainfo->ai_addr, ainfo->ai_addrlen), msg);
- check(::listen(fd, 32), msg);
- return fd.release();
- }
-
- std::string addr_;
- std::function<proton::connection_options(const std::string&)> factory_;
- epoll_container& container_;
- proton::connection_options opts_;
- proton::listen_handler& listener_;
-};
-
-
-epoll_container::epoll_container(const std::string& id)
- : id_(id), epoll_fd_(check(epoll_create(1), "epoll_create")),
- interrupt_fd_(check(eventfd(1, 0), "eventfd")),
- stopping_(false), threads_(0)
-{}
-
-epoll_container::~epoll_container() {
- try {
- stop(proton::error_condition("exception", "container shut-down"));
- wait();
- } catch (...) {}
-}
-
-proton::connection epoll_container::add_driver(proton::connection_options opts, int fd, bool server)
-{
- lock_guard g(lock_);
- if (stopping_)
- throw proton::error("container is stopping");
- std::unique_ptr<pollable_driver> eng(new pollable_driver(*this, fd, epoll_fd_));
- if (server)
- eng->driver().accept(opts);
- else
- eng->driver().connect(opts);
- proton::connection c = eng->driver().connection();
- eng->notify();
- drivers_[eng.get()] = std::move(eng);
- return c;
-}
-
-void epoll_container::erase(pollable* e) {
- lock_guard g(lock_);
- if (!drivers_.erase(e)) {
- pollable_listener* l = dynamic_cast<pollable_listener*>(e);
- if (l)
- listeners_.erase(l->addr());
- }
- idle_check(g);
-}
-
-void epoll_container::idle_check(const lock_guard&) {
- if (stopping_ && drivers_.empty() && listeners_.empty())
- interrupt();
-}
-
-proton::returned<proton::connection> epoll_container::connect(
- const std::string& addr, const proton::connection_options& opts)
-{
- std::string msg = "connect to "+addr;
- unique_addrinfo ainfo(addr);
- unique_fd fd(check(::socket(ainfo->ai_family, SOCK_STREAM, 0), msg));
- check(::connect(fd, ainfo->ai_addr, ainfo->ai_addrlen), msg);
- return make_thread_safe(add_driver(opts, fd.release(), false));
-}
-
-proton::listener epoll_container::listen(const std::string& addr, proton::listen_handler& lh) {
- lock_guard g(lock_);
- if (stopping_)
- throw proton::error("container is stopping");
- auto& l = listeners_[addr];
- try {
- l.reset(new pollable_listener(addr, lh, epoll_fd_, *this));
- l->notify();
- return proton::listener(*this, addr);
- } catch (const std::exception& e) {
- lh.on_error(e.what());
- lh.on_close();
- throw;
- }
-}
-
-void epoll_container::stop_listening(const std::string& addr) {
- lock_guard g(lock_);
- listeners_.erase(addr);
- idle_check(g);
-}
-
-void epoll_container::run() {
- ++threads_;
- try {
- epoll_event e;
- while(true) {
- check(::epoll_wait(epoll_fd_, &e, 1, -1), "epoll_wait");
- pollable* p = reinterpret_cast<pollable*>(e.data.ptr);
- if (!p)
- break; // Interrupted
- if (!p->do_work(e.events))
- erase(p);
- }
- } catch (const std::exception& e) {
- stop(proton::error_condition("exception", e.what()));
- }
- if (--threads_ == 0)
- stopped_.notify_all();
-}
-
-void epoll_container::auto_stop(bool set) {
- lock_guard g(lock_);
- stopping_ = set;
-}
-
-void epoll_container::stop(const proton::error_condition& err) {
- lock_guard g(lock_);
- stop_err_ = err;
- interrupt();
-}
-
-void epoll_container::wait() {
- std::unique_lock<std::mutex> l(lock_);
- stopped_.wait(l, [this]() { return this->threads_ == 0; } );
- for (auto& eng : drivers_)
- eng.second->driver().disconnected(stop_err_);
- listeners_.clear();
- drivers_.clear();
-}
-
-void epoll_container::interrupt() {
- // Add an always-readable fd with 0 data and no ONESHOT to interrupt all threads.
- epoll_event ev = {};
- ev.events = EPOLLIN;
- check(epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupt_fd_, &ev), "interrupt");
-}
-
-}
-
-// This is the only public function.
-std::unique_ptr<proton::container> make_mt_container(const std::string& id) {
- return std::unique_ptr<proton::container>(new epoll_container(id));
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4eba80ee/examples/cpp/mt/mt_container.hpp
----------------------------------------------------------------------
diff --git a/examples/cpp/mt/mt_container.hpp b/examples/cpp/mt/mt_container.hpp
deleted file mode 100644
index 164fe72..0000000
--- a/examples/cpp/mt/mt_container.hpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef MT_MT_CONTROLLER_HPP
-#define MT_MT_CONTROLLER_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 <proton/default_container.hpp>
-#include <memory>
-
-// Defined in whichever MT container implementation we are linked with.
-std::unique_ptr<proton::container> make_mt_container(const std::string& id);
-
-#endif // MT_MT_DEFAULT_CONTAINER.HPP
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[20/20] qpid-proton git commit: PROTON-1481: [C++ binding] Rename
proton::defer -> proton::schedule_work
Posted by as...@apache.org.
PROTON-1481: [C++ binding] Rename proton::defer -> proton::schedule_work
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/8aee73b6
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/8aee73b6
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/8aee73b6
Branch: refs/heads/master
Commit: 8aee73b611bd0faff3d065e1ed16f89d5c222b73
Parents: 1e2efdb
Author: Andrew Stitcher <as...@apache.org>
Authored: Fri May 19 17:02:05 2017 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
examples/cpp/broker.cpp | 24 ++++++------
examples/cpp/scheduled_send_03.cpp | 6 +--
.../bindings/cpp/include/proton/thread_safe.hpp | 2 +-
.../bindings/cpp/include/proton/work_queue.hpp | 40 ++++++++++----------
4 files changed, 36 insertions(+), 36 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8aee73b6/examples/cpp/broker.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/broker.cpp b/examples/cpp/broker.cpp
index 09a771c..2cb2b36 100644
--- a/examples/cpp/broker.cpp
+++ b/examples/cpp/broker.cpp
@@ -139,7 +139,7 @@ class Queue {
DOUT(std::cerr << "(" << current_->second << ") ";);
if (current_->second>0) {
DOUT(std::cerr << current_->first << " ";);
- proton::defer(current_->first, &Sender::sendMsg, current_->first, messages_.front());
+ proton::schedule_work(current_->first, &Sender::sendMsg, current_->first, messages_.front());
messages_.pop_front();
--current_->second;
++current_;
@@ -178,14 +178,14 @@ public:
// If we're about to erase the current subscription move on
if (current_ != subscriptions_.end() && current_->first==s) ++current_;
subscriptions_.erase(s);
- proton::defer(s, &Sender::unsubscribed, s);
+ proton::schedule_work(s, &Sender::unsubscribed, s);
}
};
// We have credit to send a message.
void Sender::on_sendable(proton::sender &sender) {
if (queue_) {
- proton::defer(queue_, &Queue::flow, queue_, this, sender.credit());
+ proton::schedule_work(queue_, &Queue::flow, queue_, this, sender.credit());
} else {
pending_credit_ = sender.credit();
}
@@ -193,7 +193,7 @@ void Sender::on_sendable(proton::sender &sender) {
void Sender::on_sender_close(proton::sender &sender) {
if (queue_) {
- proton::defer(queue_, &Queue::unsubscribe, queue_, this);
+ proton::schedule_work(queue_, &Queue::unsubscribe, queue_, this);
} else {
// TODO: Is it possible to be closed before we get the queue allocated?
// If so, we should have a way to mark the sender deleted, so we can delete
@@ -207,12 +207,12 @@ void Sender::boundQueue(Queue* q, std::string qn) {
queue_ = q;
queue_name_ = qn;
- proton::defer(q, &Queue::subscribe, q, this);
+ proton::schedule_work(q, &Queue::subscribe, q, this);
sender_.open(proton::sender_options()
.source((proton::source_options().address(queue_name_)))
.handler(*this));
if (pending_credit_>0) {
- proton::defer(queue_, &Queue::flow, queue_, this, pending_credit_);
+ proton::schedule_work(queue_, &Queue::flow, queue_, this, pending_credit_);
}
std::cout << "sending from " << queue_name_ << std::endl;
}
@@ -237,7 +237,7 @@ class Receiver : public proton::messaging_handler {
void queueMsgs() {
DOUT(std::cerr << "Receiver: " << this << " queueing " << messages_.size() << " msgs to: " << queue_ << "\n";);
while (!messages_.empty()) {
- proton::defer(queue_, &Queue::queueMsg, queue_, messages_.front());
+ proton::schedule_work(queue_, &Queue::queueMsg, queue_, messages_.front());
messages_.pop_front();
}
}
@@ -295,7 +295,7 @@ public:
} else {
q = i->second;
}
- proton::defer(&connection, &T::boundQueue, &connection, q, qn);
+ proton::schedule_work(&connection, &T::boundQueue, &connection, q, qn);
}
void findQueueSender(Sender* s, std::string qn) {
@@ -325,7 +325,7 @@ public:
std::string qn = sender.source().dynamic() ? "" : sender.source().address();
Sender* s = new Sender(sender, senders_);
senders_[sender] = s;
- proton::defer(&queue_manager_, &QueueManager::findQueueSender, &queue_manager_, s, qn);
+ proton::schedule_work(&queue_manager_, &QueueManager::findQueueSender, &queue_manager_, s, qn);
}
// A receiver receives messages from a publisher to a queue.
@@ -341,7 +341,7 @@ public:
DOUT(std::cerr << "ODD - trying to attach to a empty address\n";);
}
Receiver* r = new Receiver(receiver);
- proton::defer(&queue_manager_, &QueueManager::findQueueReceiver, &queue_manager_, r, qname);
+ proton::schedule_work(&queue_manager_, &QueueManager::findQueueReceiver, &queue_manager_, r, qname);
}
}
@@ -352,7 +352,7 @@ public:
if (j == senders_.end()) continue;
Sender* s = j->second;
if (s->queue_) {
- proton::defer(s->queue_, &Queue::unsubscribe, s->queue_, s);
+ proton::schedule_work(s->queue_, &Queue::unsubscribe, s->queue_, s);
}
senders_.erase(j);
}
@@ -370,7 +370,7 @@ public:
if (j == senders_.end()) continue;
Sender* s = j->second;
if (s->queue_) {
- proton::defer(s->queue_, &Queue::unsubscribe, s->queue_, s);
+ proton::schedule_work(s->queue_, &Queue::unsubscribe, s->queue_, s);
}
}
delete this; // All done.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8aee73b6/examples/cpp/scheduled_send_03.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/scheduled_send_03.cpp b/examples/cpp/scheduled_send_03.cpp
index 8ac46a1..008853c 100644
--- a/examples/cpp/scheduled_send_03.cpp
+++ b/examples/cpp/scheduled_send_03.cpp
@@ -62,8 +62,8 @@ class scheduled_sender : public proton::messaging_handler {
void on_sender_open(proton::sender & s) OVERRIDE {
work_queue = &s.work_queue();
- proton::defer(work_queue, timeout, &scheduled_sender::cancel, this, s);
- proton::defer(work_queue, interval, &scheduled_sender::tick, this, s);
+ proton::schedule_work(work_queue, timeout, &scheduled_sender::cancel, this, s);
+ proton::schedule_work(work_queue, interval, &scheduled_sender::tick, this, s);
}
void cancel(proton::sender sender) {
@@ -73,7 +73,7 @@ class scheduled_sender : public proton::messaging_handler {
void tick(proton::sender sender) {
if (!canceled) {
- proton::defer(work_queue, interval, &scheduled_sender::tick, this, sender); // Next tick
+ proton::schedule_work(work_queue, interval, &scheduled_sender::tick, this, sender); // Next tick
if (sender.credit() > 0) // Only send if we have credit
send(sender);
else
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8aee73b6/proton-c/bindings/cpp/include/proton/thread_safe.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/thread_safe.hpp b/proton-c/bindings/cpp/include/proton/thread_safe.hpp
index 04e39df..0b38883 100644
--- a/proton-c/bindings/cpp/include/proton/thread_safe.hpp
+++ b/proton-c/bindings/cpp/include/proton/thread_safe.hpp
@@ -70,7 +70,7 @@ class thread_safe : private internal::pn_ptr_base, private internal::endpoint_tr
~thread_safe() {
if (ptr()) {
- if (!!work_queue().impl_) defer(&work_queue(), &decref, (void*)ptr());
+ if (!!work_queue().impl_) schedule_work(&work_queue(), &decref, (void*)ptr());
else decref(ptr());
}
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8aee73b6/proton-c/bindings/cpp/include/proton/work_queue.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/work_queue.hpp b/proton-c/bindings/cpp/include/proton/work_queue.hpp
index 61567b8..844680b 100644
--- a/proton-c/bindings/cpp/include/proton/work_queue.hpp
+++ b/proton-c/bindings/cpp/include/proton/work_queue.hpp
@@ -284,76 +284,76 @@ void_function0& make_work(R (*f)(A, B, C), A a, B b, C c) {
namespace {
template <class T>
-bool defer_helper(T t, void_function0& w) {
+bool schedule_work_helper(T t, void_function0& w) {
bool r = t->add(w);
if (!r) delete &w;
return r;
}
}
-/// defer is a convenience that is used for C++03 code to defer function calls
+/// schedule_work is a convenience that is used for C++03 code to defer function calls
/// to a work_queue
template <class WQ, class F>
-bool defer(WQ wq, F f) {
- return defer_helper(wq, make_work(f));
+bool schedule_work(WQ wq, F f) {
+ return schedule_work_helper(wq, make_work(f));
}
template <class WQ, class F, class A>
-bool defer(WQ wq, F f, A a) {
- return defer_helper(wq, make_work(f, a));
+bool schedule_work(WQ wq, F f, A a) {
+ return schedule_work_helper(wq, make_work(f, a));
}
template <class WQ, class F, class A, class B>
-bool defer(WQ wq, F f, A a, B b) {
- return defer_helper(wq, make_work(f, a, b));
+bool schedule_work(WQ wq, F f, A a, B b) {
+ return schedule_work_helper(wq, make_work(f, a, b));
}
template <class WQ, class F, class A, class B, class C>
-bool defer(WQ wq, F f, A a, B b, C c) {
- return defer_helper(wq, make_work(f, a, b, c));
+bool schedule_work(WQ wq, F f, A a, B b, C c) {
+ return schedule_work_helper(wq, make_work(f, a, b, c));
}
template <class WQ, class F, class A, class B, class C, class D>
-bool defer(WQ wq, F f, A a, B b, C c, D d) {
- return defer_helper(wq, make_work(f, a, b, c, d));
+bool schedule_work(WQ wq, F f, A a, B b, C c, D d) {
+ return schedule_work_helper(wq, make_work(f, a, b, c, d));
}
template <class WQ, class F>
-void defer(WQ wq, duration dn, F f) {
+void schedule_work(WQ wq, duration dn, F f) {
wq->schedule(dn, make_work(f));
}
template <class WQ, class F, class A>
-void defer(WQ wq, duration dn, F f, A a) {
+void schedule_work(WQ wq, duration dn, F f, A a) {
wq->schedule(dn, make_work(f, a));
}
template <class WQ, class F, class A, class B>
-void defer(WQ wq, duration dn, F f, A a, B b) {
+void schedule_work(WQ wq, duration dn, F f, A a, B b) {
wq->schedule(dn, make_work(f, a, b));
}
template <class WQ, class F, class A, class B, class C>
-void defer(WQ wq, duration dn, F f, A a, B b, C c) {
+void schedule_work(WQ wq, duration dn, F f, A a, B b, C c) {
wq->schedule(dn, make_work(f, a, b, c));
}
template <class WQ, class F, class A, class B, class C, class D>
-void defer(WQ wq, duration dn, F f, A a, B b, C c, D d) {
+void schedule_work(WQ wq, duration dn, F f, A a, B b, C c, D d) {
wq->schedule(dn, make_work(f, a, b, c, d));
}
-/// This version of proton::defer defers calling a free function to an arbitrary work queue
+/// This version of proton::schedule_work schedule_works calling a free function to an arbitrary work queue
#else
// The C++11 version is *much* simpler and even so more general!
// These definitions encompass everything in the C++03 section
template <class WQ, class... Rest>
-bool defer(WQ wq, Rest&&... r) {
+bool schedule_work(WQ wq, Rest&&... r) {
return wq->add(std::bind(std::forward<Rest>(r)...));
}
template <class WQ, class... Rest>
-void defer(WQ wq, duration d, Rest&&... r) {
+void schedule_work(WQ wq, duration d, Rest&&... r) {
wq->schedule(d, std::bind(std::forward<Rest>(r)...));
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[18/20] qpid-proton git commit: PROTON-1482: [C++ binding] Added
convenience overload to proton::defer for scheduled deferred work - Used new
conveniences in scheduled_send_03 example
Posted by as...@apache.org.
PROTON-1482: [C++ binding] Added convenience overload to proton::defer
for scheduled deferred work
- Used new conveniences in scheduled_send_03 example
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/1e2efdb0
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/1e2efdb0
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/1e2efdb0
Branch: refs/heads/master
Commit: 1e2efdb01c8ebf863626150c9c14eae600c4739c
Parents: 88c2d7d
Author: Andrew Stitcher <as...@apache.org>
Authored: Fri May 19 01:38:18 2017 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
examples/cpp/scheduled_send_03.cpp | 50 +++-----------------
.../bindings/cpp/include/proton/work_queue.hpp | 31 ++++++++++++
2 files changed, 37 insertions(+), 44 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1e2efdb0/examples/cpp/scheduled_send_03.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/scheduled_send_03.cpp b/examples/cpp/scheduled_send_03.cpp
index c3c63c8..8ac46a1 100644
--- a/examples/cpp/scheduled_send_03.cpp
+++ b/examples/cpp/scheduled_send_03.cpp
@@ -46,49 +46,13 @@ class scheduled_sender : public proton::messaging_handler {
proton::work_queue *work_queue;
bool ready, canceled;
- struct cancel_fn : public proton::void_function0 {
- scheduled_sender* parent;
- proton::sender sender;
- cancel_fn(): parent(0) {}
- cancel_fn(scheduled_sender& ss, proton::sender& s) : parent(&ss), sender(s) {}
- void operator()() { if (parent) parent->cancel(sender); }
- };
-
- struct tick_fn : public proton::void_function0 {
- scheduled_sender* parent;
- proton::sender sender;
- tick_fn(): parent(0) {}
- tick_fn(scheduled_sender& ss, proton::sender& s) : parent(&ss), sender(s) {}
- void operator()() { if (parent) parent->tick(sender); }
- };
-
- struct defer_cancel_fn : public proton::void_function0 {
- scheduled_sender& parent;
- defer_cancel_fn(scheduled_sender& ss) : parent(ss) {}
- void operator()() { parent.work_queue->add(parent.do_cancel); }
- };
-
- struct defer_tick_fn : public proton::void_function0 {
- scheduled_sender& parent;
- defer_tick_fn(scheduled_sender& ss) : parent(ss) {}
- void operator()() { parent.work_queue->add(parent.do_tick); }
- };
-
- tick_fn do_tick;
- cancel_fn do_cancel;
- defer_tick_fn defer_tick;
- defer_cancel_fn defer_cancel;
-
public:
-
scheduled_sender(const std::string &s, double d, double t) :
url(s),
interval(int(d*proton::duration::SECOND.milliseconds())), // Send interval.
timeout(int(t*proton::duration::SECOND.milliseconds())), // Cancel after timeout.
ready(true), // Ready to send.
- canceled(false), // Canceled.
- defer_tick(*this),
- defer_cancel(*this)
+ canceled(false) // Canceled.
{}
void on_container_start(proton::container &c) OVERRIDE {
@@ -98,20 +62,18 @@ class scheduled_sender : public proton::messaging_handler {
void on_sender_open(proton::sender & s) OVERRIDE {
work_queue = &s.work_queue();
- do_cancel = cancel_fn(*this, s);
- do_tick = tick_fn(*this, s);
- s.container().schedule(timeout, defer_cancel); // Call this->cancel after timeout.
- s.container().schedule(interval, defer_tick); // Start regular ticks every interval.
+ proton::defer(work_queue, timeout, &scheduled_sender::cancel, this, s);
+ proton::defer(work_queue, interval, &scheduled_sender::tick, this, s);
}
- void cancel(proton::sender& sender) {
+ void cancel(proton::sender sender) {
canceled = true;
sender.connection().close();
}
- void tick(proton::sender& sender) {
+ void tick(proton::sender sender) {
if (!canceled) {
- sender.container().schedule(interval, defer_tick); // Next tick
+ proton::defer(work_queue, interval, &scheduled_sender::tick, this, sender); // Next tick
if (sender.credit() > 0) // Only send if we have credit
send(sender);
else
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1e2efdb0/proton-c/bindings/cpp/include/proton/work_queue.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/work_queue.hpp b/proton-c/bindings/cpp/include/proton/work_queue.hpp
index bef041c..61567b8 100644
--- a/proton-c/bindings/cpp/include/proton/work_queue.hpp
+++ b/proton-c/bindings/cpp/include/proton/work_queue.hpp
@@ -22,6 +22,7 @@
*
*/
+#include "./duration.hpp"
#include "./fwd.hpp"
#include "./function.hpp"
#include "./internal/config.hpp"
@@ -317,6 +318,31 @@ bool defer(WQ wq, F f, A a, B b, C c, D d) {
return defer_helper(wq, make_work(f, a, b, c, d));
}
+template <class WQ, class F>
+void defer(WQ wq, duration dn, F f) {
+ wq->schedule(dn, make_work(f));
+}
+
+template <class WQ, class F, class A>
+void defer(WQ wq, duration dn, F f, A a) {
+ wq->schedule(dn, make_work(f, a));
+}
+
+template <class WQ, class F, class A, class B>
+void defer(WQ wq, duration dn, F f, A a, B b) {
+ wq->schedule(dn, make_work(f, a, b));
+}
+
+template <class WQ, class F, class A, class B, class C>
+void defer(WQ wq, duration dn, F f, A a, B b, C c) {
+ wq->schedule(dn, make_work(f, a, b, c));
+}
+
+template <class WQ, class F, class A, class B, class C, class D>
+void defer(WQ wq, duration dn, F f, A a, B b, C c, D d) {
+ wq->schedule(dn, make_work(f, a, b, c, d));
+}
+
/// This version of proton::defer defers calling a free function to an arbitrary work queue
#else
// The C++11 version is *much* simpler and even so more general!
@@ -326,6 +352,11 @@ bool defer(WQ wq, Rest&&... r) {
return wq->add(std::bind(std::forward<Rest>(r)...));
}
+template <class WQ, class... Rest>
+void defer(WQ wq, duration d, Rest&&... r) {
+ wq->schedule(d, std::bind(std::forward<Rest>(r)...));
+}
+
template <class... Rest>
work make_work(Rest&&... r) {
return std::bind(std::forward<Rest>(r)...);
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[14/20] qpid-proton git commit: PROTON-1481: [C++ binding] simplify
work_queue code by introducing work type - The work type can be created from
std::function or void_function0 - and so pushes those c++11/C++03
differences into a single place
Posted by as...@apache.org.
PROTON-1481: [C++ binding] simplify work_queue code by introducing work type
- The work type can be created from std::function<void()> or void_function0
- and so pushes those c++11/C++03 differences into a single place
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/5dd3f464
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/5dd3f464
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/5dd3f464
Branch: refs/heads/master
Commit: 5dd3f464fbe472de49c0341a853098eba8059a14
Parents: d1c91a4
Author: Andrew Stitcher <as...@apache.org>
Authored: Mon May 15 01:36:52 2017 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
examples/cpp/broker.cpp | 8 +-
.../bindings/cpp/include/proton/container.hpp | 14 +--
proton-c/bindings/cpp/include/proton/fwd.hpp | 4 +-
.../bindings/cpp/include/proton/work_queue.hpp | 52 +++++++---
proton-c/bindings/cpp/src/container.cpp | 6 +-
.../cpp/src/include/proactor_container_impl.hpp | 12 +--
.../src/include/proactor_work_queue_impl.hpp | 6 +-
.../cpp/src/proactor_container_impl.cpp | 103 ++++---------------
proton-c/bindings/cpp/src/work_queue.cpp | 10 +-
9 files changed, 77 insertions(+), 138 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/5dd3f464/examples/cpp/broker.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/broker.cpp b/examples/cpp/broker.cpp
index d39314c..9af60ba 100644
--- a/examples/cpp/broker.cpp
+++ b/examples/cpp/broker.cpp
@@ -185,7 +185,7 @@ public:
sender_(s), senders_(ss), work_queue_(s.work_queue()), queue_(0), pending_credit_(0)
{}
- void add(proton::void_function0& f) {
+ void add(proton::work f) {
work_queue_.add(f);
}
@@ -241,7 +241,7 @@ public:
work_queue_(c), name_(n), current_(subscriptions_.end())
{}
- void add(proton::void_function0& f) {
+ void add(proton::work f) {
work_queue_.add(f);
}
@@ -333,7 +333,7 @@ public:
receiver_(r), work_queue_(r.work_queue()), queue_(0)
{}
- void add(proton::void_function0& f) {
+ void add(proton::work f) {
work_queue_.add(f);
}
@@ -361,7 +361,7 @@ public:
container_(c), work_queue_(c), next_id_(0)
{}
- void add(proton::void_function0& f) {
+ void add(proton::work f) {
work_queue_.add(f);
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/5dd3f464/proton-c/bindings/cpp/include/proton/container.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/container.hpp b/proton-c/bindings/cpp/include/proton/container.hpp
index 383aa3c..0739517 100644
--- a/proton-c/bindings/cpp/include/proton/container.hpp
+++ b/proton-c/bindings/cpp/include/proton/container.hpp
@@ -206,15 +206,11 @@ class PN_CPP_CLASS_EXTERN container {
/// @copydoc receiver_options
PN_CPP_EXTERN class receiver_options receiver_options() const;
- /// Schedule a function to be called after the duration. C++03
- /// compatible, for C++11 use schedule(duration,
- /// std::function<void()>)
- PN_CPP_EXTERN void schedule(duration, void_function0&);
-
-#if PN_CPP_HAS_STD_FUNCTION
- /// Schedule a function to be called after the duration
- PN_CPP_EXTERN void schedule(duration, std::function<void()>);
-#endif
+ /// Schedule a piece of work to happen after the duration:
+ /// The piece of work can be created from a function object.
+ /// for C++11 and on use a std::function<void()> type; for
+ /// C++03 compatibility you can use void_function0&
+ PN_CPP_EXTERN void schedule(duration, work);
private:
class impl;
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/5dd3f464/proton-c/bindings/cpp/include/proton/fwd.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/fwd.hpp b/proton-c/bindings/cpp/include/proton/fwd.hpp
index 6ad216e..b839f42 100644
--- a/proton-c/bindings/cpp/include/proton/fwd.hpp
+++ b/proton-c/bindings/cpp/include/proton/fwd.hpp
@@ -31,7 +31,6 @@ class container;
class delivery;
class error_condition;
class event;
-class work_queue;
class message;
class message_id;
class messaging_handler;
@@ -54,7 +53,8 @@ class tracker;
class transport;
class url;
class void_function0;
-
+class work;
+class work_queue;
namespace io {
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/5dd3f464/proton-c/bindings/cpp/include/proton/work_queue.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/work_queue.hpp b/proton-c/bindings/cpp/include/proton/work_queue.hpp
index 7acd507..7c21710 100644
--- a/proton-c/bindings/cpp/include/proton/work_queue.hpp
+++ b/proton-c/bindings/cpp/include/proton/work_queue.hpp
@@ -23,6 +23,7 @@
*/
#include "./fwd.hpp"
+#include "./function.hpp"
#include "./internal/config.hpp"
#include "./internal/export.hpp"
#include "./internal/pn_unique_ptr.hpp"
@@ -35,12 +36,44 @@ struct pn_link_t;
namespace proton {
-/// **Experimental** - A serial execution context.
+/// **Experimental** - A work queue for serial execution.
///
/// Event handler functions associated with a single proton::connection are called in sequence.
-/// The connection's @ref event_loop allows you to "inject" extra work from any thread,
+/// The connection's @ref work_queue allows you to "inject" extra @ref work from any thread,
/// and have it executed in the same sequence.
///
+/// You may also create arbitrary @ref work_queue objects backed by a @ref container that allow
+/// other objects to have their own serialised work queues that can have work injected safely
+/// from other threads. The @ref container ensures that the work is correctly serialised.
+///
+/// The @ref work class represents the work to be queued and can be created from a function
+/// that takes no parameters and returns no value.
+///
+
+class work {
+ public:
+#if PN_CPP_HAS_STD_FUNCTION
+ work(void_function0& f): item_( [&f]() { f(); }) {}
+ template <class T>
+ work(T f): item_(f) {}
+
+ void operator()() { item_(); }
+#else
+ work(void_function0& f): item_(&f) {}
+
+ void operator()() { (*item_)(); }
+#endif
+ ~work() {}
+
+
+ private:
+#if PN_CPP_HAS_STD_FUNCTION
+ std::function<void()> item_;
+#else
+ void_function0* item_;
+#endif
+};
+
class PN_CPP_CLASS_EXTERN work_queue {
/// @cond internal
class impl;
@@ -48,14 +81,14 @@ class PN_CPP_CLASS_EXTERN work_queue {
/// @endcond
public:
- /// Create event_loop
+ /// Create work_queue
PN_CPP_EXTERN work_queue();
PN_CPP_EXTERN work_queue(container&);
PN_CPP_EXTERN ~work_queue();
#if PN_CPP_HAS_EXPLICIT_CONVERSIONS
- /// When using C++11 (or later) you can use event_loop in a bool context
+ /// When using C++11 (or later) you can use work_queue in a bool context
/// to indicate if there is an event loop set.
PN_CPP_EXTERN explicit operator bool() const { return bool(impl_); }
#endif
@@ -63,17 +96,12 @@ class PN_CPP_CLASS_EXTERN work_queue {
/// No event loop set.
PN_CPP_EXTERN bool operator !() const { return !impl_; }
- /// Arrange to have f() called in the event_loop's sequence: possibly
- /// deferred, possibly in another thread.
+ /// Add work to the work queue: f() will be called serialised with other work in the queue:
+ /// deferred and possibly in another thread.
///
/// @return true if f() has or will be called, false if the event_loop is ended
/// and f() cannot be injected.
- PN_CPP_EXTERN bool add(void_function0& f);
-
-#if PN_CPP_HAS_STD_FUNCTION
- /// @copydoc inject(void_function0&)
- PN_CPP_EXTERN bool add(std::function<void()> f);
-#endif
+ PN_CPP_EXTERN bool add(work f);
private:
PN_CPP_EXTERN static work_queue& get(pn_connection_t*);
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/5dd3f464/proton-c/bindings/cpp/src/container.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/container.cpp b/proton-c/bindings/cpp/src/container.cpp
index b98da78..c2af659 100644
--- a/proton-c/bindings/cpp/src/container.cpp
+++ b/proton-c/bindings/cpp/src/container.cpp
@@ -103,11 +103,7 @@ returned<receiver> container::open_receiver(
std::string container::id() const { return impl_->id(); }
-void container::schedule(duration d, void_function0& f) { return impl_->schedule(d, f); }
-
-#if PN_CPP_HAS_STD_FUNCTION
-void container::schedule(duration d, std::function<void()> f) { return impl_->schedule(d, f); }
-#endif
+void container::schedule(duration d, work f) { return impl_->schedule(d, f); }
void container::client_connection_options(const connection_options& c) { impl_->client_connection_options(c); }
connection_options container::client_connection_options() const { return impl_->client_connection_options(); }
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/5dd3f464/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp b/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
index 9b4be11..fc963f7 100644
--- a/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
+++ b/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
@@ -73,10 +73,7 @@ class container::impl {
void run();
void stop(const error_condition& err);
void auto_stop(bool set);
- void schedule(duration, void_function0&);
-#if PN_CPP_HAS_STD_FUNCTION
- void schedule(duration, std::function<void()>);
-#endif
+ void schedule(duration, work);
template <class T> static void set_handler(T s, messaging_handler* h);
template <class T> static messaging_handler* get_handler(T s);
static work_queue::impl* make_work_queue(container&);
@@ -101,12 +98,7 @@ class container::impl {
void remove_work_queue(container_work_queue*);
struct scheduled {
timestamp time; // duration from epoch for task
-#if PN_CPP_HAS_STD_FUNCTION
- std::function<void()> task;
-#else
- void_function0* task_;
- void task();
-#endif
+ work task;
// We want to get to get the *earliest* first so test is "reversed"
bool operator < (const scheduled& r) const { return r.time < time; }
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/5dd3f464/proton-c/bindings/cpp/src/include/proactor_work_queue_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proactor_work_queue_impl.hpp b/proton-c/bindings/cpp/src/include/proactor_work_queue_impl.hpp
index 57fc4c0..ac0f803 100644
--- a/proton-c/bindings/cpp/src/include/proactor_work_queue_impl.hpp
+++ b/proton-c/bindings/cpp/src/include/proactor_work_queue_impl.hpp
@@ -24,16 +24,14 @@
#include "proton/fwd.hpp"
#include "proton/internal/config.hpp"
+#include "proton/work_queue.hpp"
namespace proton {
class work_queue::impl {
public:
virtual ~impl() {};
- virtual bool inject(void_function0& f) = 0;
-#if PN_CPP_HAS_STD_FUNCTION
- virtual bool inject(std::function<void()> f) = 0;
-#endif
+ virtual bool add(work f) = 0;
virtual void run_all_jobs() = 0;
virtual void finished() = 0;
};
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/5dd3f464/proton-c/bindings/cpp/src/proactor_container_impl.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proactor_container_impl.cpp b/proton-c/bindings/cpp/src/proactor_container_impl.cpp
index 78ccabf..0135c08 100644
--- a/proton-c/bindings/cpp/src/proactor_container_impl.cpp
+++ b/proton-c/bindings/cpp/src/proactor_container_impl.cpp
@@ -47,11 +47,7 @@ class container::impl::common_work_queue : public work_queue::impl {
public:
common_work_queue(): finished_(false) {}
-#if PN_CPP_HAS_STD_FUNCTION
- typedef std::vector<std::function<void()> > jobs;
-#else
- typedef std::vector<void_function0*> jobs;
-#endif
+ typedef std::vector<work> jobs;
void run_all_jobs();
void finished() { finished_ = true; }
@@ -60,100 +56,53 @@ class container::impl::common_work_queue : public work_queue::impl {
bool finished_;
};
-#if PN_CPP_HAS_STD_FUNCTION
-void container::impl::common_work_queue::run_all_jobs() {
- decltype(jobs_) j;
- {
- std::swap(j, jobs_);
- }
- // Run queued work, but ignore any exceptions
- for (auto& f : j) try {
- f();
- } catch (...) {};
-}
-#else
void container::impl::common_work_queue::run_all_jobs() {
+ jobs j;
+ // Lock this operation for mt
+ std::swap(j, jobs_);
// Run queued work, but ignore any exceptions
- for (jobs::iterator f = jobs_.begin(); f != jobs_.end(); ++f) try {
- (**f)();
+ for (jobs::iterator f = j.begin(); f != j.end(); ++f) try {
+ (*f)();
} catch (...) {};
- jobs_.clear();
return;
}
-#endif
class container::impl::connection_work_queue : public common_work_queue {
public:
connection_work_queue(pn_connection_t* c): connection_(c) {}
- bool inject(void_function0& f);
-#if PN_CPP_HAS_STD_FUNCTION
- bool inject(std::function<void()> f);
-#endif
+ bool add(work f);
pn_connection_t* connection_;
};
-#if PN_CPP_HAS_STD_FUNCTION
-bool container::impl::connection_work_queue::inject(std::function<void()> f) {
- // Note this is an unbounded work queue.
- // A resource-safe implementation should be bounded.
- if (finished_) return false;
- jobs_.emplace_back(std::move(f));
- pn_connection_wake(connection_);
- return true;
-}
-
-bool container::impl::connection_work_queue::inject(proton::void_function0& f) {
- return inject([&f]() { f(); });
-}
-#else
-bool container::impl::connection_work_queue::inject(proton::void_function0& f) {
+bool container::impl::connection_work_queue::add(work f) {
// Note this is an unbounded work queue.
// A resource-safe implementation should be bounded.
if (finished_) return false;
- jobs_.push_back(&f);
+ jobs_.push_back(f);
pn_connection_wake(connection_);
return true;
}
-#endif
class container::impl::container_work_queue : public common_work_queue {
public:
container_work_queue(container::impl& c): container_(c) {}
~container_work_queue() { container_.remove_work_queue(this); }
- bool inject(void_function0& f);
-#if PN_CPP_HAS_STD_FUNCTION
- bool inject(std::function<void()> f);
-#endif
+ bool add(work f);
container::impl& container_;
};
-#if PN_CPP_HAS_STD_FUNCTION
-bool container::impl::container_work_queue::inject(std::function<void()> f) {
- // Note this is an unbounded work queue.
- // A resource-safe implementation should be bounded.
- if (finished_) return false;
- jobs_.emplace_back(std::move(f));
- pn_proactor_set_timeout(container_.proactor_, 0);
- return true;
-}
-
-bool container::impl::container_work_queue::inject(proton::void_function0& f) {
- return inject([&f]() { f(); });
-}
-#else
-bool container::impl::container_work_queue::inject(proton::void_function0& f) {
+bool container::impl::container_work_queue::add(work f) {
// Note this is an unbounded work queue.
// A resource-safe implementation should be bounded.
if (finished_) return false;
- jobs_.push_back(&f);
+ jobs_.push_back(f);
pn_proactor_set_timeout(container_.proactor_, 0);
return true;
}
-#endif
class work_queue::impl* container::impl::make_work_queue(container& c) {
return c.impl_->add_work_queue();
@@ -277,32 +226,18 @@ proton::listener container::impl::listen(const std::string& addr, proton::listen
return proton::listener(listener);
}
-#if PN_CPP_HAS_STD_FUNCTION
-void container::impl::schedule(duration delay, void_function0& f) {
- schedule(delay, [&f](){ f(); } );
-}
-
-void container::impl::schedule(duration delay, std::function<void()> f) {
- // Set timeout
- pn_proactor_set_timeout(proactor_, delay.milliseconds());
-
- // Record timeout; Add callback to timeout sorted list
- deferred_.emplace_back(scheduled{timestamp::now()+delay, f});
- std::push_heap(deferred_.begin(), deferred_.end());
-}
-#else
-void container::impl::scheduled::task() {(*task_)();}
-
-void container::impl::schedule(duration delay, void_function0& f) {
- // Set timeout
- pn_proactor_set_timeout(proactor_, delay.milliseconds());
+void container::impl::schedule(duration delay, work f) {
+ timestamp now = timestamp::now();
// Record timeout; Add callback to timeout sorted list
- scheduled s = {timestamp::now()+delay, &f};
+ scheduled s = {now+delay, f};
deferred_.push_back(s);
std::push_heap(deferred_.begin(), deferred_.end());
+
+ // Set timeout for current head of timeout queue
+ scheduled* next = &deferred_.front();
+ pn_proactor_set_timeout(proactor_, (next->time-now).milliseconds());
}
-#endif
void container::impl::client_connection_options(const connection_options &opts) {
client_connection_options_ = opts;
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/5dd3f464/proton-c/bindings/cpp/src/work_queue.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/work_queue.cpp b/proton-c/bindings/cpp/src/work_queue.cpp
index 961e5f0..db95042 100644
--- a/proton-c/bindings/cpp/src/work_queue.cpp
+++ b/proton-c/bindings/cpp/src/work_queue.cpp
@@ -35,16 +35,10 @@ work_queue::~work_queue() {}
work_queue& work_queue::operator=(impl* i) { impl_.reset(i); return *this; }
-bool work_queue::add(void_function0& f) {
- return impl_->inject(f);
+bool work_queue::add(work f) {
+ return impl_->add(f);
}
-#if PN_CPP_HAS_STD_FUNCTION
-bool work_queue::add(std::function<void()> f) {
- return impl_->inject(f);
-}
-#endif
-
work_queue& work_queue::get(pn_connection_t* c) {
return connection_context::get(c).work_queue_;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[04/20] qpid-proton git commit: PROTON-1400: [C++ binding] Change
semantic for incoming xx_open - If not overridden then you get automatic
outgoing matching xx_open - If overridden then it is assumed you will handle
the outgoing open yourself.
Posted by as...@apache.org.
PROTON-1400: [C++ binding] Change semantic for incoming xx_open
- If not overridden then you get automatic outgoing matching xx_open
- If overridden then it is assumed you will handle the outgoing open
yourself.
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/ec2364f0
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/ec2364f0
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/ec2364f0
Branch: refs/heads/master
Commit: ec2364f0bb99937ff37165b7c7c4c74531f27633
Parents: 4eba80e
Author: Andrew Stitcher <as...@apache.org>
Authored: Fri Apr 14 02:13:12 2017 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
examples/cpp/broker.cpp | 3 ++
examples/cpp/ssl.cpp | 3 ++
examples/cpp/ssl_client_cert.cpp | 3 ++
.../bindings/cpp/src/connection_driver_test.cpp | 3 ++
proton-c/bindings/cpp/src/handler.cpp | 34 +++++++++++++++-----
proton-c/bindings/cpp/src/messaging_adapter.cpp | 20 ------------
6 files changed, 38 insertions(+), 28 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ec2364f0/examples/cpp/broker.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/broker.cpp b/examples/cpp/broker.cpp
index e47a2a6..5b0982b 100644
--- a/examples/cpp/broker.cpp
+++ b/examples/cpp/broker.cpp
@@ -29,9 +29,11 @@
#include <proton/listener.hpp>
#include <proton/message.hpp>
#include <proton/messaging_handler.hpp>
+#include <proton/receiver_options.hpp>
#include <proton/sender_options.hpp>
#include <proton/source_options.hpp>
#include <proton/target.hpp>
+#include <proton/target_options.hpp>
#include <proton/thread_safe.hpp>
#include <proton/tracker.hpp>
@@ -180,6 +182,7 @@ class broker_connection_handler : public proton::messaging_handler {
r.connection().container().stop(
proton::error_condition("shutdown", "stop broker"));
} else {
+ r.open(proton::receiver_options().target(proton::target_options().address(qname)));
std::cout << "receiving to " << qname << std::endl;
}
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ec2364f0/examples/cpp/ssl.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/ssl.cpp b/examples/cpp/ssl.cpp
index 00bbccd..85dfa48 100644
--- a/examples/cpp/ssl.cpp
+++ b/examples/cpp/ssl.cpp
@@ -72,6 +72,9 @@ struct server_handler : public proton::messaging_handler {
std::cout << "Inbound server connection connected via SSL. Protocol: " <<
c.transport().ssl().protocol() << std::endl;
listener.stop(); // Just expecting the one connection.
+
+ // Go and do default inbound open stuff too
+ messaging_handler::on_connection_open(c);
}
void on_transport_error(proton::transport &t) OVERRIDE {
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ec2364f0/examples/cpp/ssl_client_cert.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/ssl_client_cert.cpp b/examples/cpp/ssl_client_cert.cpp
index 630e74b..8ca2dc2 100644
--- a/examples/cpp/ssl_client_cert.cpp
+++ b/examples/cpp/ssl_client_cert.cpp
@@ -65,6 +65,9 @@ struct server_handler : public proton::messaging_handler {
c.close();
}
listener.stop();
+
+ // Go and do default inbound open stuff too
+ messaging_handler::on_connection_open(c);
}
void on_message(proton::delivery &, proton::message &m) OVERRIDE {
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ec2364f0/proton-c/bindings/cpp/src/connection_driver_test.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connection_driver_test.cpp b/proton-c/bindings/cpp/src/connection_driver_test.cpp
index ae18ebe..db5bc90 100644
--- a/proton-c/bindings/cpp/src/connection_driver_test.cpp
+++ b/proton-c/bindings/cpp/src/connection_driver_test.cpp
@@ -131,14 +131,17 @@ struct record_handler : public messaging_handler {
std::deque<proton::message> messages;
void on_receiver_open(receiver &l) PN_CPP_OVERRIDE {
+ messaging_handler::on_receiver_open(l);
receivers.push_back(l);
}
void on_sender_open(sender &l) PN_CPP_OVERRIDE {
+ messaging_handler::on_sender_open(l);
senders.push_back(l);
}
void on_session_open(session &s) PN_CPP_OVERRIDE {
+ messaging_handler::on_session_open(s);
sessions.push_back(s);
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ec2364f0/proton-c/bindings/cpp/src/handler.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/handler.cpp b/proton-c/bindings/cpp/src/handler.cpp
index 3137718..84d9e8a 100644
--- a/proton-c/bindings/cpp/src/handler.cpp
+++ b/proton-c/bindings/cpp/src/handler.cpp
@@ -21,17 +21,19 @@
#include "proton/messaging_handler.hpp"
#include "proton/connection.hpp"
+#include "proton/container.hpp"
#include "proton/error_condition.hpp"
#include "proton/receiver.hpp"
+#include "proton/receiver_options.hpp"
#include "proton/sender.hpp"
+#include "proton/sender_options.hpp"
#include "proton/session.hpp"
#include "proton/transport.hpp"
-#include "messaging_adapter.hpp"
+#include "proton_bits.hpp"
-#include <proton/handlers.h>
-
-#include <algorithm>
+#include "proton/connection.h"
+#include "proton/session.h"
namespace proton {
@@ -48,17 +50,33 @@ void messaging_handler::on_transport_error(transport &t) { on_error(t.error());
void messaging_handler::on_transport_open(transport &) {}
void messaging_handler::on_connection_close(connection &) {}
void messaging_handler::on_connection_error(connection &c) { on_error(c.error()); }
-void messaging_handler::on_connection_open(connection &) {}
+void messaging_handler::on_connection_open(connection &c) {
+ if (c.uninitialized()) {
+ pn_connection_open(unwrap(c));
+ }
+}
void messaging_handler::on_session_close(session &) {}
void messaging_handler::on_session_error(session &s) { on_error(s.error()); }
-void messaging_handler::on_session_open(session &) {}
+void messaging_handler::on_session_open(session &s) {
+ if (s.uninitialized()) {
+ pn_session_open(unwrap(s));
+ }
+}
void messaging_handler::on_receiver_close(receiver &) {}
void messaging_handler::on_receiver_error(receiver &l) { on_error(l.error()); }
-void messaging_handler::on_receiver_open(receiver &) {}
+void messaging_handler::on_receiver_open(receiver &l) {
+ if (l.uninitialized()) {
+ l.open(l.connection().receiver_options());
+ }
+}
void messaging_handler::on_receiver_detach(receiver &) {}
void messaging_handler::on_sender_close(sender &) {}
void messaging_handler::on_sender_error(sender &l) { on_error(l.error()); }
-void messaging_handler::on_sender_open(sender &) {}
+void messaging_handler::on_sender_open(sender &l) {
+ if (l.uninitialized()) {
+ l.open(l.connection().sender_options());
+ }
+}
void messaging_handler::on_sender_detach(sender &) {}
void messaging_handler::on_tracker_accept(tracker &) {}
void messaging_handler::on_tracker_reject(tracker &) {}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ec2364f0/proton-c/bindings/cpp/src/messaging_adapter.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/messaging_adapter.cpp b/proton-c/bindings/cpp/src/messaging_adapter.cpp
index 521566c..cb1b776 100644
--- a/proton-c/bindings/cpp/src/messaging_adapter.cpp
+++ b/proton-c/bindings/cpp/src/messaging_adapter.cpp
@@ -176,14 +176,6 @@ void on_delivery(messaging_handler& handler, pn_event_t* event) {
}
}
-bool is_local_open(pn_state_t state) {
- return state & PN_LOCAL_ACTIVE;
-}
-
-bool is_local_unititialised(pn_state_t state) {
- return state & PN_LOCAL_UNINIT;
-}
-
bool is_remote_unititialised(pn_state_t state) {
return state & PN_REMOTE_UNINIT;
}
@@ -256,18 +248,12 @@ void on_connection_remote_open(messaging_handler& handler, pn_event_t* event) {
pn_connection_t *conn = pn_event_connection(event);
connection c(make_wrapper(conn));
handler.on_connection_open(c);
- if (!is_local_open(pn_connection_state(conn)) && is_local_unititialised(pn_connection_state(conn))) {
- pn_connection_open(conn);
- }
}
void on_session_remote_open(messaging_handler& handler, pn_event_t* event) {
pn_session_t *session = pn_event_session(event);
class session s(make_wrapper(session));
handler.on_session_open(s);
- if (!is_local_open(pn_session_state(session)) && is_local_unititialised(pn_session_state(session))) {
- pn_session_open(session);
- }
}
void on_link_local_open(messaging_handler& handler, pn_event_t* event) {
@@ -286,16 +272,10 @@ void on_link_remote_open(messaging_handler& handler, pn_event_t* event) {
if (pn_link_is_receiver(lnk)) {
receiver r(make_wrapper<receiver>(lnk));
handler.on_receiver_open(r);
- if (is_local_unititialised(pn_link_state(lnk))) {
- r.open(r.connection().receiver_options());
- }
credit_topup(lnk);
} else {
sender s(make_wrapper<sender>(lnk));
handler.on_sender_open(s);
- if (is_local_unititialised(pn_link_state(lnk))) {
- s.open(s.connection().sender_options());
- }
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[07/20] qpid-proton git commit: PROTON-1400: [C++ binding] Removed
proton_event and proton_handler - Removed old low level proton event handling
completely - Now directly dispatch to the messaging_handler - Moved private
message::decode directly into mes
Posted by as...@apache.org.
PROTON-1400: [C++ binding] Removed proton_event and proton_handler
- Removed old low level proton event handling completely
- Now directly dispatch to the messaging_handler
- Moved private message::decode directly into message handling code
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/1a513d64
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/1a513d64
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/1a513d64
Branch: refs/heads/master
Commit: 1a513d64f6f884c228e8a0a5b691c96949b3d1f4
Parents: 9c1797c
Author: Andrew Stitcher <as...@apache.org>
Authored: Mon Jan 23 12:32:50 2017 -0500
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
proton-c/bindings/cpp/CMakeLists.txt | 2 -
.../bindings/cpp/include/proton/message.hpp | 4 -
proton-c/bindings/cpp/src/handler.cpp | 1 -
proton-c/bindings/cpp/src/include/contexts.hpp | 2 -
.../cpp/src/include/messaging_adapter.hpp | 30 +-
.../cpp/src/include/proactor_container_impl.hpp | 1 -
.../bindings/cpp/src/include/proton_event.hpp | 286 -------------------
.../bindings/cpp/src/include/proton_handler.hpp | 92 ------
.../bindings/cpp/src/io/connection_driver.cpp | 5 +-
proton-c/bindings/cpp/src/message.cpp | 14 -
proton-c/bindings/cpp/src/messaging_adapter.cpp | 208 ++++++++------
.../cpp/src/proactor_container_impl.cpp | 6 +-
proton-c/bindings/cpp/src/proton_event.cpp | 88 ------
proton-c/bindings/cpp/src/proton_handler.cpp | 74 -----
14 files changed, 131 insertions(+), 682 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1a513d64/proton-c/bindings/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/CMakeLists.txt b/proton-c/bindings/cpp/CMakeLists.txt
index 295a99e..625206f 100644
--- a/proton-c/bindings/cpp/CMakeLists.txt
+++ b/proton-c/bindings/cpp/CMakeLists.txt
@@ -55,8 +55,6 @@ set(qpid-proton-cpp-source
src/node_options.cpp
src/object.cpp
src/proton_bits.cpp
- src/proton_event.cpp
- src/proton_handler.cpp
src/receiver.cpp
src/receiver_options.cpp
src/reconnect_timer.cpp
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1a513d64/proton-c/bindings/cpp/include/proton/message.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/message.hpp b/proton-c/bindings/cpp/include/proton/message.hpp
index a25f7db..a428c46 100644
--- a/proton-c/bindings/cpp/include/proton/message.hpp
+++ b/proton-c/bindings/cpp/include/proton/message.hpp
@@ -319,11 +319,7 @@ class message {
mutable pn_message_t *pn_msg_;
- /// Decode the message corresponding to a delivery from a link.
- void decode(proton::delivery);
-
PN_CPP_EXTERN friend void swap(message&, message&);
- friend class messaging_adapter;
/// @endcond
};
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1a513d64/proton-c/bindings/cpp/src/handler.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/handler.cpp b/proton-c/bindings/cpp/src/handler.cpp
index 5cf6208..3137718 100644
--- a/proton-c/bindings/cpp/src/handler.cpp
+++ b/proton-c/bindings/cpp/src/handler.cpp
@@ -27,7 +27,6 @@
#include "proton/session.hpp"
#include "proton/transport.hpp"
-#include "proton_event.hpp"
#include "messaging_adapter.hpp"
#include <proton/handlers.h>
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1a513d64/proton-c/bindings/cpp/src/include/contexts.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/contexts.hpp b/proton-c/bindings/cpp/src/include/contexts.hpp
index c096a6e..637cbec 100644
--- a/proton-c/bindings/cpp/src/include/contexts.hpp
+++ b/proton-c/bindings/cpp/src/include/contexts.hpp
@@ -32,8 +32,6 @@
#include "proton/io/link_namer.hpp"
-#include "proton_handler.hpp"
-
struct pn_record_t;
struct pn_link_t;
struct pn_session_t;
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1a513d64/proton-c/bindings/cpp/src/include/messaging_adapter.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/messaging_adapter.hpp b/proton-c/bindings/cpp/src/include/messaging_adapter.hpp
index d7eb6a0..10c7682 100644
--- a/proton-c/bindings/cpp/src/include/messaging_adapter.hpp
+++ b/proton-c/bindings/cpp/src/include/messaging_adapter.hpp
@@ -22,37 +22,19 @@
*
*/
-#include "proton/messaging_handler.hpp"
-
-#include "proton_handler.hpp"
-
-#include <proton/event.h>
-#include <proton/reactor.h>
-
///@cond INTERNAL
+struct pn_event_t;
+
namespace proton {
+class messaging_handler;
+
/// Convert the low level proton-c events to the higher level proton::messaging_handler calls
-class messaging_adapter : public proton_handler
+class messaging_adapter
{
public:
- messaging_adapter(messaging_handler &delegate) : delegate_(delegate) {}
-
- void on_link_flow(proton_event &e);
- void on_delivery(proton_event &e);
- void on_connection_remote_open(proton_event &e);
- void on_connection_remote_close(proton_event &e);
- void on_session_remote_open(proton_event &e);
- void on_session_remote_close(proton_event &e);
- void on_link_local_open(proton_event &e);
- void on_link_remote_open(proton_event &e);
- void on_link_remote_detach(proton_event & e);
- void on_link_remote_close(proton_event &e);
- void on_transport_closed(proton_event &e);
-
- private:
- messaging_handler &delegate_; // The handler for generated messaging_event's
+ static void dispatch(messaging_handler& delegate, pn_event_t* e);
};
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1a513d64/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp b/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
index 8c12c02..859493d 100644
--- a/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
+++ b/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
@@ -35,7 +35,6 @@
#include "proton/sender_options.hpp"
#include "proton_bits.hpp"
-#include "proton_handler.hpp"
#include <list>
#include <map>
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1a513d64/proton-c/bindings/cpp/src/include/proton_event.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proton_event.hpp b/proton-c/bindings/cpp/src/include/proton_event.hpp
deleted file mode 100644
index be324e7..0000000
--- a/proton-c/bindings/cpp/src/include/proton_event.hpp
+++ /dev/null
@@ -1,286 +0,0 @@
-#ifndef PROTON_CPP_PROTONEVENT_H
-#define PROTON_CPP_PROTONEVENT_H
-
-/*
- *
- * 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 "proton/fwd.hpp"
-#include "proton/error.hpp"
-
-#include <proton/event.h>
-
-namespace proton {
-
-class proton_handler;
-
-/** Event information for a proton::proton_handler */
-class proton_event
-{
- public:
- /// The type of an event
- enum event_type {
- ///@name Event types
- ///@{
-
- /**
- * Defined as a programming convenience. No event of this type will
- * ever be generated.
- */
- EVENT_NONE=PN_EVENT_NONE,
-
- /**
- * A reactor has been started. Events of this type point to the reactor.
- */
- REACTOR_INIT=PN_REACTOR_INIT,
-
- /**
- * A reactor has no more events to process. Events of this type
- * point to the reactor.
- */
- REACTOR_QUIESCED=PN_REACTOR_QUIESCED,
-
- /**
- * A reactor has been stopped. Events of this type point to the reactor.
- */
- REACTOR_FINAL=PN_REACTOR_FINAL,
-
- /**
- * A timer event has occurred.
- */
- TIMER_TASK=PN_TIMER_TASK,
-
- /**
- * The connection has been created. This is the first event that
- * will ever be issued for a connection. Events of this type point
- * to the relevant connection.
- */
- CONNECTION_INIT=PN_CONNECTION_INIT,
-
- /**
- * The connection has been bound to a transport. This event is
- * issued when the transport::bind() is called.
- */
- CONNECTION_BOUND=PN_CONNECTION_BOUND,
-
- /**
- * The connection has been unbound from its transport. This event is
- * issued when transport::unbind() is called.
- */
- CONNECTION_UNBOUND=PN_CONNECTION_UNBOUND,
-
- /**
- * The local connection endpoint has been closed. Events of this
- * type point to the relevant connection.
- */
- CONNECTION_LOCAL_OPEN=PN_CONNECTION_LOCAL_OPEN,
-
- /**
- * The remote endpoint has opened the connection. Events of this
- * type point to the relevant connection.
- */
- CONNECTION_REMOTE_OPEN=PN_CONNECTION_REMOTE_OPEN,
-
- /**
- * The local connection endpoint has been closed. Events of this
- * type point to the relevant connection.
- */
- CONNECTION_LOCAL_CLOSE=PN_CONNECTION_LOCAL_CLOSE,
-
- /**
- * The remote endpoint has closed the connection. Events of this
- * type point to the relevant connection.
- */
- CONNECTION_REMOTE_CLOSE=PN_CONNECTION_REMOTE_CLOSE,
-
- /**
- * The connection has been freed and any outstanding processing has
- * been completed. This is the final event that will ever be issued
- * for a connection.
- */
- CONNECTION_FINAL=PN_CONNECTION_FINAL,
-
- /**
- * The session has been created. This is the first event that will
- * ever be issued for a session.
- */
- SESSION_INIT=PN_SESSION_INIT,
-
- /**
- * The local session endpoint has been opened. Events of this type
- * point to the relevant session.
- */
- SESSION_LOCAL_OPEN=PN_SESSION_LOCAL_OPEN,
-
- /**
- * The remote endpoint has opened the session. Events of this type
- * point to the relevant session.
- */
- SESSION_REMOTE_OPEN=PN_SESSION_REMOTE_OPEN,
-
- /**
- * The local session endpoint has been closed. Events of this type
- * point ot the relevant session.
- */
- SESSION_LOCAL_CLOSE=PN_SESSION_LOCAL_CLOSE,
-
- /**
- * The remote endpoint has closed the session. Events of this type
- * point to the relevant session.
- */
- SESSION_REMOTE_CLOSE=PN_SESSION_REMOTE_CLOSE,
-
- /**
- * The session has been freed and any outstanding processing has
- * been completed. This is the final event that will ever be issued
- * for a session.
- */
- SESSION_FINAL=PN_SESSION_FINAL,
-
- /**
- * The link has been created. This is the first event that will ever
- * be issued for a link.
- */
- LINK_INIT=PN_LINK_INIT,
-
- /**
- * The local link endpoint has been opened. Events of this type
- * point ot the relevant link.
- */
- LINK_LOCAL_OPEN=PN_LINK_LOCAL_OPEN,
-
- /**
- * The remote endpoint has opened the link. Events of this type
- * point to the relevant link.
- */
- LINK_REMOTE_OPEN=PN_LINK_REMOTE_OPEN,
-
- /**
- * The local link endpoint has been closed. Events of this type
- * point ot the relevant link.
- */
- LINK_LOCAL_CLOSE=PN_LINK_LOCAL_CLOSE,
-
- /**
- * The remote endpoint has closed the link. Events of this type
- * point to the relevant link.
- */
- LINK_REMOTE_CLOSE=PN_LINK_REMOTE_CLOSE,
-
- /**
- * The local link endpoint has been detached. Events of this type
- * point to the relevant link.
- */
- LINK_LOCAL_DETACH=PN_LINK_LOCAL_DETACH,
-
- /**
- * The remote endpoint has detached the link. Events of this type
- * point to the relevant link.
- */
- LINK_REMOTE_DETACH=PN_LINK_REMOTE_DETACH,
-
- /**
- * The flow control state for a link has changed. Events of this
- * type point to the relevant link.
- */
- LINK_FLOW=PN_LINK_FLOW,
-
- /**
- * The link has been freed and any outstanding processing has been
- * completed. This is the final event that will ever be issued for a
- * link. Events of this type point to the relevant link.
- */
- LINK_FINAL=PN_LINK_FINAL,
-
- /**
- * A delivery has been created or updated. Events of this type point
- * to the relevant delivery.
- */
- DELIVERY=PN_DELIVERY,
-
- /**
- * The transport has new data to read and/or write. Events of this
- * type point to the relevant transport.
- */
- TRANSPORT=PN_TRANSPORT,
-
- /**
- * The transport has authenticated, if this is received by a server
- * the associated transport has authenticated an incoming connection
- * and transport::user() can be used to obtain the authenticated
- * user.
- */
- TRANSPORT_AUTHENTICATED=PN_TRANSPORT_AUTHENTICATED,
-
- /**
- * Indicates that a transport error has occurred. Use
- * transport::condition() to access the details of the error
- * from the associated transport.
- */
- TRANSPORT_ERROR=PN_TRANSPORT_ERROR,
-
- /**
- * Indicates that the head of the transport has been closed. This
- * means the transport will never produce more bytes for output to
- * the network. Events of this type point to the relevant transport.
- */
- TRANSPORT_HEAD_CLOSED=PN_TRANSPORT_HEAD_CLOSED,
-
- /**
- * Indicates that the tail of the transport has been closed. This
- * means the transport will never be able to process more bytes from
- * the network. Events of this type point to the relevant transport.
- */
- TRANSPORT_TAIL_CLOSED=PN_TRANSPORT_TAIL_CLOSED,
-
- /**
- * Indicates that the both the head and tail of the transport are
- * closed. Events of this type point to the relevant transport.
- */
- TRANSPORT_CLOSED=PN_TRANSPORT_CLOSED,
-
- SELECTABLE_INIT=PN_SELECTABLE_INIT,
- SELECTABLE_UPDATED=PN_SELECTABLE_UPDATED,
- SELECTABLE_READABLE=PN_SELECTABLE_READABLE,
- SELECTABLE_WRITABLE=PN_SELECTABLE_WRITABLE,
- SELECTABLE_ERROR=PN_SELECTABLE_ERROR,
- SELECTABLE_EXPIRED=PN_SELECTABLE_EXPIRED,
- SELECTABLE_FINAL=PN_SELECTABLE_FINAL
- };
- ///@}
-
- proton_event(pn_event_t *ce) :
- pn_event_(ce)
- {}
-
- pn_event_t* pn_event() const { return pn_event_; }
-
- /// Get type of event
- event_type type() const { return event_type(pn_event_type(pn_event_)); }
-
- void dispatch(proton_handler& h);
-
- private:
- pn_event_t *pn_event_;
-};
-
-}
-
-#endif /*!PROTON_CPP_PROTONEVENT_H*/
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1a513d64/proton-c/bindings/cpp/src/include/proton_handler.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proton_handler.hpp b/proton-c/bindings/cpp/src/include/proton_handler.hpp
deleted file mode 100644
index 9941396..0000000
--- a/proton-c/bindings/cpp/src/include/proton_handler.hpp
+++ /dev/null
@@ -1,92 +0,0 @@
-#ifndef PROTON_CPP_PROTONHANDLER_H
-#define PROTON_CPP_PROTONHANDLER_H
-
-/*
- *
- * 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 "proton/internal/object.hpp"
-
-#include <vector>
-
-struct pn_handler_t;
-
-namespace proton {
-
-class event;
-class proton_event;
-
-/// Handler base class, subclass and over-ride event handling member functions.
-/// @see proton::proton_event for meaning of events.
-class proton_handler
-{
- public:
- proton_handler();
- virtual ~proton_handler();
-
- ///@name Over-ride these member functions to handle events
- ///@{
- virtual void on_reactor_init(proton_event &e);
- virtual void on_reactor_quiesced(proton_event &e);
- virtual void on_reactor_final(proton_event &e);
- virtual void on_timer_task(proton_event &e);
- virtual void on_connection_init(proton_event &e);
- virtual void on_connection_bound(proton_event &e);
- virtual void on_connection_unbound(proton_event &e);
- virtual void on_connection_local_open(proton_event &e);
- virtual void on_connection_local_close(proton_event &e);
- virtual void on_connection_remote_open(proton_event &e);
- virtual void on_connection_remote_close(proton_event &e);
- virtual void on_connection_final(proton_event &e);
- virtual void on_session_init(proton_event &e);
- virtual void on_session_local_open(proton_event &e);
- virtual void on_session_local_close(proton_event &e);
- virtual void on_session_remote_open(proton_event &e);
- virtual void on_session_remote_close(proton_event &e);
- virtual void on_session_final(proton_event &e);
- virtual void on_link_init(proton_event &e);
- virtual void on_link_local_open(proton_event &e);
- virtual void on_link_local_close(proton_event &e);
- virtual void on_link_local_detach(proton_event &e);
- virtual void on_link_remote_open(proton_event &e);
- virtual void on_link_remote_close(proton_event &e);
- virtual void on_link_remote_detach(proton_event &e);
- virtual void on_link_flow(proton_event &e);
- virtual void on_link_final(proton_event &e);
- virtual void on_delivery(proton_event &e);
- virtual void on_transport(proton_event &e);
- virtual void on_transport_error(proton_event &e);
- virtual void on_transport_head_closed(proton_event &e);
- virtual void on_transport_tail_closed(proton_event &e);
- virtual void on_transport_closed(proton_event &e);
- virtual void on_selectable_init(proton_event &e);
- virtual void on_selectable_updated(proton_event &e);
- virtual void on_selectable_readable(proton_event &e);
- virtual void on_selectable_writable(proton_event &e);
- virtual void on_selectable_expired(proton_event &e);
- virtual void on_selectable_error(proton_event &e);
- virtual void on_selectable_final(proton_event &e);
- virtual void on_unhandled(proton_event &e);
- ///@}
-};
-
-}
-
-#endif /*!PROTON_CPP_PROTONHANDLER_H*/
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1a513d64/proton-c/bindings/cpp/src/io/connection_driver.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/io/connection_driver.cpp b/proton-c/bindings/cpp/src/io/connection_driver.cpp
index d7c5e5c..0f5bc33 100644
--- a/proton-c/bindings/cpp/src/io/connection_driver.cpp
+++ b/proton-c/bindings/cpp/src/io/connection_driver.cpp
@@ -28,7 +28,6 @@
#include "messaging_adapter.hpp"
#include "msg.hpp"
#include "proton_bits.hpp"
-#include "proton_event.hpp"
#include <proton/connection.h>
#include <proton/transport.h>
@@ -88,11 +87,9 @@ bool connection_driver::has_events() const {
bool connection_driver::dispatch() {
pn_event_t* c_event;
while ((c_event = pn_connection_driver_next_event(&driver_)) != NULL) {
- proton_event cpp_event(c_event);
try {
if (handler_ != 0) {
- messaging_adapter adapter(*handler_);
- cpp_event.dispatch(adapter);
+ messaging_adapter::dispatch(*handler_, c_event);
}
} catch (const std::exception& e) {
pn_condition_t *cond = pn_transport_condition(driver_.transport);
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1a513d64/proton-c/bindings/cpp/src/message.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/message.cpp b/proton-c/bindings/cpp/src/message.cpp
index d121cc8..1fbdf70 100644
--- a/proton-c/bindings/cpp/src/message.cpp
+++ b/proton-c/bindings/cpp/src/message.cpp
@@ -300,20 +300,6 @@ void message::decode(const std::vector<char> &s) {
check(pn_message_decode(pn_msg(), &s[0], s.size()));
}
-void message::decode(proton::delivery delivery) {
- std::vector<char> buf;
- buf.resize(pn_delivery_pending(unwrap(delivery)));
- if (buf.empty())
- throw error("message decode: no delivery pending on link");
- proton::receiver link = delivery.receiver();
- assert(!buf.empty());
- ssize_t n = pn_link_recv(unwrap(link), const_cast<char *>(&buf[0]), buf.size());
- if (n != ssize_t(buf.size())) throw error(MSG("receiver read failure"));
- clear();
- decode(buf);
- pn_link_advance(unwrap(link));
-}
-
bool message::durable() const { return pn_message_is_durable(pn_msg()); }
void message::durable(bool b) { pn_message_set_durable(pn_msg(), b); }
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1a513d64/proton-c/bindings/cpp/src/messaging_adapter.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/messaging_adapter.cpp b/proton-c/bindings/cpp/src/messaging_adapter.cpp
index 613808b..3a16930 100644
--- a/proton-c/bindings/cpp/src/messaging_adapter.cpp
+++ b/proton-c/bindings/cpp/src/messaging_adapter.cpp
@@ -23,6 +23,7 @@
#include "proton/delivery.hpp"
#include "proton/error.hpp"
+#include "proton/messaging_handler.hpp"
#include "proton/receiver_options.hpp"
#include "proton/sender.hpp"
#include "proton/sender_options.hpp"
@@ -32,7 +33,6 @@
#include "contexts.hpp"
#include "msg.hpp"
#include "proton_bits.hpp"
-#include "proton_event.hpp"
#include <proton/connection.h>
#include <proton/delivery.h>
@@ -42,62 +42,71 @@
#include <proton/session.h>
#include <proton/transport.h>
+#include <assert.h>
#include <string.h>
namespace proton {
namespace {
+// This must only be called for receiver links
void credit_topup(pn_link_t *link) {
- if (link && pn_link_is_receiver(link)) {
- int window = link_context::get(link).credit_window;
- if (window) {
- int delta = window - pn_link_credit(link);
- pn_link_flow(link, delta);
- }
+ assert(pn_link_is_receiver(link));
+ int window = link_context::get(link).credit_window;
+ if (window) {
+ int delta = window - pn_link_credit(link);
+ pn_link_flow(link, delta);
}
}
-}
-void messaging_adapter::on_link_flow(proton_event &pe) {
- pn_event_t *pne = pe.pn_event();
- pn_link_t *lnk = pn_event_link(pne);
+
+void on_link_flow(messaging_handler& handler, pn_event_t* event) {
+ pn_link_t *lnk = pn_event_link(event);
// TODO: process session flow data, if no link-specific data, just return.
if (!lnk) return;
- link_context& lctx = link_context::get(lnk);
int state = pn_link_state(lnk);
if ((state&PN_LOCAL_ACTIVE) && (state&PN_REMOTE_ACTIVE)) {
+ link_context& lctx = link_context::get(lnk);
if (pn_link_is_sender(lnk)) {
if (pn_link_credit(lnk) > 0) {
sender s(make_wrapper<sender>(lnk));
- if (pn_link_get_drain(lnk)) {
- if (!lctx.draining) {
- lctx.draining = true;
- delegate_.on_sender_drain_start(s);
- }
- }
- else {
- lctx.draining = false;
+ bool draining = pn_link_get_drain(lnk);
+ if ( draining && !lctx.draining) {
+ handler.on_sender_drain_start(s);
}
+ lctx.draining = draining;
// create on_message extended event
- delegate_.on_sendable(s);
+ handler.on_sendable(s);
}
- }
- else {
+ } else {
// receiver
if (!pn_link_credit(lnk) && lctx.draining) {
lctx.draining = false;
receiver r(make_wrapper<receiver>(lnk));
- delegate_.on_receiver_drain_finish(r);
+ handler.on_receiver_drain_finish(r);
}
+ credit_topup(lnk);
}
}
- credit_topup(lnk);
}
-void messaging_adapter::on_delivery(proton_event &pe) {
- pn_event_t *cevent = pe.pn_event();
- pn_link_t *lnk = pn_event_link(cevent);
- pn_delivery_t *dlv = pn_event_delivery(cevent);
+// Decode the message corresponding to a delivery from a link.
+void message_decode(message& msg, proton::delivery delivery) {
+ std::vector<char> buf;
+ buf.resize(pn_delivery_pending(unwrap(delivery)));
+ if (buf.empty())
+ throw error("message decode: no delivery pending on link");
+ proton::receiver link = delivery.receiver();
+ assert(!buf.empty());
+ ssize_t n = pn_link_recv(unwrap(link), const_cast<char *>(&buf[0]), buf.size());
+ if (n != ssize_t(buf.size())) throw error(MSG("receiver read failure"));
+ msg.clear();
+ msg.decode(buf);
+ pn_link_advance(unwrap(link));
+}
+
+void on_delivery(messaging_handler& handler, pn_event_t* event) {
+ pn_link_t *lnk = pn_event_link(event);
+ pn_delivery_t *dlv = pn_event_delivery(event);
link_context& lctx = link_context::get(lnk);
if (pn_link_is_receiver(lnk)) {
@@ -110,29 +119,29 @@ void messaging_adapter::on_delivery(proton_event &pe) {
// Avoid expensive heap malloc/free overhead.
// See PROTON-998
class message &msg(ctx.event_message);
- msg.decode(d);
+ message_decode(msg, d);
if (pn_link_state(lnk) & PN_LOCAL_CLOSED) {
if (lctx.auto_accept)
d.release();
} else {
- delegate_.on_message(d, msg);
+ handler.on_message(d, msg);
if (lctx.auto_accept && !d.settled())
d.accept();
if (lctx.draining && !pn_link_credit(lnk)) {
lctx.draining = false;
receiver r(make_wrapper<receiver>(lnk));
- delegate_.on_receiver_drain_finish(r);
+ handler.on_receiver_drain_finish(r);
}
}
}
else if (pn_delivery_updated(dlv) && d.settled()) {
- delegate_.on_delivery_settle(d);
+ handler.on_delivery_settle(d);
}
if (lctx.draining && pn_link_credit(lnk) == 0) {
lctx.draining = false;
pn_link_set_drain(lnk, false);
receiver r(make_wrapper<receiver>(lnk));
- delegate_.on_receiver_drain_finish(r);
+ handler.on_receiver_drain_finish(r);
if (lctx.pending_credit) {
pn_link_flow(lnk, lctx.pending_credit);
lctx.pending_credit = 0;
@@ -145,17 +154,17 @@ void messaging_adapter::on_delivery(proton_event &pe) {
if (pn_delivery_updated(dlv)) {
uint64_t rstate = pn_delivery_remote_state(dlv);
if (rstate == PN_ACCEPTED) {
- delegate_.on_tracker_accept(t);
+ handler.on_tracker_accept(t);
}
else if (rstate == PN_REJECTED) {
- delegate_.on_tracker_reject(t);
+ handler.on_tracker_reject(t);
}
else if (rstate == PN_RELEASED || rstate == PN_MODIFIED) {
- delegate_.on_tracker_release(t);
+ handler.on_tracker_release(t);
}
if (t.settled()) {
- delegate_.on_tracker_settle(t);
+ handler.on_tracker_settle(t);
}
if (lctx.auto_settle)
t.settle();
@@ -163,8 +172,6 @@ void messaging_adapter::on_delivery(proton_event &pe) {
}
}
-namespace {
-
bool is_local_open(pn_state_t state) {
return state & PN_LOCAL_ACTIVE;
}
@@ -177,54 +184,48 @@ bool is_remote_unititialised(pn_state_t state) {
return state & PN_REMOTE_UNINIT;
}
-} // namespace
-
-void messaging_adapter::on_link_remote_detach(proton_event & pe) {
- pn_event_t *cevent = pe.pn_event();
- pn_link_t *lnk = pn_event_link(cevent);
+void on_link_remote_detach(messaging_handler& handler, pn_event_t* event) {
+ pn_link_t *lnk = pn_event_link(event);
if (pn_link_is_receiver(lnk)) {
receiver r(make_wrapper<receiver>(lnk));
- delegate_.on_receiver_detach(r);
+ handler.on_receiver_detach(r);
} else {
sender s(make_wrapper<sender>(lnk));
- delegate_.on_sender_detach(s);
+ handler.on_sender_detach(s);
}
pn_link_detach(lnk);
}
-void messaging_adapter::on_link_remote_close(proton_event &pe) {
- pn_event_t *cevent = pe.pn_event();
- pn_link_t *lnk = pn_event_link(cevent);
+void on_link_remote_close(messaging_handler& handler, pn_event_t* event) {
+ pn_link_t *lnk = pn_event_link(event);
if (pn_link_is_receiver(lnk)) {
receiver r(make_wrapper<receiver>(lnk));
if (pn_condition_is_set(pn_link_remote_condition(lnk))) {
- delegate_.on_receiver_error(r);
+ handler.on_receiver_error(r);
}
- delegate_.on_receiver_close(r);
+ handler.on_receiver_close(r);
} else {
sender s(make_wrapper<sender>(lnk));
if (pn_condition_is_set(pn_link_remote_condition(lnk))) {
- delegate_.on_sender_error(s);
+ handler.on_sender_error(s);
}
- delegate_.on_sender_close(s);
+ handler.on_sender_close(s);
}
pn_link_close(lnk);
}
-void messaging_adapter::on_session_remote_close(proton_event &pe) {
- pn_event_t *cevent = pe.pn_event();
- pn_session_t *session = pn_event_session(cevent);
+void on_session_remote_close(messaging_handler& handler, pn_event_t* event) {
+ pn_session_t *session = pn_event_session(event);
class session s(make_wrapper(session));
if (pn_condition_is_set(pn_session_remote_condition(session))) {
- delegate_.on_session_error(s);
+ handler.on_session_error(s);
}
- delegate_.on_session_close(s);
+ handler.on_session_close(s);
pn_session_close(session);
}
-void messaging_adapter::on_connection_remote_close(proton_event &pe) {
- pn_event_t *cevent = pe.pn_event();
- pn_connection_t *conn = pn_event_connection(cevent);
+void on_connection_remote_close(messaging_handler& handler, pn_event_t* event) {
+ pn_connection_t *conn = pn_event_connection(event);
pn_condition_t *cond = pn_connection_remote_condition(conn);
// If we got a close with a condition of amqp:connection:forced then treat this
@@ -237,71 +238,108 @@ void messaging_adapter::on_connection_remote_close(proton_event &pe) {
connection c(make_wrapper(conn));
if (pn_condition_is_set(cond)) {
- delegate_.on_connection_error(c);
+ handler.on_connection_error(c);
}
- delegate_.on_connection_close(c);
+ handler.on_connection_close(c);
pn_connection_close(conn);
}
-void messaging_adapter::on_connection_remote_open(proton_event &pe) {
+void on_connection_remote_open(messaging_handler& handler, pn_event_t* event) {
// Generate on_transport_open event here until we find a better place
- transport t(make_wrapper(pn_event_transport(pe.pn_event())));
- delegate_.on_transport_open(t);
+ transport t(make_wrapper(pn_event_transport(event)));
+ handler.on_transport_open(t);
- pn_connection_t *conn = pn_event_connection(pe.pn_event());
+ pn_connection_t *conn = pn_event_connection(event);
connection c(make_wrapper(conn));
- delegate_.on_connection_open(c);
+ handler.on_connection_open(c);
if (!is_local_open(pn_connection_state(conn)) && is_local_unititialised(pn_connection_state(conn))) {
pn_connection_open(conn);
}
}
-void messaging_adapter::on_session_remote_open(proton_event &pe) {
- pn_session_t *session = pn_event_session(pe.pn_event());
+void on_session_remote_open(messaging_handler& handler, pn_event_t* event) {
+ pn_session_t *session = pn_event_session(event);
class session s(make_wrapper(session));
- delegate_.on_session_open(s);
+ handler.on_session_open(s);
if (!is_local_open(pn_session_state(session)) && is_local_unititialised(pn_session_state(session))) {
pn_session_open(session);
}
}
-void messaging_adapter::on_link_local_open(proton_event &pe) {
- credit_topup(pn_event_link(pe.pn_event()));
+void on_link_local_open(messaging_handler& handler, pn_event_t* event) {
+ pn_link_t* lnk = pn_event_link(event);
+ if ( pn_link_is_receiver(lnk) ) {
+ credit_topup(lnk);
+ // We know local is active so don't check for it
+ } else if ( pn_link_state(lnk)&PN_REMOTE_ACTIVE && pn_link_credit(lnk) > 0) {
+ sender s(make_wrapper<sender>(lnk));
+ handler.on_sendable(s);
+ }
}
-void messaging_adapter::on_link_remote_open(proton_event &pe) {
- pn_link_t *lnk = pn_event_link(pe.pn_event());
+void on_link_remote_open(messaging_handler& handler, pn_event_t* event) {
+ pn_link_t *lnk = pn_event_link(event);
if (pn_link_is_receiver(lnk)) {
receiver r(make_wrapper<receiver>(lnk));
- delegate_.on_receiver_open(r);
+ handler.on_receiver_open(r);
if (is_local_unititialised(pn_link_state(lnk))) {
r.open(r.connection().receiver_options());
}
+ credit_topup(lnk);
} else {
sender s(make_wrapper<sender>(lnk));
- delegate_.on_sender_open(s);
+ handler.on_sender_open(s);
if (is_local_unititialised(pn_link_state(lnk))) {
s.open(s.connection().sender_options());
}
}
- credit_topup(lnk);
}
-void messaging_adapter::on_transport_closed(proton_event &pe) {
- pn_transport_t *tspt = pn_event_transport(pe.pn_event());
+void on_transport_closed(messaging_handler& handler, pn_event_t* event) {
+ pn_transport_t *tspt = pn_event_transport(event);
transport t(make_wrapper(tspt));
// If the connection isn't open generate on_transport_open event
// because we didn't generate it yet and the events won't match.
- pn_connection_t *conn = pn_event_connection(pe.pn_event());
+ pn_connection_t *conn = pn_event_connection(event);
if (!conn || is_remote_unititialised(pn_connection_state(conn))) {
- delegate_.on_transport_open(t);
+ handler.on_transport_open(t);
}
if (pn_condition_is_set(pn_transport_condition(tspt))) {
- delegate_.on_transport_error(t);
+ handler.on_transport_error(t);
+ }
+ handler.on_transport_close(t);
+}
+
+}
+
+void messaging_adapter::dispatch(messaging_handler& handler, pn_event_t* event)
+{
+ pn_event_type_t type = pn_event_type(event);
+
+ // Only handle events we are interested in
+ switch(type) {
+
+ case PN_CONNECTION_REMOTE_OPEN: on_connection_remote_open(handler, event); break;
+ case PN_CONNECTION_REMOTE_CLOSE: on_connection_remote_close(handler, event); break;
+
+ case PN_SESSION_REMOTE_OPEN: on_session_remote_open(handler, event); break;
+ case PN_SESSION_REMOTE_CLOSE: on_session_remote_close(handler, event); break;
+
+ case PN_LINK_LOCAL_OPEN: on_link_local_open(handler, event); break;
+ case PN_LINK_REMOTE_OPEN: on_link_remote_open(handler, event); break;
+ case PN_LINK_REMOTE_CLOSE: on_link_remote_close(handler, event); break;
+ case PN_LINK_REMOTE_DETACH: on_link_remote_detach(handler, event); break;
+ case PN_LINK_FLOW: on_link_flow(handler, event); break;
+
+ case PN_DELIVERY: on_delivery(handler, event); break;
+
+ case PN_TRANSPORT_CLOSED: on_transport_closed(handler, event); break;
+
+ // Ignore everything else
+ default: break;
}
- delegate_.on_transport_close(t);
}
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1a513d64/proton-c/bindings/cpp/src/proactor_container_impl.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proactor_container_impl.cpp b/proton-c/bindings/cpp/src/proactor_container_impl.cpp
index 2b6b1de..2486e2b 100644
--- a/proton-c/bindings/cpp/src/proactor_container_impl.cpp
+++ b/proton-c/bindings/cpp/src/proactor_container_impl.cpp
@@ -35,7 +35,6 @@
#include "contexts.hpp"
#include "messaging_adapter.hpp"
#include "proton_bits.hpp"
-#include "proton_event.hpp"
#include <assert.h>
@@ -377,10 +376,7 @@ bool container::impl::handle(pn_event_t* event) {
// This is pretty unusual, but possible if we use the default constructor for container
if (!mh) return false;
- // TODO: Currently create a throwaway messaging_adapter and proton_event so we can call dispatch, a bit inefficient
- messaging_adapter ma(*mh);
- proton_event pe(event);
- pe.dispatch(ma);
+ messaging_adapter::dispatch(*mh, event);
return false;
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1a513d64/proton-c/bindings/cpp/src/proton_event.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proton_event.cpp b/proton-c/bindings/cpp/src/proton_event.cpp
deleted file mode 100644
index 9a1ffea..0000000
--- a/proton-c/bindings/cpp/src/proton_event.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- *
- * 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 "proton_event.hpp"
-
-#include "proton/error.hpp"
-
-#include "msg.hpp"
-#include "proton_handler.hpp"
-#include "types_internal.hpp"
-
-namespace proton {
-
-void proton_event::dispatch(proton_handler &handler) {
- pn_event_type_t type = pn_event_type(pn_event_);
- switch(type) {
-
- case PN_REACTOR_INIT: handler.on_reactor_init(*this); break;
- case PN_REACTOR_QUIESCED: handler.on_reactor_quiesced(*this); break;
- case PN_REACTOR_FINAL: handler.on_reactor_final(*this); break;
-
- case PN_TIMER_TASK: handler.on_timer_task(*this); break;
-
- case PN_CONNECTION_INIT: handler.on_connection_init(*this); break;
- case PN_CONNECTION_BOUND: handler.on_connection_bound(*this); break;
- case PN_CONNECTION_UNBOUND: handler.on_connection_unbound(*this); break;
- case PN_CONNECTION_LOCAL_OPEN: handler.on_connection_local_open(*this); break;
- case PN_CONNECTION_LOCAL_CLOSE: handler.on_connection_local_close(*this); break;
- case PN_CONNECTION_REMOTE_OPEN: handler.on_connection_remote_open(*this); break;
- case PN_CONNECTION_REMOTE_CLOSE: handler.on_connection_remote_close(*this); break;
- case PN_CONNECTION_FINAL: handler.on_connection_final(*this); break;
-
- case PN_SESSION_INIT: handler.on_session_init(*this); break;
- case PN_SESSION_LOCAL_OPEN: handler.on_session_local_open(*this); break;
- case PN_SESSION_LOCAL_CLOSE: handler.on_session_local_close(*this); break;
- case PN_SESSION_REMOTE_OPEN: handler.on_session_remote_open(*this); break;
- case PN_SESSION_REMOTE_CLOSE: handler.on_session_remote_close(*this); break;
- case PN_SESSION_FINAL: handler.on_session_final(*this); break;
-
- case PN_LINK_INIT: handler.on_link_init(*this); break;
- case PN_LINK_LOCAL_OPEN: handler.on_link_local_open(*this); break;
- case PN_LINK_LOCAL_CLOSE: handler.on_link_local_close(*this); break;
- case PN_LINK_LOCAL_DETACH: handler.on_link_local_detach(*this); break;
- case PN_LINK_REMOTE_OPEN: handler.on_link_remote_open(*this); break;
- case PN_LINK_REMOTE_CLOSE: handler.on_link_remote_close(*this); break;
- case PN_LINK_REMOTE_DETACH: handler.on_link_remote_detach(*this); break;
- case PN_LINK_FLOW: handler.on_link_flow(*this); break;
- case PN_LINK_FINAL: handler.on_link_final(*this); break;
-
- case PN_DELIVERY: handler.on_delivery(*this); break;
-
- case PN_TRANSPORT: handler.on_transport(*this); break;
- case PN_TRANSPORT_ERROR: handler.on_transport_error(*this); break;
- case PN_TRANSPORT_HEAD_CLOSED: handler.on_transport_head_closed(*this); break;
- case PN_TRANSPORT_TAIL_CLOSED: handler.on_transport_tail_closed(*this); break;
- case PN_TRANSPORT_CLOSED: handler.on_transport_closed(*this); break;
-
- case PN_SELECTABLE_INIT: handler.on_selectable_init(*this); break;
- case PN_SELECTABLE_UPDATED: handler.on_selectable_updated(*this); break;
- case PN_SELECTABLE_READABLE: handler.on_selectable_readable(*this); break;
- case PN_SELECTABLE_WRITABLE: handler.on_selectable_writable(*this); break;
- case PN_SELECTABLE_EXPIRED: handler.on_selectable_expired(*this); break;
- case PN_SELECTABLE_ERROR: handler.on_selectable_error(*this); break;
- case PN_SELECTABLE_FINAL: handler.on_selectable_final(*this); break;
- default:
- throw error(MSG("Invalid Proton event type " << type));
- }
-}
-
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1a513d64/proton-c/bindings/cpp/src/proton_handler.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proton_handler.cpp b/proton-c/bindings/cpp/src/proton_handler.cpp
deleted file mode 100644
index 87d00a3..0000000
--- a/proton-c/bindings/cpp/src/proton_handler.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- *
- * 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 "proton_handler.hpp"
-#include "proton_event.hpp"
-
-namespace proton {
-
-proton_handler::proton_handler() {}
-proton_handler::~proton_handler() {}
-
-// Everything goes to on_unhandled() unless overriden by subclass
-
-void proton_handler::on_reactor_init(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_reactor_quiesced(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_reactor_final(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_timer_task(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_connection_init(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_connection_bound(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_connection_unbound(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_connection_local_open(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_connection_local_close(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_connection_remote_open(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_connection_remote_close(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_connection_final(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_session_init(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_session_local_open(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_session_local_close(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_session_remote_open(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_session_remote_close(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_session_final(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_link_init(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_link_local_open(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_link_local_close(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_link_local_detach(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_link_remote_open(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_link_remote_close(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_link_remote_detach(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_link_flow(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_link_final(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_delivery(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_transport(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_transport_error(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_transport_head_closed(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_transport_tail_closed(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_transport_closed(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_selectable_init(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_selectable_updated(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_selectable_readable(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_selectable_writable(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_selectable_expired(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_selectable_error(proton_event &e) { on_unhandled(e); }
-void proton_handler::on_selectable_final(proton_event &e) { on_unhandled(e); }
-
-void proton_handler::on_unhandled(proton_event &) {}
-
-}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[15/20] qpid-proton git commit: PROTON-1481: [C++ binding] Split out
general work deferring functions to the work_queue header Add efficient C++11
versions of work factories Reorder defer arguments to be like std::bind Add
extra overloads for defer like
Posted by as...@apache.org.
PROTON-1481: [C++ binding] Split out general work deferring functions to the work_queue header
Add efficient C++11 versions of work factories
Reorder defer arguments to be like std::bind
Add extra overloads for defer like std::bind (for free functions arbitrary work_queues)
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/efc899fb
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/efc899fb
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/efc899fb
Branch: refs/heads/master
Commit: efc899fb377611fcf9cf26280a2025c980bb0bf2
Parents: 5dd3f46
Author: Andrew Stitcher <as...@apache.org>
Authored: Mon May 15 01:45:43 2017 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
examples/cpp/broker.cpp | 110 ++--------
.../bindings/cpp/include/proton/work_queue.hpp | 210 +++++++++++++++++++
2 files changed, 222 insertions(+), 98 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/efc899fb/examples/cpp/broker.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/broker.cpp b/examples/cpp/broker.cpp
index 9af60ba..a1ef3a5 100644
--- a/examples/cpp/broker.cpp
+++ b/examples/cpp/broker.cpp
@@ -70,92 +70,6 @@
// SendMsg(msg) - From a Queue to a Connection (sender)
// Unsubscribed() - From a Queue to a Connection (sender)
-// Utilities to make injecting member functions palatable in C++03
-template <class T>
-struct work0 : public proton::void_function0 {
- T& holder_;
- void (T::* fn_)();
-
- work0(T& h, void (T::* a)()) :
- holder_(h), fn_(a) {}
-
- void operator()() OVERRIDE {
- (holder_.*fn_)();
- delete this;
- }
-};
-
-template <class T, class A>
-struct work1 : public proton::void_function0 {
- T& holder_;
- void (T::* fn_)(A);
- A a_;
-
- work1(T& h, void (T::* t)(A), A a) :
- holder_(h), fn_(t), a_(a) {}
-
- void operator()() OVERRIDE {
- (holder_.*fn_)(a_);
- delete this;
- }
-};
-
-template <class T, class A, class B>
-struct work2 : public proton::void_function0 {
- T& holder_;
- void (T::* fn_)(A, B);
- A a_;
- B b_;
-
- work2(T& h, void (T::* t)(A, B), A a, B b) :
- holder_(h), fn_(t), a_(a), b_(b) {}
-
- void operator()() OVERRIDE {
- (holder_.*fn_)(a_, b_);
- delete this;
- }
-};
-
-template <class T, class A, class B, class C>
-struct work3 : public proton::void_function0 {
- T& holder_;
- void (T::* fn_)(A, B, C);
- A a_;
- B b_;
- C c_;
-
- work3(T& h, void (T::* t)(A, B, C), A a, B b, C c) :
- holder_(h), fn_(t), a_(a), b_(b), c_(c) {}
-
- void operator()() OVERRIDE {
- (holder_.*fn_)(a_, b_, c_);
- delete this;
- }
-};
-
-template <class T>
-void defer(T* t, void (T::*f)()) {
- work0<T>* w = new work0<T>(*t, f);
- t->add(*w);
-}
-
-template <class T, class A>
-void defer(T* t, void (T::*f)(A), A a) {
- work1<T, A>* w = new work1<T, A>(*t, f, a);
- t->add(*w);
-}
-
-template <class T, class A, class B>
-void defer(T* t, void (T::*f)(A, B), A a, B b) {
- work2<T, A, B>* w = new work2<T, A, B>(*t, f, a, b);
- t->add(*w);
-}
-
-template <class T, class A, class B, class C>
-void defer(T* t, void (T::*f)(A, B, C), A a, B b, C c) {
- work3<T, A, B, C>* w = new work3<T, A, B, C>(*t, f, a, b, c);
- t->add(*w);
-}
// Simple debug output
bool verbose;
@@ -225,7 +139,7 @@ class Queue {
DOUT(std::cerr << "(" << current_->second << ") ";);
if (current_->second>0) {
DOUT(std::cerr << current_->first << " ";);
- defer(current_->first, &Sender::sendMsg, messages_.front());
+ proton::defer(&Sender::sendMsg, current_->first, messages_.front());
messages_.pop_front();
--current_->second;
++current_;
@@ -264,14 +178,14 @@ public:
// If we're about to erase the current subscription move on
if (current_ != subscriptions_.end() && current_->first==s) ++current_;
subscriptions_.erase(s);
- defer(s, &Sender::unsubscribed);
+ proton::defer(&Sender::unsubscribed, s);
}
};
// We have credit to send a message.
void Sender::on_sendable(proton::sender &sender) {
if (queue_) {
- defer(queue_, &Queue::flow, this, sender.credit());
+ proton::defer(&Queue::flow, queue_, this, sender.credit());
} else {
pending_credit_ = sender.credit();
}
@@ -279,7 +193,7 @@ void Sender::on_sendable(proton::sender &sender) {
void Sender::on_sender_close(proton::sender &sender) {
if (queue_) {
- defer(queue_, &Queue::unsubscribe, this);
+ proton::defer(&Queue::unsubscribe, queue_, this);
} else {
// TODO: Is it possible to be closed before we get the queue allocated?
// If so, we should have a way to mark the sender deleted, so we can delete
@@ -293,12 +207,12 @@ void Sender::boundQueue(Queue* q, std::string qn) {
queue_ = q;
queue_name_ = qn;
- defer(q, &Queue::subscribe, this);
+ proton::defer(&Queue::subscribe, q, this);
sender_.open(proton::sender_options()
.source((proton::source_options().address(queue_name_)))
.handler(*this));
if (pending_credit_>0) {
- defer(queue_, &Queue::flow, this, pending_credit_);
+ proton::defer(&Queue::flow, queue_, this, pending_credit_);
}
std::cout << "sending from " << queue_name_ << std::endl;
}
@@ -323,7 +237,7 @@ class Receiver : public proton::messaging_handler {
void queueMsgs() {
DOUT(std::cerr << "Receiver: " << this << " queueing " << messages_.size() << " msgs to: " << queue_ << "\n";);
while (!messages_.empty()) {
- defer(queue_, &Queue::queueMsg, messages_.front());
+ proton::defer(&Queue::queueMsg, queue_, messages_.front());
messages_.pop_front();
}
}
@@ -381,7 +295,7 @@ public:
} else {
q = i->second;
}
- defer(&connection, &T::boundQueue, q, qn);
+ proton::defer(&T::boundQueue, &connection, q, qn);
}
void findQueueSender(Sender* s, std::string qn) {
@@ -411,7 +325,7 @@ public:
std::string qn = sender.source().dynamic() ? "" : sender.source().address();
Sender* s = new Sender(sender, senders_);
senders_[sender] = s;
- defer(&queue_manager_, &QueueManager::findQueueSender, s, qn);
+ proton::defer(&QueueManager::findQueueSender, &queue_manager_, s, qn);
}
// A receiver receives messages from a publisher to a queue.
@@ -427,7 +341,7 @@ public:
DOUT(std::cerr << "ODD - trying to attach to a empty address\n";);
}
Receiver* r = new Receiver(receiver);
- defer(&queue_manager_, &QueueManager::findQueueReceiver, r, qname);
+ proton::defer(&QueueManager::findQueueReceiver, &queue_manager_, r, qname);
}
}
@@ -438,7 +352,7 @@ public:
if (j == senders_.end()) continue;
Sender* s = j->second;
if (s->queue_) {
- defer(s->queue_, &Queue::unsubscribe, s);
+ proton::defer(&Queue::unsubscribe, s->queue_, s);
}
senders_.erase(j);
}
@@ -456,7 +370,7 @@ public:
if (j == senders_.end()) continue;
Sender* s = j->second;
if (s->queue_) {
- defer(s->queue_, &Queue::unsubscribe, s);
+ proton::defer(&Queue::unsubscribe, s->queue_, s);
}
}
delete this; // All done.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/efc899fb/proton-c/bindings/cpp/include/proton/work_queue.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/work_queue.hpp b/proton-c/bindings/cpp/include/proton/work_queue.hpp
index 7c21710..1937e11 100644
--- a/proton-c/bindings/cpp/include/proton/work_queue.hpp
+++ b/proton-c/bindings/cpp/include/proton/work_queue.hpp
@@ -117,6 +117,216 @@ class PN_CPP_CLASS_EXTERN work_queue {
/// @endcond
};
+// Utilities to make injecting functions/member functions palatable in C++03
+// Lots of repetition to handle functions with up to 3 arguments
+#if !PN_CPP_HAS_CPP11
+struct work0 : public proton::void_function0 {
+ void (* fn_)();
+
+ work0(void (* f)()) :
+ fn_(f) {}
+
+ void operator()() {
+ (*fn_)();
+ delete this;
+ }
+};
+
+template <class A>
+struct work1 : public proton::void_function0 {
+ void (* fn_)(A);
+ A a_;
+
+ work1(void (* t)(A), A a) :
+ fn_(t), a_(a) {}
+
+ void operator()() {
+ (*fn_)(a_);
+ delete this;
+ }
+};
+
+template <class A, class B>
+struct work2 : public proton::void_function0 {
+ void (* fn_)(A, B);
+ A a_;
+ B b_;
+
+ work2(void (* t)(A, B), A a, B b) :
+ fn_(t), a_(a), b_(b) {}
+
+ void operator()() {
+ (*fn_)(a_, b_);
+ delete this;
+ }
+};
+
+template <class A, class B, class C>
+struct work3 : public proton::void_function0 {
+ void (* fn_)(A, B, C);
+ A a_;
+ B b_;
+ C c_;
+
+ work3(void (* t)(A, B, C), A a, B b, C c) :
+ fn_(t), a_(a), b_(b), c_(c) {}
+
+ void operator()() {
+ (*fn_)(a_, b_, c_);
+ delete this;
+ }
+};
+
+template <class T>
+struct work_pmf0 : public proton::void_function0 {
+ T& holder_;
+ void (T::* fn_)();
+
+ work_pmf0(void (T::* a)(), T& h) :
+ holder_(h), fn_(a) {}
+
+ void operator()() {
+ (holder_.*fn_)();
+ delete this;
+ }
+};
+
+template <class T, class A>
+struct work_pmf1 : public proton::void_function0 {
+ T& holder_;
+ void (T::* fn_)(A);
+ A a_;
+
+ work_pmf1(void (T::* t)(A), T& h, A a) :
+ holder_(h), fn_(t), a_(a) {}
+
+ void operator()() {
+ (holder_.*fn_)(a_);
+ delete this;
+ }
+};
+
+template <class T, class A, class B>
+struct work_pmf2 : public proton::void_function0 {
+ T& holder_;
+ void (T::* fn_)(A, B);
+ A a_;
+ B b_;
+
+ work_pmf2(void (T::* t)(A, B), T& h, A a, B b) :
+ holder_(h), fn_(t), a_(a), b_(b) {}
+
+ void operator()() {
+ (holder_.*fn_)(a_, b_);
+ delete this;
+ }
+};
+
+template <class T, class A, class B, class C>
+struct work_pmf3 : public proton::void_function0 {
+ T& holder_;
+ void (T::* fn_)(A, B, C);
+ A a_;
+ B b_;
+ C c_;
+
+ work_pmf3(void (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_);
+ delete this;
+ }
+};
+
+/// This version of proton::defer defers calling an object's member function to the object's work queue
+template <class T>
+void defer(void (T::*f)(), T* t) {
+ work_pmf0<T>* w = new work_pmf0<T>(f, *t);
+ t->add(*w);
+}
+
+template <class T, class A>
+void defer(void (T::*f)(A), T* t, A a) {
+ work_pmf1<T, A>* w = new work_pmf1<T, A>(f, *t, a);
+ t->add(*w);
+}
+
+template <class T, class A, class B>
+void defer(void (T::*f)(A, B), T* t, A a, B b) {
+ work_pmf2<T, A, B>* w = new work_pmf2<T, A, B>(f, *t, a, b);
+ t->add(*w);
+}
+
+template <class T, class A, class B, class C>
+void defer(void (T::*f)(A, B, C), T* t, A a, B b, C c) {
+ work_pmf3<T, A, B, C>* w = new work_pmf3<T, A, B, C>(f, *t, a, b, c);
+ t->add(*w);
+}
+
+/// This version of proton::defer defers calling a member function to an arbitrary work queue
+template <class T, class U>
+void defer(U* wq, void (T::*f)(), T* t) {
+ work_pmf0<T>* w = new work_pmf0<T>(f, *t);
+ wq->add(*w);
+}
+
+template <class T, class U, class A>
+void defer(U* wq, void (T::*f)(A), T* t, A a) {
+ work_pmf1<T, A>* w = new work_pmf1<T, A>(f, *t, a);
+ wq->add(*w);
+}
+
+template <class T, class U, class A, class B>
+void defer(U* wq, void (T::*f)(A, B), T* t, A a, B b) {
+ work_pmf2<T, A, B>* w = new work_pmf2<T, A, B>(f, *t, a, b);
+ wq->add(*w);
+}
+
+template <class T, class U, class A, class B, class C>
+void defer(U* wq, void (T::*f)(A, B, C), T* t, A a, B b, C c) {
+ work_pmf3<T, A, B, C>* w = new work_pmf3<T, A, B, C>(f, *t, a, b, c);
+ wq->add(*w);
+}
+
+/// This version of proton::defer defers calling a free function to an arbitrary work queue
+template <class U>
+void defer(U* wq, void (*f)()) {
+ work0* w = new work0(f);
+ wq->add(*w);
+}
+
+template <class U, class A>
+void defer(U* wq, void (*f)(A), A a) {
+ work1<A>* w = new work1<A>(f, a);
+ wq->add(*w);
+}
+
+template <class U, class A, class B>
+void defer(U* wq, void (*f)(A, B), A a, B b) {
+ work2<A, B>* w = new work2<A, B>(f, a, b);
+ wq->add(*w);
+}
+
+template <class U, class A, class B, class C>
+void defer(U* wq, void (*f)(A, B, C), A a, B b, C c) {
+ work3<A, B, C>* w = new work3<A, B, C>(f, a, b, c);
+ wq->add(*w);
+}
+#else
+// The C++11 version is *much* simpler and even so more general!
+// These 2 definitions encompass everything in the C++03 section
+template <class T, class... Rest>
+void defer(void(T::*f)(Rest...), T* t, Rest... r) {
+ t->add(std::bind(f, t, r...));
+}
+
+template <class U, class... Rest>
+void defer(U* wq, Rest&&... r) {
+ wq->add(std::bind(std::forward<Rest>(r)...));
+}
+#endif
+
} // proton
#endif // PROTON_WORK_QUEUE_HPP
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[09/20] qpid-proton git commit: PROTON-1400: [C++ binding] Implement
container level event_loops
Posted by as...@apache.org.
PROTON-1400: [C++ binding] Implement container level event_loops
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/570d0a1a
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/570d0a1a
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/570d0a1a
Branch: refs/heads/master
Commit: 570d0a1aae29adfab861a76f37d2aa9f14488a9a
Parents: ec2364f
Author: Andrew Stitcher <as...@apache.org>
Authored: Thu Apr 20 15:20:40 2017 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
.../bindings/cpp/include/proton/container.hpp | 1 +
.../bindings/cpp/include/proton/event_loop.hpp | 1 +
proton-c/bindings/cpp/src/event_loop.cpp | 3 +
.../cpp/src/include/proactor_container_impl.hpp | 10 ++
.../src/include/proactor_event_loop_impl.hpp | 23 +--
.../cpp/src/proactor_container_impl.cpp | 156 ++++++++++++++-----
6 files changed, 139 insertions(+), 55 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/570d0a1a/proton-c/bindings/cpp/include/proton/container.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/container.hpp b/proton-c/bindings/cpp/include/proton/container.hpp
index be83e5e..0262e0f 100644
--- a/proton-c/bindings/cpp/include/proton/container.hpp
+++ b/proton-c/bindings/cpp/include/proton/container.hpp
@@ -224,6 +224,7 @@ class PN_CPP_CLASS_EXTERN container {
friend class session_options;
friend class receiver_options;
friend class sender_options;
+ friend class event_loop;
};
} // proton
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/570d0a1a/proton-c/bindings/cpp/include/proton/event_loop.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/event_loop.hpp b/proton-c/bindings/cpp/include/proton/event_loop.hpp
index f49d211..6d1646e 100644
--- a/proton-c/bindings/cpp/include/proton/event_loop.hpp
+++ b/proton-c/bindings/cpp/include/proton/event_loop.hpp
@@ -50,6 +50,7 @@ class PN_CPP_CLASS_EXTERN event_loop {
public:
/// Create event_loop
PN_CPP_EXTERN event_loop();
+ PN_CPP_EXTERN event_loop(container&);
PN_CPP_EXTERN ~event_loop();
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/570d0a1a/proton-c/bindings/cpp/src/event_loop.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/event_loop.cpp b/proton-c/bindings/cpp/src/event_loop.cpp
index ab39aa7..5320011 100644
--- a/proton-c/bindings/cpp/src/event_loop.cpp
+++ b/proton-c/bindings/cpp/src/event_loop.cpp
@@ -20,6 +20,7 @@
#include "proton/event_loop.hpp"
#include "contexts.hpp"
+#include "proactor_container_impl.hpp"
#include "proactor_event_loop_impl.hpp"
#include <proton/session.h>
@@ -28,6 +29,8 @@
namespace proton {
event_loop::event_loop() {}
+event_loop::event_loop(container& c) { *this = container::impl::make_event_loop(c); }
+
event_loop::~event_loop() {}
event_loop& event_loop::operator=(impl* i) { impl_.reset(i); return *this; }
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/570d0a1a/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp b/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
index 859493d..4b84a6e 100644
--- a/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
+++ b/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
@@ -28,6 +28,7 @@
#include "proton/connection_options.hpp"
#include "proton/duration.hpp"
#include "proton/error_condition.hpp"
+#include "proton/event_loop.hpp"
#include "proton/messaging_handler.hpp"
#include "proton/receiver.hpp"
#include "proton/receiver_options.hpp"
@@ -38,6 +39,7 @@
#include <list>
#include <map>
+#include <set>
#include <string>
#include <vector>
@@ -77,8 +79,12 @@ class container::impl {
#endif
template <class T> static void set_handler(T s, messaging_handler* h);
template <class T> static messaging_handler* get_handler(T s);
+ static event_loop::impl* make_event_loop(container&);
private:
+ class common_event_loop;
+ class connection_event_loop;
+ class container_event_loop;
pn_listener_t* listen_common_lh(const std::string&);
connection connect_common(const std::string&, const connection_options&);
@@ -89,6 +95,10 @@ class container::impl {
container& container_;
+ typedef std::set<container_event_loop*> event_loops;
+ event_loops event_loops_;
+ container_event_loop* add_event_loop();
+ void remove_event_loop(container_event_loop*);
struct scheduled {
timestamp time; // duration from epoch for task
#if PN_CPP_HAS_STD_FUNCTION
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/570d0a1a/proton-c/bindings/cpp/src/include/proactor_event_loop_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proactor_event_loop_impl.hpp b/proton-c/bindings/cpp/src/include/proactor_event_loop_impl.hpp
index 8fa7acf..82ec129 100644
--- a/proton-c/bindings/cpp/src/include/proactor_event_loop_impl.hpp
+++ b/proton-c/bindings/cpp/src/include/proactor_event_loop_impl.hpp
@@ -23,30 +23,19 @@
*/
#include "proton/fwd.hpp"
-
-struct pn_connection_t;
+#include "proton/internal/config.hpp"
namespace proton {
class event_loop::impl {
public:
- impl(pn_connection_t*);
-
- bool inject(void_function0& f);
+ virtual ~impl() {};
+ virtual bool inject(void_function0& f) = 0;
#if PN_CPP_HAS_STD_FUNCTION
- bool inject(std::function<void()> f);
- typedef std::vector<std::function<void()> > jobs;
-#else
- typedef std::vector<void_function0*> jobs;
+ virtual bool inject(std::function<void()> f) = 0;
#endif
-
-
- void run_all_jobs();
- void finished();
-
- jobs jobs_;
- pn_connection_t* connection_;
- bool finished_;
+ virtual void run_all_jobs() = 0;
+ virtual void finished() = 0;
};
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/570d0a1a/proton-c/bindings/cpp/src/proactor_container_impl.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proactor_container_impl.cpp b/proton-c/bindings/cpp/src/proactor_container_impl.cpp
index 2486e2b..4d526f2 100644
--- a/proton-c/bindings/cpp/src/proactor_container_impl.cpp
+++ b/proton-c/bindings/cpp/src/proactor_container_impl.cpp
@@ -43,30 +43,25 @@
namespace proton {
-event_loop::impl::impl(pn_connection_t* c)
- : connection_(c), finished_(false)
-{}
-
-void event_loop::impl::finished() {
- finished_ = true;
-}
+class container::impl::common_event_loop : public event_loop::impl {
+ public:
+ common_event_loop(): finished_(false) {}
#if PN_CPP_HAS_STD_FUNCTION
-bool event_loop::impl::inject(std::function<void()> f) {
- // Note this is an unbounded work queue.
- // A resource-safe implementation should be bounded.
- if (finished_)
- return false;
- jobs_.push_back(f);
- pn_connection_wake(connection_);
- return true;
-}
+ typedef std::vector<std::function<void()> > jobs;
+#else
+ typedef std::vector<void_function0*> jobs;
+#endif
-bool event_loop::impl::inject(proton::void_function0& f) {
- return inject([&f]() { f(); });
-}
+ void run_all_jobs();
+ void finished() { finished_ = true; }
-void event_loop::impl::run_all_jobs() {
+ jobs jobs_;
+ bool finished_;
+};
+
+#if PN_CPP_HAS_STD_FUNCTION
+void container::impl::common_event_loop::run_all_jobs() {
decltype(jobs_) j;
{
std::swap(j, jobs_);
@@ -77,25 +72,93 @@ void event_loop::impl::run_all_jobs() {
} catch (...) {};
}
#else
-bool event_loop::impl::inject(proton::void_function0& f) {
+void container::impl::common_event_loop::run_all_jobs() {
+ // Run queued work, but ignore any exceptions
+ for (jobs::iterator f = jobs_.begin(); f != jobs_.end(); ++f) try {
+ (**f)();
+ } catch (...) {};
+ jobs_.clear();
+ return;
+}
+#endif
+
+class container::impl::connection_event_loop : public common_event_loop {
+ public:
+ connection_event_loop(pn_connection_t* c): connection_(c) {}
+
+ bool inject(void_function0& f);
+#if PN_CPP_HAS_STD_FUNCTION
+ bool inject(std::function<void()> f);
+#endif
+
+ pn_connection_t* connection_;
+};
+
+#if PN_CPP_HAS_STD_FUNCTION
+bool container::impl::connection_event_loop::inject(std::function<void()> f) {
+ // Note this is an unbounded work queue.
+ // A resource-safe implementation should be bounded.
+ if (finished_) return false;
+ jobs_.emplace_back(std::move(f));
+ pn_connection_wake(connection_);
+ return true;
+}
+
+bool container::impl::connection_event_loop::inject(proton::void_function0& f) {
+ return inject([&f]() { f(); });
+}
+#else
+bool container::impl::connection_event_loop::inject(proton::void_function0& f) {
// Note this is an unbounded work queue.
// A resource-safe implementation should be bounded.
- if (finished_)
- return false;
+ if (finished_) return false;
jobs_.push_back(&f);
pn_connection_wake(connection_);
return true;
}
+#endif
-void event_loop::impl::run_all_jobs() {
- // Run queued work, but ignore any exceptions
- for (event_loop::impl::jobs::iterator f = jobs_.begin(); f != jobs_.end(); ++f) try {
- (**f)();
- } catch (...) {};
- jobs_.clear();
- return;
+class container::impl::container_event_loop : public common_event_loop {
+ public:
+ container_event_loop(container::impl& c): container_(c) {}
+ ~container_event_loop() { container_.remove_event_loop(this); }
+
+ bool inject(void_function0& f);
+#if PN_CPP_HAS_STD_FUNCTION
+ bool inject(std::function<void()> f);
+#endif
+
+ container::impl& container_;
+};
+
+#if PN_CPP_HAS_STD_FUNCTION
+bool container::impl::container_event_loop::inject(std::function<void()> f) {
+ // Note this is an unbounded work queue.
+ // A resource-safe implementation should be bounded.
+ if (finished_) return false;
+ jobs_.emplace_back(std::move(f));
+ pn_proactor_set_timeout(container_.proactor_, 0);
+ return true;
+}
+
+bool container::impl::container_event_loop::inject(proton::void_function0& f) {
+ return inject([&f]() { f(); });
+}
+#else
+bool container::impl::container_event_loop::inject(proton::void_function0& f) {
+ // Note this is an unbounded work queue.
+ // A resource-safe implementation should be bounded.
+ if (finished_) return false;
+ jobs_.push_back(&f);
+ pn_proactor_set_timeout(container_.proactor_, 0);
+ return true;
}
#endif
+
+class event_loop::impl* container::impl::make_event_loop(container& c) {
+ return c.impl_->add_event_loop();
+}
+
container::impl::impl(container& c, const std::string& id, messaging_handler* mh)
: container_(c), proactor_(pn_proactor()), handler_(mh), id_(id),
auto_stop_(true), stopping_(false)
@@ -109,6 +172,16 @@ container::impl::~impl() {
pn_proactor_free(proactor_);
}
+container::impl::container_event_loop* container::impl::add_event_loop() {
+ container_event_loop* c = new container_event_loop(*this);
+ event_loops_.insert(c);
+ return c;
+}
+
+void container::impl::remove_event_loop(container::impl::container_event_loop* l) {
+ event_loops_.erase(l);
+}
+
proton::connection container::impl::connect_common(
const std::string& addr,
const proton::connection_options& user_opts)
@@ -125,7 +198,7 @@ proton::connection container::impl::connect_common(
connection_context& cc(connection_context::get(pnc));
cc.container = &container_;
cc.handler = mh;
- cc.event_loop_ = new event_loop::impl(pnc);
+ cc.event_loop_ = new container::impl::connection_event_loop(pnc);
pn_connection_set_container(pnc, id_.c_str());
pn_connection_set_hostname(pnc, url.host().c_str());
@@ -225,7 +298,7 @@ void container::impl::schedule(duration delay, void_function0& f) {
pn_proactor_set_timeout(proactor_, delay.milliseconds());
// Record timeout; Add callback to timeout sorted list
- scheduled s={timestamp::now()+delay, &f};
+ scheduled s = {timestamp::now()+delay, &f};
deferred_.push_back(s);
std::push_heap(deferred_.begin(), deferred_.end());
}
@@ -285,13 +358,20 @@ bool container::impl::handle(pn_event_t* event) {
case PN_PROACTOR_INTERRUPT:
return false;
- case PN_PROACTOR_TIMEOUT:
- // Maybe we got a timeout and have nothing scheduled (not sure if this is possible)
- if ( deferred_.size()==0 ) return false;
+ case PN_PROACTOR_TIMEOUT: {
+ // Can get an immediate timeout, if we have a container event loop inject
+ if ( deferred_.size()>0 ) {
+ run_timer_jobs();
+ }
- run_timer_jobs();
+ // Run every container event loop job
+ // This is not at all efficient and single threads all these jobs, but it does correctly
+ // serialise them
+ for (event_loops::iterator loop = event_loops_.begin(); loop!=event_loops_.end(); ++loop) {
+ (*loop)->run_all_jobs();
+ }
return false;
-
+ }
case PN_LISTENER_OPEN:
return false;
@@ -312,7 +392,7 @@ bool container::impl::handle(pn_event_t* event) {
cc.container = &container_;
cc.listener_context_ = &lc;
cc.handler = opts.handler();
- cc.event_loop_ = new event_loop::impl(c);
+ cc.event_loop_ = new container::impl::connection_event_loop(c);
pn_listener_accept(l, c);
return false;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[03/20] qpid-proton git commit: PROTON-1481: [C++ binding] Simplify
code to use convenience functions
Posted by as...@apache.org.
PROTON-1481: [C++ binding] Simplify code to use convenience functions
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/ca446eac
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/ca446eac
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/ca446eac
Branch: refs/heads/master
Commit: ca446eac8d56ae9510f4ac5dbb1a9ab3dba93ac5
Parents: bf3a2b4
Author: Andrew Stitcher <as...@apache.org>
Authored: Thu May 18 14:14:58 2017 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
.../bindings/cpp/include/proton/thread_safe.hpp | 17 ++---------------
.../bindings/cpp/include/proton/work_queue.hpp | 9 ---------
2 files changed, 2 insertions(+), 24 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ca446eac/proton-c/bindings/cpp/include/proton/thread_safe.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/thread_safe.hpp b/proton-c/bindings/cpp/include/proton/thread_safe.hpp
index e5f5303..04e39df 100644
--- a/proton-c/bindings/cpp/include/proton/thread_safe.hpp
+++ b/proton-c/bindings/cpp/include/proton/thread_safe.hpp
@@ -63,12 +63,6 @@ template <class T>
class thread_safe : private internal::pn_ptr_base, private internal::endpoint_traits<T> {
typedef typename T::pn_type pn_type;
- struct inject_decref : public void_function0 {
- pn_type* ptr_;
- inject_decref(pn_type* p) : ptr_(p) {}
- void operator()() PN_CPP_OVERRIDE { decref(ptr_); delete this; }
- };
-
public:
/// @cond INTERNAL
static void operator delete(void*) {}
@@ -76,15 +70,8 @@ class thread_safe : private internal::pn_ptr_base, private internal::endpoint_tr
~thread_safe() {
if (ptr()) {
- if (!!work_queue()) {
-#if PN_CPP_HAS_STD_BIND
- work_queue().add(std::bind(&decref, ptr()));
-#else
- work_queue().add(*new inject_decref(ptr()));
-#endif
- } else {
- decref(ptr());
- }
+ if (!!work_queue().impl_) defer(&work_queue(), &decref, (void*)ptr());
+ else decref(ptr());
}
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ca446eac/proton-c/bindings/cpp/include/proton/work_queue.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/work_queue.hpp b/proton-c/bindings/cpp/include/proton/work_queue.hpp
index 4d843c2..fe739f5 100644
--- a/proton-c/bindings/cpp/include/proton/work_queue.hpp
+++ b/proton-c/bindings/cpp/include/proton/work_queue.hpp
@@ -87,15 +87,6 @@ class PN_CPP_CLASS_EXTERN work_queue {
PN_CPP_EXTERN ~work_queue();
-#if PN_CPP_HAS_EXPLICIT_CONVERSIONS
- /// When using C++11 (or later) you can use work_queue in a bool context
- /// to indicate if there is an event loop set.
- PN_CPP_EXTERN explicit operator bool() const { return bool(impl_); }
-#endif
-
- /// No event loop set.
- PN_CPP_EXTERN bool operator !() const { return !impl_; }
-
/// Add work to the work queue: f() will be called serialised with other work in the queue:
/// deferred and possibly in another thread.
///
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[12/20] qpid-proton git commit: PROTON-1481: [C++ binding] Rename
event_loop API to work_queue
Posted by as...@apache.org.
PROTON-1481: [C++ binding] Rename event_loop API to work_queue
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/45d5612b
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/45d5612b
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/45d5612b
Branch: refs/heads/master
Commit: 45d5612bd674fa5055767ae66a261b9d81433edf
Parents: 2b2666b
Author: Andrew Stitcher <as...@apache.org>
Authored: Mon May 15 01:27:54 2017 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
examples/cpp/broker.cpp | 40 ++++-----
examples/cpp/scheduled_send.cpp | 12 +--
examples/cpp/scheduled_send_03.cpp | 10 +--
proton-c/bindings/cpp/CMakeLists.txt | 2 +-
.../bindings/cpp/include/proton/container.hpp | 2 +-
.../bindings/cpp/include/proton/event_loop.hpp | 94 --------------------
proton-c/bindings/cpp/include/proton/fwd.hpp | 2 +-
.../cpp/include/proton/io/connection_driver.hpp | 2 +-
.../bindings/cpp/include/proton/thread_safe.hpp | 12 +--
.../bindings/cpp/include/proton/work_queue.hpp | 94 ++++++++++++++++++++
proton-c/bindings/cpp/src/connection.cpp | 2 +-
proton-c/bindings/cpp/src/event_loop.cpp | 60 -------------
proton-c/bindings/cpp/src/include/contexts.hpp | 4 +-
.../cpp/src/include/proactor_container_impl.hpp | 18 ++--
.../src/include/proactor_event_loop_impl.hpp | 43 ---------
.../src/include/proactor_work_queue_impl.hpp | 43 +++++++++
.../bindings/cpp/src/io/connection_driver.cpp | 2 +-
.../cpp/src/proactor_container_impl.cpp | 54 +++++------
proton-c/bindings/cpp/src/work_queue.cpp | 60 +++++++++++++
19 files changed, 278 insertions(+), 278 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/examples/cpp/broker.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/broker.cpp b/examples/cpp/broker.cpp
index 2fbe077..8c2d2ff 100644
--- a/examples/cpp/broker.cpp
+++ b/examples/cpp/broker.cpp
@@ -136,25 +136,25 @@ struct work3 : public proton::void_function0 {
template <class T>
void defer(T* t, void (T::*f)()) {
work0<T>* w = new work0<T>(*t, f);
- t->inject(*w);
+ t->add(*w);
}
template <class T, class A>
void defer(T* t, void (T::*f)(A), A a) {
work1<T, A>* w = new work1<T, A>(*t, f, a);
- t->inject(*w);
+ t->add(*w);
}
template <class T, class A, class B>
void defer(T* t, void (T::*f)(A, B), A a, B b) {
work2<T, A, B>* w = new work2<T, A, B>(*t, f, a, b);
- t->inject(*w);
+ t->add(*w);
}
template <class T, class A, class B, class C>
void defer(T* t, void (T::*f)(A, B, C), A a, B b, C c) {
work3<T, A, B, C>* w = new work3<T, A, B, C>(*t, f, a, b, c);
- t->inject(*w);
+ t->add(*w);
}
// Simple debug output
@@ -171,7 +171,7 @@ class Sender : public proton::messaging_handler {
proton::sender sender_;
senders& senders_;
- proton::event_loop& event_loop_;
+ proton::work_queue& work_queue_;
std::string queue_name_;
Queue* queue_;
int pending_credit_;
@@ -182,11 +182,11 @@ class Sender : public proton::messaging_handler {
public:
Sender(proton::sender s, senders& ss) :
- sender_(s), senders_(ss), event_loop_(make_thread_safe(s).get()->event_loop()), queue_(0), pending_credit_(0)
+ sender_(s), senders_(ss), work_queue_(make_thread_safe(s).get()->work_queue()), queue_(0), pending_credit_(0)
{}
- void inject(proton::void_function0& f) {
- event_loop_.inject(f);
+ void add(proton::void_function0& f) {
+ work_queue_.add(f);
}
@@ -203,7 +203,7 @@ public:
// Queue - round robin subscriptions
class Queue {
- proton::event_loop event_loop_;
+ proton::work_queue work_queue_;
const std::string name_;
std::deque<proton::message> messages_;
typedef std::map<Sender*, int> subscriptions; // With credit
@@ -238,11 +238,11 @@ class Queue {
public:
Queue(proton::container& c, const std::string& n) :
- event_loop_(c), name_(n), current_(subscriptions_.end())
+ work_queue_(c), name_(n), current_(subscriptions_.end())
{}
- void inject(proton::void_function0& f) {
- event_loop_.inject(f);
+ void add(proton::void_function0& f) {
+ work_queue_.add(f);
}
void queueMsg(proton::message m) {
@@ -307,7 +307,7 @@ class Receiver : public proton::messaging_handler {
friend class connection_handler;
proton::receiver receiver_;
- proton::event_loop& event_loop_;
+ proton::work_queue& work_queue_;
Queue* queue_;
std::deque<proton::message> messages_;
@@ -330,11 +330,11 @@ class Receiver : public proton::messaging_handler {
public:
Receiver(proton::receiver r) :
- receiver_(r), event_loop_(make_thread_safe(r).get()->event_loop()), queue_(0)
+ receiver_(r), work_queue_(make_thread_safe(r).get()->work_queue()), queue_(0)
{}
- void inject(proton::void_function0& f) {
- event_loop_.inject(f);
+ void add(proton::void_function0& f) {
+ work_queue_.add(f);
}
void boundQueue(Queue* q, std::string qn) {
@@ -351,18 +351,18 @@ public:
class QueueManager {
proton::container& container_;
- proton::event_loop event_loop_;
+ proton::work_queue work_queue_;
typedef std::map<std::string, Queue*> queues;
queues queues_;
int next_id_; // Use to generate unique queue IDs.
public:
QueueManager(proton::container& c) :
- container_(c), event_loop_(c), next_id_(0)
+ container_(c), work_queue_(c), next_id_(0)
{}
- void inject(proton::void_function0& f) {
- event_loop_.inject(f);
+ void add(proton::void_function0& f) {
+ work_queue_.add(f);
}
template <class T>
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/examples/cpp/scheduled_send.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/scheduled_send.cpp b/examples/cpp/scheduled_send.cpp
index de04c3b..bbef15b 100644
--- a/examples/cpp/scheduled_send.cpp
+++ b/examples/cpp/scheduled_send.cpp
@@ -23,12 +23,12 @@
#include <proton/container.hpp>
#include <proton/default_container.hpp>
-#include <proton/event_loop.hpp>
#include <proton/message.hpp>
#include <proton/messaging_handler.hpp>
#include <proton/sender.hpp>
#include <proton/thread_safe.hpp>
#include <proton/tracker.hpp>
+#include <proton/work_queue.hpp>
#include <iostream>
@@ -40,7 +40,7 @@ class scheduled_sender : public proton::messaging_handler {
std::string url;
proton::sender sender;
proton::duration interval, timeout;
- proton::event_loop* event_loop;
+ proton::work_queue* work_queue;
bool ready, canceled;
public:
@@ -57,11 +57,11 @@ class scheduled_sender : public proton::messaging_handler {
// and must arrange lambdas for send and close to happen in the connection context.
void on_container_start(proton::container &c) OVERRIDE {
sender = c.open_sender(url);
- event_loop = &proton::make_thread_safe(sender).get()->event_loop();
+ work_queue = &proton::make_thread_safe(sender).get()->work_queue();
// Call this->cancel after timeout.
- c.schedule(timeout, [this]() { this->event_loop->inject( [this]() { this->cancel(); }); });
+ c.schedule(timeout, [this]() { this->work_queue->add( [this]() { this->cancel(); }); });
// Start regular ticks every interval.
- c.schedule(interval, [this]() { this->event_loop->inject( [this]() { this->tick(); }); });
+ c.schedule(interval, [this]() { this->work_queue->add( [this]() { this->tick(); }); });
}
void cancel() {
@@ -72,7 +72,7 @@ class scheduled_sender : public proton::messaging_handler {
void tick() {
// Schedule the next tick unless we have been cancelled.
if (!canceled)
- sender.container().schedule(interval, [this]() { this->event_loop->inject( [this]() { this->tick(); }); });
+ sender.container().schedule(interval, [this]() { this->work_queue->add( [this]() { this->tick(); }); });
if (sender.credit() > 0) // Only send if we have credit
send();
else
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/examples/cpp/scheduled_send_03.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/scheduled_send_03.cpp b/examples/cpp/scheduled_send_03.cpp
index d106d29..4b1b626 100644
--- a/examples/cpp/scheduled_send_03.cpp
+++ b/examples/cpp/scheduled_send_03.cpp
@@ -25,13 +25,13 @@
#include <proton/connection.hpp>
#include <proton/default_container.hpp>
#include <proton/duration.hpp>
-#include <proton/event_loop.hpp>
#include <proton/function.hpp>
#include <proton/message.hpp>
#include <proton/messaging_handler.hpp>
#include <proton/sender.hpp>
#include <proton/thread_safe.hpp>
#include <proton/tracker.hpp>
+#include <proton/work_queue.hpp>
#include <iostream>
@@ -43,7 +43,7 @@ class scheduled_sender : public proton::messaging_handler {
private:
std::string url;
proton::duration interval, timeout;
- proton::event_loop *event_loop;
+ proton::work_queue *work_queue;
bool ready, canceled;
struct cancel_fn : public proton::void_function0 {
@@ -65,13 +65,13 @@ class scheduled_sender : public proton::messaging_handler {
struct defer_cancel_fn : public proton::void_function0 {
scheduled_sender& parent;
defer_cancel_fn(scheduled_sender& ss) : parent(ss) {}
- void operator()() { parent.event_loop->inject(parent.do_cancel); }
+ void operator()() { parent.work_queue->add(parent.do_cancel); }
};
struct defer_tick_fn : public proton::void_function0 {
scheduled_sender& parent;
defer_tick_fn(scheduled_sender& ss) : parent(ss) {}
- void operator()() { parent.event_loop->inject(parent.do_tick); }
+ void operator()() { parent.work_queue->add(parent.do_tick); }
};
tick_fn do_tick;
@@ -96,7 +96,7 @@ class scheduled_sender : public proton::messaging_handler {
}
void on_sender_open(proton::sender & s) OVERRIDE {
- event_loop = &proton::make_thread_safe(s).get()->event_loop();
+ work_queue = &proton::make_thread_safe(s).get()->work_queue();
do_cancel = cancel_fn(*this, s);
do_tick = tick_fn(*this, s);
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/proton-c/bindings/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/CMakeLists.txt b/proton-c/bindings/cpp/CMakeLists.txt
index 625206f..21ff26c 100644
--- a/proton-c/bindings/cpp/CMakeLists.txt
+++ b/proton-c/bindings/cpp/CMakeLists.txt
@@ -44,7 +44,6 @@ set(qpid-proton-cpp-source
src/endpoint.cpp
src/error.cpp
src/error_condition.cpp
- src/event_loop.cpp
src/handler.cpp
src/io/connection_driver.cpp
src/io/link_namer.cpp
@@ -77,6 +76,7 @@ set(qpid-proton-cpp-source
src/url.cpp
src/uuid.cpp
src/value.cpp
+ src/work_queue.cpp
)
set_source_files_properties (
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/proton-c/bindings/cpp/include/proton/container.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/container.hpp b/proton-c/bindings/cpp/include/proton/container.hpp
index 0262e0f..383aa3c 100644
--- a/proton-c/bindings/cpp/include/proton/container.hpp
+++ b/proton-c/bindings/cpp/include/proton/container.hpp
@@ -224,7 +224,7 @@ class PN_CPP_CLASS_EXTERN container {
friend class session_options;
friend class receiver_options;
friend class sender_options;
- friend class event_loop;
+ friend class work_queue;
};
} // proton
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/proton-c/bindings/cpp/include/proton/event_loop.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/event_loop.hpp b/proton-c/bindings/cpp/include/proton/event_loop.hpp
deleted file mode 100644
index 6d1646e..0000000
--- a/proton-c/bindings/cpp/include/proton/event_loop.hpp
+++ /dev/null
@@ -1,94 +0,0 @@
-#ifndef PROTON_EVENT_LOOP_HPP
-#define PROTON_EVENT_LOOP_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 "./fwd.hpp"
-#include "./internal/config.hpp"
-#include "./internal/export.hpp"
-#include "./internal/pn_unique_ptr.hpp"
-
-#include <functional>
-
-struct pn_connection_t;
-struct pn_session_t;
-struct pn_link_t;
-
-namespace proton {
-
-/// **Experimental** - A serial execution context.
-///
-/// Event handler functions associated with a single proton::connection are called in sequence.
-/// The connection's @ref event_loop allows you to "inject" extra work from any thread,
-/// and have it executed in the same sequence.
-///
-class PN_CPP_CLASS_EXTERN event_loop {
- /// @cond internal
- class impl;
- event_loop& operator=(impl* i);
- /// @endcond
-
- public:
- /// Create event_loop
- PN_CPP_EXTERN event_loop();
- PN_CPP_EXTERN event_loop(container&);
-
- PN_CPP_EXTERN ~event_loop();
-
-#if PN_CPP_HAS_EXPLICIT_CONVERSIONS
- /// When using C++11 (or later) you can use event_loop in a bool context
- /// to indicate if there is an event loop set.
- PN_CPP_EXTERN explicit operator bool() const { return bool(impl_); }
-#endif
-
- /// No event loop set.
- PN_CPP_EXTERN bool operator !() const { return !impl_; }
-
- /// Arrange to have f() called in the event_loop's sequence: possibly
- /// deferred, possibly in another thread.
- ///
- /// @return true if f() has or will be called, false if the event_loop is ended
- /// and f() cannot be injected.
- PN_CPP_EXTERN bool inject(void_function0& f);
-
-#if PN_CPP_HAS_STD_FUNCTION
- /// @copydoc inject(void_function0&)
- PN_CPP_EXTERN bool inject(std::function<void()> f);
-#endif
-
- private:
- PN_CPP_EXTERN static event_loop& get(pn_connection_t*);
- PN_CPP_EXTERN static event_loop& get(pn_session_t*);
- PN_CPP_EXTERN static event_loop& get(pn_link_t*);
-
- internal::pn_unique_ptr<impl> impl_;
-
- /// @cond INTERNAL
- friend class container;
- friend class io::connection_driver;
- template <class T> friend class thread_safe;
- /// @endcond
-};
-
-} // proton
-
-#endif // PROTON_EVENT_LOOP_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/proton-c/bindings/cpp/include/proton/fwd.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/fwd.hpp b/proton-c/bindings/cpp/include/proton/fwd.hpp
index 54d7646..6ad216e 100644
--- a/proton-c/bindings/cpp/include/proton/fwd.hpp
+++ b/proton-c/bindings/cpp/include/proton/fwd.hpp
@@ -31,7 +31,7 @@ class container;
class delivery;
class error_condition;
class event;
-class event_loop;
+class work_queue;
class message;
class message_id;
class messaging_handler;
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/proton-c/bindings/cpp/include/proton/io/connection_driver.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/io/connection_driver.hpp b/proton-c/bindings/cpp/include/proton/io/connection_driver.hpp
index 8d0be85..5df210d 100644
--- a/proton-c/bindings/cpp/include/proton/io/connection_driver.hpp
+++ b/proton-c/bindings/cpp/include/proton/io/connection_driver.hpp
@@ -40,7 +40,7 @@
namespace proton {
-class event_loop;
+class work_queue;
class proton_handler;
namespace io {
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/proton-c/bindings/cpp/include/proton/thread_safe.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/thread_safe.hpp b/proton-c/bindings/cpp/include/proton/thread_safe.hpp
index 608a1ca..e5f5303 100644
--- a/proton-c/bindings/cpp/include/proton/thread_safe.hpp
+++ b/proton-c/bindings/cpp/include/proton/thread_safe.hpp
@@ -25,10 +25,10 @@
#include "./fwd.hpp"
#include "./internal/config.hpp"
#include "./connection.hpp"
-#include "./event_loop.hpp"
#include "./function.hpp"
#include "./internal/object.hpp"
#include "./internal/type_traits.hpp"
+#include "./work_queue.hpp"
#include <functional>
@@ -76,11 +76,11 @@ class thread_safe : private internal::pn_ptr_base, private internal::endpoint_tr
~thread_safe() {
if (ptr()) {
- if (!!event_loop()) {
+ if (!!work_queue()) {
#if PN_CPP_HAS_STD_BIND
- event_loop().inject(std::bind(&decref, ptr()));
+ work_queue().add(std::bind(&decref, ptr()));
#else
- event_loop().inject(*new inject_decref(ptr()));
+ work_queue().add(*new inject_decref(ptr()));
#endif
} else {
decref(ptr());
@@ -88,8 +88,8 @@ class thread_safe : private internal::pn_ptr_base, private internal::endpoint_tr
}
}
- /// Get the event loop for this object.
- class event_loop& event_loop() { return event_loop::get(ptr()); }
+ /// Get the work queue for this object.
+ class work_queue& work_queue() { return work_queue::get(ptr()); }
/// Get the thread-unsafe proton object wrapped by this thread_safe<T>
T unsafe() { return T(ptr()); }
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/proton-c/bindings/cpp/include/proton/work_queue.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/work_queue.hpp b/proton-c/bindings/cpp/include/proton/work_queue.hpp
new file mode 100644
index 0000000..7acd507
--- /dev/null
+++ b/proton-c/bindings/cpp/include/proton/work_queue.hpp
@@ -0,0 +1,94 @@
+#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 "./fwd.hpp"
+#include "./internal/config.hpp"
+#include "./internal/export.hpp"
+#include "./internal/pn_unique_ptr.hpp"
+
+#include <functional>
+
+struct pn_connection_t;
+struct pn_session_t;
+struct pn_link_t;
+
+namespace proton {
+
+/// **Experimental** - A serial execution context.
+///
+/// Event handler functions associated with a single proton::connection are called in sequence.
+/// The connection's @ref event_loop allows you to "inject" extra work from any thread,
+/// and have it executed in the same sequence.
+///
+class PN_CPP_CLASS_EXTERN work_queue {
+ /// @cond internal
+ class impl;
+ work_queue& operator=(impl* i);
+ /// @endcond
+
+ public:
+ /// Create event_loop
+ PN_CPP_EXTERN work_queue();
+ PN_CPP_EXTERN work_queue(container&);
+
+ PN_CPP_EXTERN ~work_queue();
+
+#if PN_CPP_HAS_EXPLICIT_CONVERSIONS
+ /// When using C++11 (or later) you can use event_loop in a bool context
+ /// to indicate if there is an event loop set.
+ PN_CPP_EXTERN explicit operator bool() const { return bool(impl_); }
+#endif
+
+ /// No event loop set.
+ PN_CPP_EXTERN bool operator !() const { return !impl_; }
+
+ /// Arrange to have f() called in the event_loop's sequence: possibly
+ /// deferred, possibly in another thread.
+ ///
+ /// @return true if f() has or will be called, false if the event_loop is ended
+ /// and f() cannot be injected.
+ PN_CPP_EXTERN bool add(void_function0& f);
+
+#if PN_CPP_HAS_STD_FUNCTION
+ /// @copydoc inject(void_function0&)
+ PN_CPP_EXTERN bool add(std::function<void()> f);
+#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_;
+
+ /// @cond INTERNAL
+ friend class container;
+ friend class io::connection_driver;
+ template <class T> friend class thread_safe;
+ /// @endcond
+};
+
+} // proton
+
+#endif // PROTON_WORK_QUEUE_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/proton-c/bindings/cpp/src/connection.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connection.cpp b/proton-c/bindings/cpp/src/connection.cpp
index 11d5624..5432a42 100644
--- a/proton-c/bindings/cpp/src/connection.cpp
+++ b/proton-c/bindings/cpp/src/connection.cpp
@@ -25,12 +25,12 @@
#include "proton/connection_options.hpp"
#include "proton/container.hpp"
#include "proton/error.hpp"
-#include "proton/event_loop.hpp"
#include "proton/receiver_options.hpp"
#include "proton/sender_options.hpp"
#include "proton/session.hpp"
#include "proton/session_options.hpp"
#include "proton/transport.hpp"
+#include "proton/work_queue.hpp"
#include "contexts.hpp"
#include "msg.hpp"
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/proton-c/bindings/cpp/src/event_loop.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/event_loop.cpp b/proton-c/bindings/cpp/src/event_loop.cpp
deleted file mode 100644
index 5320011..0000000
--- a/proton-c/bindings/cpp/src/event_loop.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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 "proton/event_loop.hpp"
-
-#include "contexts.hpp"
-#include "proactor_container_impl.hpp"
-#include "proactor_event_loop_impl.hpp"
-
-#include <proton/session.h>
-#include <proton/link.h>
-
-namespace proton {
-
-event_loop::event_loop() {}
-event_loop::event_loop(container& c) { *this = container::impl::make_event_loop(c); }
-
-event_loop::~event_loop() {}
-
-event_loop& event_loop::operator=(impl* i) { impl_.reset(i); return *this; }
-
-bool event_loop::inject(void_function0& f) {
- return impl_->inject(f);
-}
-
-#if PN_CPP_HAS_STD_FUNCTION
-bool event_loop::inject(std::function<void()> f) {
- return impl_->inject(f);
-}
-#endif
-
-event_loop& event_loop::get(pn_connection_t* c) {
- return connection_context::get(c).event_loop_;
-}
-
-event_loop& event_loop::get(pn_session_t* s) {
- return get(pn_session_connection(s));
-}
-
-event_loop& event_loop::get(pn_link_t* l) {
- return get(pn_link_session(l));
-}
-
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/proton-c/bindings/cpp/src/include/contexts.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/contexts.hpp b/proton-c/bindings/cpp/src/include/contexts.hpp
index ab0661a..0c829db 100644
--- a/proton-c/bindings/cpp/src/include/contexts.hpp
+++ b/proton-c/bindings/cpp/src/include/contexts.hpp
@@ -22,7 +22,7 @@
*
*/
-#include "proton/event_loop.hpp"
+#include "proton/work_queue.hpp"
#include "proton/message.hpp"
#include "proton/internal/pn_unique_ptr.hpp"
@@ -92,7 +92,7 @@ class connection_context : public context {
messaging_handler* handler;
internal::pn_unique_ptr<reconnect_timer> reconnect;
listener_context* listener_context_;
- event_loop event_loop_;
+ work_queue work_queue_;
};
class listener_context : public context {
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp b/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
index 4b84a6e..9b4be11 100644
--- a/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
+++ b/proton-c/bindings/cpp/src/include/proactor_container_impl.hpp
@@ -28,12 +28,12 @@
#include "proton/connection_options.hpp"
#include "proton/duration.hpp"
#include "proton/error_condition.hpp"
-#include "proton/event_loop.hpp"
#include "proton/messaging_handler.hpp"
#include "proton/receiver.hpp"
#include "proton/receiver_options.hpp"
#include "proton/sender.hpp"
#include "proton/sender_options.hpp"
+#include "proton/work_queue.hpp"
#include "proton_bits.hpp"
@@ -79,12 +79,12 @@ class container::impl {
#endif
template <class T> static void set_handler(T s, messaging_handler* h);
template <class T> static messaging_handler* get_handler(T s);
- static event_loop::impl* make_event_loop(container&);
+ static work_queue::impl* make_work_queue(container&);
private:
- class common_event_loop;
- class connection_event_loop;
- class container_event_loop;
+ class common_work_queue;
+ class connection_work_queue;
+ class container_work_queue;
pn_listener_t* listen_common_lh(const std::string&);
connection connect_common(const std::string&, const connection_options&);
@@ -95,10 +95,10 @@ class container::impl {
container& container_;
- typedef std::set<container_event_loop*> event_loops;
- event_loops event_loops_;
- container_event_loop* add_event_loop();
- void remove_event_loop(container_event_loop*);
+ typedef std::set<container_work_queue*> work_queues;
+ work_queues work_queues_;
+ container_work_queue* add_work_queue();
+ void remove_work_queue(container_work_queue*);
struct scheduled {
timestamp time; // duration from epoch for task
#if PN_CPP_HAS_STD_FUNCTION
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/proton-c/bindings/cpp/src/include/proactor_event_loop_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proactor_event_loop_impl.hpp b/proton-c/bindings/cpp/src/include/proactor_event_loop_impl.hpp
deleted file mode 100644
index 82ec129..0000000
--- a/proton-c/bindings/cpp/src/include/proactor_event_loop_impl.hpp
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef PROTON_CPP_EVENT_LOOP_IMPL_HPP
-#define PROTON_CPP_EVENT_LOOP_IMPL_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 "proton/fwd.hpp"
-#include "proton/internal/config.hpp"
-
-namespace proton {
-
-class event_loop::impl {
- public:
- virtual ~impl() {};
- virtual bool inject(void_function0& f) = 0;
-#if PN_CPP_HAS_STD_FUNCTION
- virtual bool inject(std::function<void()> f) = 0;
-#endif
- virtual void run_all_jobs() = 0;
- virtual void finished() = 0;
-};
-
-}
-
-#endif // PROTON_CPP_EVENT_LOOP_IMPL_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/proton-c/bindings/cpp/src/include/proactor_work_queue_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/proactor_work_queue_impl.hpp b/proton-c/bindings/cpp/src/include/proactor_work_queue_impl.hpp
new file mode 100644
index 0000000..57fc4c0
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/proactor_work_queue_impl.hpp
@@ -0,0 +1,43 @@
+#ifndef PROTON_CPP_EVENT_LOOP_IMPL_HPP
+#define PROTON_CPP_EVENT_LOOP_IMPL_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 "proton/fwd.hpp"
+#include "proton/internal/config.hpp"
+
+namespace proton {
+
+class work_queue::impl {
+ public:
+ virtual ~impl() {};
+ virtual bool inject(void_function0& f) = 0;
+#if PN_CPP_HAS_STD_FUNCTION
+ virtual bool inject(std::function<void()> f) = 0;
+#endif
+ virtual void run_all_jobs() = 0;
+ virtual void finished() = 0;
+};
+
+}
+
+#endif // PROTON_CPP_EVENT_LOOP_IMPL_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/proton-c/bindings/cpp/src/io/connection_driver.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/io/connection_driver.cpp b/proton-c/bindings/cpp/src/io/connection_driver.cpp
index 58af052..d907e5c 100644
--- a/proton-c/bindings/cpp/src/io/connection_driver.cpp
+++ b/proton-c/bindings/cpp/src/io/connection_driver.cpp
@@ -20,10 +20,10 @@
#include "proton/io/connection_driver.hpp"
#include "proton/container.hpp"
-#include "proton/event_loop.hpp"
#include "proton/error.hpp"
#include "proton/messaging_handler.hpp"
#include "proton/uuid.hpp"
+#include "proton/work_queue.hpp"
#include "contexts.hpp"
#include "messaging_adapter.hpp"
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/proton-c/bindings/cpp/src/proactor_container_impl.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proactor_container_impl.cpp b/proton-c/bindings/cpp/src/proactor_container_impl.cpp
index 4d526f2..78ccabf 100644
--- a/proton-c/bindings/cpp/src/proactor_container_impl.cpp
+++ b/proton-c/bindings/cpp/src/proactor_container_impl.cpp
@@ -18,7 +18,7 @@
*/
#include "proactor_container_impl.hpp"
-#include "proactor_event_loop_impl.hpp"
+#include "proactor_work_queue_impl.hpp"
#include "proton/error_condition.hpp"
#include "proton/function.hpp"
@@ -43,9 +43,9 @@
namespace proton {
-class container::impl::common_event_loop : public event_loop::impl {
+class container::impl::common_work_queue : public work_queue::impl {
public:
- common_event_loop(): finished_(false) {}
+ common_work_queue(): finished_(false) {}
#if PN_CPP_HAS_STD_FUNCTION
typedef std::vector<std::function<void()> > jobs;
@@ -61,7 +61,7 @@ class container::impl::common_event_loop : public event_loop::impl {
};
#if PN_CPP_HAS_STD_FUNCTION
-void container::impl::common_event_loop::run_all_jobs() {
+void container::impl::common_work_queue::run_all_jobs() {
decltype(jobs_) j;
{
std::swap(j, jobs_);
@@ -72,7 +72,7 @@ void container::impl::common_event_loop::run_all_jobs() {
} catch (...) {};
}
#else
-void container::impl::common_event_loop::run_all_jobs() {
+void container::impl::common_work_queue::run_all_jobs() {
// Run queued work, but ignore any exceptions
for (jobs::iterator f = jobs_.begin(); f != jobs_.end(); ++f) try {
(**f)();
@@ -82,9 +82,9 @@ void container::impl::common_event_loop::run_all_jobs() {
}
#endif
-class container::impl::connection_event_loop : public common_event_loop {
+class container::impl::connection_work_queue : public common_work_queue {
public:
- connection_event_loop(pn_connection_t* c): connection_(c) {}
+ connection_work_queue(pn_connection_t* c): connection_(c) {}
bool inject(void_function0& f);
#if PN_CPP_HAS_STD_FUNCTION
@@ -95,7 +95,7 @@ class container::impl::connection_event_loop : public common_event_loop {
};
#if PN_CPP_HAS_STD_FUNCTION
-bool container::impl::connection_event_loop::inject(std::function<void()> f) {
+bool container::impl::connection_work_queue::inject(std::function<void()> f) {
// Note this is an unbounded work queue.
// A resource-safe implementation should be bounded.
if (finished_) return false;
@@ -104,11 +104,11 @@ bool container::impl::connection_event_loop::inject(std::function<void()> f) {
return true;
}
-bool container::impl::connection_event_loop::inject(proton::void_function0& f) {
+bool container::impl::connection_work_queue::inject(proton::void_function0& f) {
return inject([&f]() { f(); });
}
#else
-bool container::impl::connection_event_loop::inject(proton::void_function0& f) {
+bool container::impl::connection_work_queue::inject(proton::void_function0& f) {
// Note this is an unbounded work queue.
// A resource-safe implementation should be bounded.
if (finished_) return false;
@@ -118,10 +118,10 @@ bool container::impl::connection_event_loop::inject(proton::void_function0& f) {
}
#endif
-class container::impl::container_event_loop : public common_event_loop {
+class container::impl::container_work_queue : public common_work_queue {
public:
- container_event_loop(container::impl& c): container_(c) {}
- ~container_event_loop() { container_.remove_event_loop(this); }
+ container_work_queue(container::impl& c): container_(c) {}
+ ~container_work_queue() { container_.remove_work_queue(this); }
bool inject(void_function0& f);
#if PN_CPP_HAS_STD_FUNCTION
@@ -132,7 +132,7 @@ class container::impl::container_event_loop : public common_event_loop {
};
#if PN_CPP_HAS_STD_FUNCTION
-bool container::impl::container_event_loop::inject(std::function<void()> f) {
+bool container::impl::container_work_queue::inject(std::function<void()> f) {
// Note this is an unbounded work queue.
// A resource-safe implementation should be bounded.
if (finished_) return false;
@@ -141,11 +141,11 @@ bool container::impl::container_event_loop::inject(std::function<void()> f) {
return true;
}
-bool container::impl::container_event_loop::inject(proton::void_function0& f) {
+bool container::impl::container_work_queue::inject(proton::void_function0& f) {
return inject([&f]() { f(); });
}
#else
-bool container::impl::container_event_loop::inject(proton::void_function0& f) {
+bool container::impl::container_work_queue::inject(proton::void_function0& f) {
// Note this is an unbounded work queue.
// A resource-safe implementation should be bounded.
if (finished_) return false;
@@ -155,8 +155,8 @@ bool container::impl::container_event_loop::inject(proton::void_function0& f) {
}
#endif
-class event_loop::impl* container::impl::make_event_loop(container& c) {
- return c.impl_->add_event_loop();
+class work_queue::impl* container::impl::make_work_queue(container& c) {
+ return c.impl_->add_work_queue();
}
container::impl::impl(container& c, const std::string& id, messaging_handler* mh)
@@ -172,14 +172,14 @@ container::impl::~impl() {
pn_proactor_free(proactor_);
}
-container::impl::container_event_loop* container::impl::add_event_loop() {
- container_event_loop* c = new container_event_loop(*this);
- event_loops_.insert(c);
+container::impl::container_work_queue* container::impl::add_work_queue() {
+ container_work_queue* c = new container_work_queue(*this);
+ work_queues_.insert(c);
return c;
}
-void container::impl::remove_event_loop(container::impl::container_event_loop* l) {
- event_loops_.erase(l);
+void container::impl::remove_work_queue(container::impl::container_work_queue* l) {
+ work_queues_.erase(l);
}
proton::connection container::impl::connect_common(
@@ -198,7 +198,7 @@ proton::connection container::impl::connect_common(
connection_context& cc(connection_context::get(pnc));
cc.container = &container_;
cc.handler = mh;
- cc.event_loop_ = new container::impl::connection_event_loop(pnc);
+ cc.work_queue_ = new container::impl::connection_work_queue(pnc);
pn_connection_set_container(pnc, id_.c_str());
pn_connection_set_hostname(pnc, url.host().c_str());
@@ -344,7 +344,7 @@ bool container::impl::handle(pn_event_t* event) {
// If we have any pending connection work, do it now
pn_connection_t* c = pn_event_connection(event);
if (c) {
- event_loop::impl* loop = connection_context::get(c).event_loop_.impl_.get();
+ work_queue::impl* loop = connection_context::get(c).work_queue_.impl_.get();
loop->run_all_jobs();
}
@@ -367,7 +367,7 @@ bool container::impl::handle(pn_event_t* event) {
// Run every container event loop job
// This is not at all efficient and single threads all these jobs, but it does correctly
// serialise them
- for (event_loops::iterator loop = event_loops_.begin(); loop!=event_loops_.end(); ++loop) {
+ for (work_queues::iterator loop = work_queues_.begin(); loop!=work_queues_.end(); ++loop) {
(*loop)->run_all_jobs();
}
return false;
@@ -392,7 +392,7 @@ bool container::impl::handle(pn_event_t* event) {
cc.container = &container_;
cc.listener_context_ = &lc;
cc.handler = opts.handler();
- cc.event_loop_ = new container::impl::connection_event_loop(c);
+ cc.work_queue_ = new container::impl::connection_work_queue(c);
pn_listener_accept(l, c);
return false;
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/45d5612b/proton-c/bindings/cpp/src/work_queue.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/work_queue.cpp b/proton-c/bindings/cpp/src/work_queue.cpp
new file mode 100644
index 0000000..961e5f0
--- /dev/null
+++ b/proton-c/bindings/cpp/src/work_queue.cpp
@@ -0,0 +1,60 @@
+/*
+ * 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 "proton/work_queue.hpp"
+
+#include "contexts.hpp"
+#include "proactor_container_impl.hpp"
+#include "proactor_work_queue_impl.hpp"
+
+#include <proton/session.h>
+#include <proton/link.h>
+
+namespace proton {
+
+work_queue::work_queue() {}
+work_queue::work_queue(container& c) { *this = container::impl::make_work_queue(c); }
+
+work_queue::~work_queue() {}
+
+work_queue& work_queue::operator=(impl* i) { impl_.reset(i); return *this; }
+
+bool work_queue::add(void_function0& f) {
+ return impl_->inject(f);
+}
+
+#if PN_CPP_HAS_STD_FUNCTION
+bool work_queue::add(std::function<void()> f) {
+ return impl_->inject(f);
+}
+#endif
+
+work_queue& work_queue::get(pn_connection_t* c) {
+ return connection_context::get(c).work_queue_;
+}
+
+work_queue& work_queue::get(pn_session_t* s) {
+ return get(pn_session_connection(s));
+}
+
+work_queue& work_queue::get(pn_link_t* l) {
+ return get(pn_link_session(l));
+}
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[19/20] qpid-proton git commit: PROTON-1400: [C++ example] Fix ssl
test example to not rely on catching a specific exception thrown out of
container::run.
Posted by as...@apache.org.
PROTON-1400: [C++ example] Fix ssl test example to not rely on catching a specific exception thrown out of container::run.
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/2a606538
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/2a606538
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/2a606538
Branch: refs/heads/master
Commit: 2a606538336a15da4de38684b34432e4157a02b9
Parents: e4eca5c
Author: Andrew Stitcher <as...@apache.org>
Authored: Thu Jul 13 08:42:52 2017 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
examples/cpp/ssl.cpp | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2a606538/examples/cpp/ssl.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/ssl.cpp b/examples/cpp/ssl.cpp
index 85dfa48..166bd61 100644
--- a/examples/cpp/ssl.cpp
+++ b/examples/cpp/ssl.cpp
@@ -50,10 +50,11 @@ ssl_certificate platform_certificate(const std::string &base_name, const std::st
std::string find_CN(const std::string &);
namespace {
- std::string verify_full("full"); // Normal verification
- std::string verify_noname("noname"); // Skip matching host name against the certificate
- std::string verify_fail("fail"); // Force name mismatch failure
+ const std::string verify_full("full"); // Normal verification
+ const std::string verify_noname("noname"); // Skip matching host name against the certificate
+ const std::string verify_fail("fail"); // Force name mismatch failure
std::string verify(verify_full); // Default for example
+ bool verify_failed(false);
std::string cert_directory;
class example_cert_error : public std::runtime_error
@@ -137,8 +138,10 @@ class hello_world_direct : public proton::messaging_handler {
void on_transport_error(proton::transport &t) OVERRIDE {
std::string err = t.error().what();
- if (err.find("certificate"))
+ if (err.find("certificate")) {
+ verify_failed = true;
throw example_cert_error(err);
+ }
}
void on_sendable(proton::sender &s) OVERRIDE {
@@ -179,13 +182,15 @@ int main(int argc, char **argv) {
hello_world_direct hwd(address);
proton::default_container(hwd).run();
return 0;
- } catch (const example_cert_error& ce) {
- if (verify == verify_fail) {
- std::cout << "Expected failure of connection with wrong peer name: " << ce.what() << std::endl;
- return 0;
- }
- std::cerr << "unexpected internal certificate failure: " << ce.what() << std::endl;
} catch (const std::exception& e) {
+ if (verify_failed) {
+ if (verify == verify_fail) {
+ std::cout << "Expected failure of connection with wrong peer name: " << e.what() << std::endl;
+ return 0;
+ } else {
+ std::cerr << "unexpected internal certificate failure: ";
+ }
+ }
std::cerr << e.what() << std::endl;
}
return 1;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[11/20] qpid-proton git commit: PROTON-1400: [C++ example] Rework
broker to use container event loops
Posted by as...@apache.org.
PROTON-1400: [C++ example] Rework broker to use container event loops
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/2b2666b2
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/2b2666b2
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/2b2666b2
Branch: refs/heads/master
Commit: 2b2666b2758c5d493d07441a3eaad4a52d2bfbe1
Parents: 570d0a1
Author: Andrew Stitcher <as...@apache.org>
Authored: Tue Mar 28 13:45:28 2017 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jul 21 12:50:06 2017 -0400
----------------------------------------------------------------------
examples/cpp/broker.cpp | 553 +++++++++++++++++++++++++++++--------------
1 file changed, 377 insertions(+), 176 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2b2666b2/examples/cpp/broker.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/broker.cpp b/examples/cpp/broker.cpp
index 5b0982b..2fbe077 100644
--- a/examples/cpp/broker.cpp
+++ b/examples/cpp/broker.cpp
@@ -25,6 +25,7 @@
#include <proton/default_container.hpp>
#include <proton/delivery.hpp>
#include <proton/error_condition.hpp>
+#include <proton/function.hpp>
#include <proton/listen_handler.hpp>
#include <proton/listener.hpp>
#include <proton/message.hpp>
@@ -36,238 +37,436 @@
#include <proton/target_options.hpp>
#include <proton/thread_safe.hpp>
#include <proton/tracker.hpp>
+#include <proton/transport.hpp>
-#include <atomic>
#include <deque>
-#include <functional>
#include <iostream>
#include <map>
-#include <mutex>
#include <string>
#include "fake_cpp11.hpp"
-// Thread safe queue.
-// Stores messages, notifies subscribed connections when there is data.
-class queue {
- public:
- queue(const std::string& name) : name_(name) {}
+// This is a simplified model for a message broker, that only allows for messages to go to a
+// single receiver.
+//
+// Queues are only created and never destroyed
+//
+// Broker Entities (that need to be individually serialised)
+// QueueManager - Creates new queues, finds queues
+// Queue - Queues msgs, records subscribers, sends msgs to subscribers
+// Connection - Receives Messages from network, sends messages to network.
+
+// Work
+// FindQueue(queueName, connection) - From a Connection to the QueueManager
+// This will create the queue if it doesn't already exist and send a BoundQueue
+// message back to the connection.
+// BoundQueue(queue) - From the QueueManager to a Connection
+//
+// QueueMsg(msg) - From a Connection (receiver) to a Queue
+// Subscribe(sender) - From a Connection (sender) to a Queue
+// Flow(sender, credit) - From a Connection (sender) to a Queue
+// Unsubscribe(sender) - From a Connection (sender) to a Queue
+//
+// SendMsg(msg) - From a Queue to a Connection (sender)
+// Unsubscribed() - From a Queue to a Connection (sender)
+
+// Utilities to make injecting member functions palatable in C++03
+template <class T>
+struct work0 : public proton::void_function0 {
+ T& holder_;
+ void (T::* fn_)();
+
+ work0(T& h, void (T::* a)()) :
+ holder_(h), fn_(a) {}
+
+ void operator()() OVERRIDE {
+ (holder_.*fn_)();
+ delete this;
+ }
+};
+
+template <class T, class A>
+struct work1 : public proton::void_function0 {
+ T& holder_;
+ void (T::* fn_)(A);
+ A a_;
+
+ work1(T& h, void (T::* t)(A), A a) :
+ holder_(h), fn_(t), a_(a) {}
+
+ void operator()() OVERRIDE {
+ (holder_.*fn_)(a_);
+ delete this;
+ }
+};
+
+template <class T, class A, class B>
+struct work2 : public proton::void_function0 {
+ T& holder_;
+ void (T::* fn_)(A, B);
+ A a_;
+ B b_;
+
+ work2(T& h, void (T::* t)(A, B), A a, B b) :
+ holder_(h), fn_(t), a_(a), b_(b) {}
+
+ void operator()() OVERRIDE {
+ (holder_.*fn_)(a_, b_);
+ delete this;
+ }
+};
+
+template <class T, class A, class B, class C>
+struct work3 : public proton::void_function0 {
+ T& holder_;
+ void (T::* fn_)(A, B, C);
+ A a_;
+ B b_;
+ C c_;
+
+ work3(T& h, void (T::* t)(A, B, C), A a, B b, C c) :
+ holder_(h), fn_(t), a_(a), b_(b), c_(c) {}
+
+ void operator()() OVERRIDE {
+ (holder_.*fn_)(a_, b_, c_);
+ delete this;
+ }
+};
+
+template <class T>
+void defer(T* t, void (T::*f)()) {
+ work0<T>* w = new work0<T>(*t, f);
+ t->inject(*w);
+}
+
+template <class T, class A>
+void defer(T* t, void (T::*f)(A), A a) {
+ work1<T, A>* w = new work1<T, A>(*t, f, a);
+ t->inject(*w);
+}
+
+template <class T, class A, class B>
+void defer(T* t, void (T::*f)(A, B), A a, B b) {
+ work2<T, A, B>* w = new work2<T, A, B>(*t, f, a, b);
+ t->inject(*w);
+}
+
+template <class T, class A, class B, class C>
+void defer(T* t, void (T::*f)(A, B, C), A a, B b, C c) {
+ work3<T, A, B, C>* w = new work3<T, A, B, C>(*t, f, a, b, c);
+ t->inject(*w);
+}
+
+// Simple debug output
+bool verbose;
+#define DOUT(x) do {if (verbose) {x};} while (false)
+
+class Queue;
+class Sender;
- std::string name() const { return name_; }
+typedef std::map<proton::sender, Sender*> senders;
- // Push a message onto the queue.
- // If the queue was previously empty, notify subscribers it has messages.
- // Called from receiver's connection.
- void push(const proton::message &m) {
- std::lock_guard<std::mutex> g(lock_);
+class Sender : public proton::messaging_handler {
+ friend class connection_handler;
+
+ proton::sender sender_;
+ senders& senders_;
+ proton::event_loop& event_loop_;
+ std::string queue_name_;
+ Queue* queue_;
+ int pending_credit_;
+
+ // Messaging handlers
+ void on_sendable(proton::sender &sender) OVERRIDE;
+ void on_sender_close(proton::sender &sender) OVERRIDE;
+
+public:
+ Sender(proton::sender s, senders& ss) :
+ sender_(s), senders_(ss), event_loop_(make_thread_safe(s).get()->event_loop()), queue_(0), pending_credit_(0)
+ {}
+
+ void inject(proton::void_function0& f) {
+ event_loop_.inject(f);
+ }
+
+
+ void boundQueue(Queue* q, std::string qn);
+ void sendMsg(proton::message m) {
+ DOUT(std::cerr << "Sender: " << this << " sending\n";);
+ sender_.send(m);
+ }
+ void unsubscribed() {
+ DOUT(std::cerr << "Sender: " << this << " deleting\n";);
+ delete this;
+ }
+};
+
+// Queue - round robin subscriptions
+class Queue {
+ proton::event_loop event_loop_;
+ const std::string name_;
+ std::deque<proton::message> messages_;
+ typedef std::map<Sender*, int> subscriptions; // With credit
+ subscriptions subscriptions_;
+ subscriptions::iterator current_;
+
+ void tryToSend() {
+ DOUT(std::cerr << "Queue: " << this << " tryToSend: " << subscriptions_.size(););
+ // Starting at current_, send messages to subscriptions with credit:
+ // After each send try to find another subscription; Wrap around;
+ // Finish when we run out of messages or credit.
+ size_t outOfCredit = 0;
+ while (!messages_.empty() && outOfCredit<subscriptions_.size()) {
+ // If we got the end (or haven't started yet) start at the beginning
+ if (current_==subscriptions_.end()) {
+ current_=subscriptions_.begin();
+ }
+ // If we have credit send the message
+ DOUT(std::cerr << "(" << current_->second << ") ";);
+ if (current_->second>0) {
+ DOUT(std::cerr << current_->first << " ";);
+ defer(current_->first, &Sender::sendMsg, messages_.front());
+ messages_.pop_front();
+ --current_->second;
+ ++current_;
+ } else {
+ ++outOfCredit;
+ }
+ }
+ DOUT(std::cerr << "\n";);
+ }
+
+public:
+ Queue(proton::container& c, const std::string& n) :
+ event_loop_(c), name_(n), current_(subscriptions_.end())
+ {}
+
+ void inject(proton::void_function0& f) {
+ event_loop_.inject(f);
+ }
+
+ void queueMsg(proton::message m) {
+ DOUT(std::cerr << "Queue: " << this << "(" << name_ << ") queueMsg\n";);
messages_.push_back(m);
- if (messages_.size() == 1) { // Non-empty, notify subscribers
- for (auto cb : callbacks_)
- cb(this);
- callbacks_.clear();
+ tryToSend();
+ }
+ void flow(Sender* s, int c) {
+ DOUT(std::cerr << "Queue: " << this << "(" << name_ << ") flow: " << c << " to " << s << "\n";);
+ subscriptions_[s] = c;
+ tryToSend();
+ }
+ void subscribe(Sender* s) {
+ DOUT(std::cerr << "Queue: " << this << "(" << name_ << ") subscribe Sender: " << s << "\n";);
+ subscriptions_[s] = 0;
+ }
+ void unsubscribe(Sender* s) {
+ DOUT(std::cerr << "Queue: " << this << "(" << name_ << ") unsubscribe Sender: " << s << "\n";);
+ // If we're about to erase the current subscription move on
+ if (current_ != subscriptions_.end() && current_->first==s) ++current_;
+ subscriptions_.erase(s);
+ defer(s, &Sender::unsubscribed);
+ }
+};
+
+// We have credit to send a message.
+void Sender::on_sendable(proton::sender &sender) {
+ if (queue_) {
+ defer(queue_, &Queue::flow, this, sender.credit());
+ } else {
+ pending_credit_ = sender.credit();
+ }
+}
+
+void Sender::on_sender_close(proton::sender &sender) {
+ if (queue_) {
+ defer(queue_, &Queue::unsubscribe, this);
+ } else {
+ // TODO: Is it possible to be closed before we get the queue allocated?
+ // If so, we should have a way to mark the sender deleted, so we can delete
+ // on queue binding
+ }
+ senders_.erase(sender);
+}
+
+void Sender::boundQueue(Queue* q, std::string qn) {
+ DOUT(std::cerr << "Sender: " << this << " bound to Queue: " << q <<"(" << qn << ")\n";);
+ queue_ = q;
+ queue_name_ = qn;
+
+ defer(q, &Queue::subscribe, this);
+ sender_.open(proton::sender_options()
+ .source((proton::source_options().address(queue_name_)))
+ .handler(*this));
+ if (pending_credit_>0) {
+ defer(queue_, &Queue::flow, this, pending_credit_);
+ }
+ std::cout << "sending from " << queue_name_ << std::endl;
+}
+
+class Receiver : public proton::messaging_handler {
+ friend class connection_handler;
+
+ proton::receiver receiver_;
+ proton::event_loop& event_loop_;
+ Queue* queue_;
+ std::deque<proton::message> messages_;
+
+ // A message is received.
+ void on_message(proton::delivery &, proton::message &m) OVERRIDE {
+ messages_.push_back(m);
+
+ if (queue_) {
+ queueMsgs();
}
}
- // If the queue is not empty, pop a message into m and return true.
- // Otherwise save callback to be called when there are messages and return false.
- // Called from sender's connection.
- bool pop(proton::message& m, std::function<void(queue*)> callback) {
- std::lock_guard<std::mutex> g(lock_);
- if (messages_.empty()) {
- callbacks_.push_back(callback);
- return false;
- } else {
- m = std::move(messages_.front());
+ void queueMsgs() {
+ DOUT(std::cerr << "Receiver: " << this << " queueing " << messages_.size() << " msgs to: " << queue_ << "\n";);
+ while (!messages_.empty()) {
+ defer(queue_, &Queue::queueMsg, messages_.front());
messages_.pop_front();
- return true;
}
}
- private:
- const std::string name_;
- std::mutex lock_;
- std::deque<proton::message> messages_;
- std::vector<std::function<void(queue*)> > callbacks_;
+public:
+ Receiver(proton::receiver r) :
+ receiver_(r), event_loop_(make_thread_safe(r).get()->event_loop()), queue_(0)
+ {}
+
+ void inject(proton::void_function0& f) {
+ event_loop_.inject(f);
+ }
+
+ void boundQueue(Queue* q, std::string qn) {
+ DOUT(std::cerr << "Receiver: " << this << " bound to Queue: " << q << "(" << qn << ")\n";);
+ queue_ = q;
+ receiver_.open(proton::receiver_options()
+ .source((proton::source_options().address(qn)))
+ .handler(*this));
+ std::cout << "receiving to " << qn << std::endl;
+
+ queueMsgs();
+ }
};
-/// Thread safe map of queues.
-class queues {
- public:
- queues() : next_id_(0) {}
+class QueueManager {
+ proton::container& container_;
+ proton::event_loop event_loop_;
+ typedef std::map<std::string, Queue*> queues;
+ queues queues_;
+ int next_id_; // Use to generate unique queue IDs.
- // Get or create the named queue.
- queue* get(const std::string& name) {
- std::lock_guard<std::mutex> g(lock_);
- auto i = queues_.insert(queue_map::value_type(name, nullptr)).first;
- if (!i->second)
- i->second.reset(new queue(name));
- return i->second.get();
+public:
+ QueueManager(proton::container& c) :
+ container_(c), event_loop_(c), next_id_(0)
+ {}
+
+ void inject(proton::void_function0& f) {
+ event_loop_.inject(f);
}
- // Create a dynamic queue with a unique name.
- queue* dynamic() {
- std::ostringstream os;
- os << "_dynamic_" << next_id_++;
- return get(os.str());
+ template <class T>
+ void findQueue(T& connection, std::string& qn) {
+ if (qn.empty()) {
+ // Dynamic queue creation
+ std::ostringstream os;
+ os << "_dynamic_" << next_id_++;
+ qn = os.str();
+ }
+ Queue* q = 0;
+ queues::iterator i = queues_.find(qn);
+ if (i==queues_.end()) {
+ q = new Queue(container_, qn);
+ queues_[qn] = q;
+ } else {
+ q = i->second;
+ }
+ defer(&connection, &T::boundQueue, q, qn);
}
- private:
- typedef std::map<std::string, std::unique_ptr<queue> > queue_map;
+ void findQueueSender(Sender* s, std::string qn) {
+ findQueue(*s, qn);
+ }
- std::mutex lock_;
- queue_map queues_;
- std::atomic<int> next_id_; // Use to generate unique queue IDs.
+ void findQueueReceiver(Receiver* r, std::string qn) {
+ findQueue(*r, qn);
+ }
};
-/// Broker connection handler. Things to note:
-///
-/// 1. Each handler manages a single connection.
-///
-/// 2. For a *single connection* calls to proton::handler functions and calls to
-/// function objects passed to proton::event_loop::inject() are serialized,
-/// i.e. never called concurrently. Handlers can have per-connection state
-/// without needing locks.
-///
-/// 3. Handler/injected functions for *different connections* can be called
-/// concurrently. Resources used by multiple connections (e.g. the queues in
-/// this example) must be thread-safe.
-///
-/// 4. You can 'inject' work to be done sequentially using a connection's
-/// proton::event_loop. In this example, we create a std::function callback
-/// that we pass to queues, so they can notify us when they have messages.
-///
-class broker_connection_handler : public proton::messaging_handler {
- public:
- broker_connection_handler(queues& qs) : queues_(qs) {}
+class connection_handler : public proton::messaging_handler {
+ QueueManager& queue_manager_;
+ senders senders_;
- void on_connection_open(proton::connection& c) OVERRIDE {
- // Create the has_messages callback for queue subscriptions.
- //
- // Make a std::shared_ptr to a thread_safe handle for our proton::connection.
- // The connection's proton::event_loop will remain valid as a shared_ptr exists.
- std::shared_ptr<proton::thread_safe<proton::connection> > ts_c = make_shared_thread_safe(c);
-
- // Make a lambda function to inject a call to this->has_messages() via the proton::event_loop.
- // The function is bound to a shared_ptr so this is safe. If the connection has already closed
- // proton::event_loop::inject() will drop the callback.
- has_messages_callback_ = [this, ts_c](queue* q) mutable {
- ts_c->event_loop().inject(
- std::bind(&broker_connection_handler::has_messages, this, q));
- };
+public:
+ connection_handler(QueueManager& qm) :
+ queue_manager_(qm)
+ {}
+ void on_connection_open(proton::connection& c) OVERRIDE {
c.open(); // Accept the connection
}
// A sender sends messages from a queue to a subscriber.
void on_sender_open(proton::sender &sender) OVERRIDE {
- queue *q = sender.source().dynamic() ?
- queues_.dynamic() : queues_.get(sender.source().address());
- sender.open(proton::sender_options().source((proton::source_options().address(q->name()))));
- std::cout << "sending from " << q->name() << std::endl;
- }
-
- // We have credit to send a message.
- void on_sendable(proton::sender &s) OVERRIDE {
- queue* q = sender_queue(s);
- if (!do_send(q, s)) // Queue is empty, save ourselves in the blocked set.
- blocked_.insert(std::make_pair(q, s));
+ std::string qn = sender.source().dynamic() ? "" : sender.source().address();
+ Sender* s = new Sender(sender, senders_);
+ senders_[sender] = s;
+ defer(&queue_manager_, &QueueManager::findQueueSender, s, qn);
}
// A receiver receives messages from a publisher to a queue.
- void on_receiver_open(proton::receiver &r) OVERRIDE {
- std::string qname = r.target().address();
+ void on_receiver_open(proton::receiver &receiver) OVERRIDE {
+ std::string qname = receiver.target().address();
if (qname == "shutdown") {
std::cout << "broker shutting down" << std::endl;
// Sending to the special "shutdown" queue stops the broker.
- r.connection().container().stop(
+ receiver.connection().container().stop(
proton::error_condition("shutdown", "stop broker"));
} else {
- r.open(proton::receiver_options().target(proton::target_options().address(qname)));
- std::cout << "receiving to " << qname << std::endl;
+ if (qname.empty()) {
+ DOUT(std::cerr << "ODD - trying to attach to a empty address\n";);
+ }
+ Receiver* r = new Receiver(receiver);
+ defer(&queue_manager_, &QueueManager::findQueueReceiver, r, qname);
}
}
- // A message is received.
- void on_message(proton::delivery &d, proton::message &m) OVERRIDE {
- std::string qname = d.receiver().target().address();
- queues_.get(qname)->push(m);
- }
-
void on_session_close(proton::session &session) OVERRIDE {
- // Erase all blocked senders that belong to session.
- auto predicate = [session](const proton::sender& s) {
- return s.session() == session;
- };
- erase_sender_if(blocked_.begin(), blocked_.end(), predicate);
- }
-
- void on_sender_close(proton::sender &sender) OVERRIDE {
- // Erase sender from the blocked set.
- auto range = blocked_.equal_range(sender_queue(sender));
- auto predicate = [sender](const proton::sender& s) { return s == sender; };
- erase_sender_if(range.first, range.second, predicate);
+ // Unsubscribe all senders that belong to session.
+ for (proton::sender_iterator i = session.senders().begin(); i != session.senders().end(); ++i) {
+ senders::iterator j = senders_.find(*i);
+ if (j == senders_.end()) continue;
+ Sender* s = j->second;
+ if (s->queue_) {
+ defer(s->queue_, &Queue::unsubscribe, s);
+ }
+ senders_.erase(j);
+ }
}
void on_error(const proton::error_condition& e) OVERRIDE {
std::cerr << "error: " << e.what() << std::endl;
}
- // The container calls on_transport_close() last.
- void on_transport_close(proton::transport&) OVERRIDE {
- delete this; // All done.
- }
- private:
- typedef std::multimap<queue*, proton::sender> blocked_map;
-
- // Get the queue associated with a sender.
- queue* sender_queue(const proton::sender& s) {
- return queues_.get(s.source().address()); // Thread safe.
- }
-
- // Only called if we have credit. Return true if we sent a message.
- bool do_send(queue* q, proton::sender &s) {
- proton::message m;
- bool popped = q->pop(m, has_messages_callback_);
- if (popped)
- s.send(m);
- /// if !popped the queue has saved the callback for later.
- return popped;
- }
-
- // Called via the connection's proton::event_loop when q has messages.
- // Try all the blocked senders.
- void has_messages(queue* q) {
- auto range = blocked_.equal_range(q);
- for (auto i = range.first; i != range.second;) {
- if (i->second.credit() <= 0 || do_send(q, i->second))
- i = blocked_.erase(i); // No credit or send was successful, stop blocked.
- else
- ++i; // have credit, didn't send, keep blocked
- }
- }
-
- // Use to erase closed senders from blocked_ set.
- template <class Predicate>
- void erase_sender_if(blocked_map::iterator begin, blocked_map::iterator end, Predicate p) {
- for (auto i = begin; i != end; ) {
- if (p(i->second))
- i = blocked_.erase(i);
- else
- ++i;
+ // The container calls on_transport_close() last.
+ void on_transport_close(proton::transport& t) OVERRIDE {
+ // Unsubscribe all senders.
+ for (proton::sender_iterator i = t.connection().senders().begin(); i != t.connection().senders().end(); ++i) {
+ senders::iterator j = senders_.find(*i);
+ if (j == senders_.end()) continue;
+ Sender* s = j->second;
+ if (s->queue_) {
+ defer(s->queue_, &Queue::unsubscribe, s);
+ }
}
+ delete this; // All done.
}
-
- queues& queues_;
- blocked_map blocked_;
- std::function<void(queue*)> has_messages_callback_;
- proton::connection connection_;
};
-
class broker {
public:
broker(const std::string addr) :
- container_("mt_broker"), listener_(queues_)
+ container_("broker"), queues_(container_), listener_(queues_)
{
container_.listen(addr, listener_);
std::cout << "broker listening on " << addr << std::endl;
@@ -279,21 +478,21 @@ class broker {
private:
struct listener : public proton::listen_handler {
- listener(queues& qs) : queues_(qs) {}
+ listener(QueueManager& c) : queues_(c) {}
proton::connection_options on_accept(proton::listener&) OVERRIDE{
- return proton::connection_options().handler(*(new broker_connection_handler(queues_)));
+ return proton::connection_options().handler(*(new connection_handler(queues_)));
}
void on_error(proton::listener&, const std::string& s) OVERRIDE {
std::cerr << "listen error: " << s << std::endl;
throw std::runtime_error(s);
}
- queues& queues_;
+ QueueManager& queues_;
};
- queues queues_;
proton::container container_;
+ QueueManager queues_;
listener listener_;
};
@@ -302,9 +501,11 @@ int main(int argc, char **argv) {
std::string address("0.0.0.0");
example::options opts(argc, argv);
+ opts.add_flag(verbose, 'v', "verbose", "verbose (debugging) output");
opts.add_value(address, 'a', "address", "listen on URL", "URL");
try {
+ verbose = false;
opts.parse();
broker(address).run();
return 0;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org