Repository: qpid-proton Updated Branches: refs/heads/master b1c348889 -> 1b8450d6a
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b8450d6/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 1a1b3f3..26a78a0 100644 --- a/proton-c/bindings/cpp/src/receiver_options.cpp +++ b/proton-c/bindings/cpp/src/receiver_options.cpp @@ -45,7 +45,9 @@ template <class T> struct option { class receiver_options::impl { static void set_handler(receiver l, proton_handler &h) { pn_record_t *record = pn_link_attachments(unwrap(l)); - internal::pn_ptr<pn_handler_t> chandler = l.connection().container().impl_->cpp_handler(&h); + // FIXME aconway 2016-05-04: container_impl specific, fix for engine. + internal::pn_ptr<pn_handler_t> chandler = + static_cast<container_impl&>(l.connection().container()).cpp_handler(&h); pn_record_set_handler(record, chandler.get()); } @@ -123,7 +125,7 @@ receiver_options& receiver_options::operator=(const receiver_options& x) { void receiver_options::update(const receiver_options& x) { impl_->update(*x.impl_); } -receiver_options& receiver_options::handler(class handler *h) { impl_->handler = h->messaging_adapter_.get(); return *this; } +receiver_options& receiver_options::handler(class handler &h) { impl_->handler = h.messaging_adapter_.get(); return *this; } receiver_options& receiver_options::delivery_mode(proton::delivery_mode m) {impl_->delivery_mode = m; return *this; } receiver_options& receiver_options::auto_accept(bool b) {impl_->auto_accept = b; return *this; } receiver_options& receiver_options::auto_settle(bool b) {impl_->auto_settle = b; return *this; } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b8450d6/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 4786937..2922157 100644 --- a/proton-c/bindings/cpp/src/sender_options.cpp +++ b/proton-c/bindings/cpp/src/sender_options.cpp @@ -43,7 +43,9 @@ template <class T> struct option { class sender_options::impl { static void set_handler(sender l, proton_handler &h) { pn_record_t *record = pn_link_attachments(unwrap(l)); - internal::pn_ptr<pn_handler_t> chandler = l.connection().container().impl_->cpp_handler(&h); + // FIXME aconway 2016-05-04: container_impl specific, fix for engine. + internal::pn_ptr<pn_handler_t> chandler = + static_cast<container_impl&>(l.connection().container()).cpp_handler(&h); pn_record_set_handler(record, chandler.get()); } @@ -111,7 +113,7 @@ sender_options& sender_options::operator=(const sender_options& x) { void sender_options::update(const sender_options& x) { impl_->update(*x.impl_); } -sender_options& sender_options::handler(class handler *h) { impl_->handler = h->messaging_adapter_.get(); return *this; } +sender_options& sender_options::handler(class handler &h) { impl_->handler = h.messaging_adapter_.get(); return *this; } sender_options& sender_options::delivery_mode(proton::delivery_mode m) {impl_->delivery_mode = m; return *this; } sender_options& sender_options::auto_settle(bool b) {impl_->auto_settle = b; return *this; } sender_options& sender_options::source(source_options &s) {impl_->source = s; return *this; } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b8450d6/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 cdb4722..bfcedc2 100644 --- a/proton-c/bindings/cpp/src/session.cpp +++ b/proton-c/bindings/cpp/src/session.cpp @@ -58,7 +58,9 @@ connection session::connection() const { namespace { std::string next_link_name(const connection& c) { - return connection_context::get(c).link_gen.next(); + io::link_namer* ln = connection_context::get(c).link_gen; + + return ln ? ln->link_name() : uuid::random().str(); } } @@ -119,7 +121,6 @@ receiver_range session::receivers() const { return receiver_range(receiver_iterator(make_wrapper<receiver>(lnk), pn_object())); } - session_iterator session_iterator::operator++() { obj_ = pn_session_next(unwrap(obj_), 0); return *this; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b8450d6/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 9f77d6b..71b5b8d 100644 --- a/proton-c/bindings/cpp/src/session_options.cpp +++ b/proton-c/bindings/cpp/src/session_options.cpp @@ -49,7 +49,9 @@ class session_options::impl { if (s.uninitialized()) { if (handler.set) { pn_record_t *record = pn_session_attachments(unwrap(s)); - internal::pn_ptr<pn_handler_t> chandler = s.connection().container().impl_->cpp_handler(handler.value); + // FIXME aconway 2016-05-04: container_impl specific + internal::pn_ptr<pn_handler_t> chandler = + static_cast<container_impl&>(s.connection().container()).cpp_handler(handler.value); pn_record_set_handler(record, chandler.get()); } } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b8450d6/proton-c/bindings/cpp/src/test_dummy_container.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/test_dummy_container.hpp b/proton-c/bindings/cpp/src/test_dummy_container.hpp new file mode 100644 index 0000000..7307901 --- /dev/null +++ b/proton-c/bindings/cpp/src/test_dummy_container.hpp @@ -0,0 +1,73 @@ +#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 container { + public: + dummy_container(const std::string cid="") : + id_(cid), fail("not implemented for dummy_container") {} + + returned<connection> connect(const std::string&, const connection_options&) { throw fail; } + listener listen(const std::string& , listen_handler& ) { throw fail; } + listener listen(const std::string&, const connection_options&) { 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_; } + + 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::inject_handler& h) PN_CPP_OVERRIDE { h.on_inject(); return true; } +}; + +} + +#endif // TEST_DUMMY_CONTAINER_HPP http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b8450d6/proton-c/bindings/cpp/src/thread_safe_test.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/thread_safe_test.cpp b/proton-c/bindings/cpp/src/thread_safe_test.cpp new file mode 100644 index 0000000..540fcc8 --- /dev/null +++ b/proton-c/bindings/cpp/src/thread_safe_test.cpp @@ -0,0 +1,117 @@ +/* + * 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. + */ + +/// Test reference counting for object wrappers, threads_safe<> wrappers and returned<> wrappers. +/// + +#include "test_bits.hpp" +#include "test_dummy_container.hpp" +#include "proton_bits.hpp" + +#include "proton/thread_safe.hpp" +#include "proton/io/connection_engine.hpp" +#include "proton/io/link_namer.hpp" + +#include <proton/connection.h> + +namespace { + +using namespace proton; +using namespace test; +using namespace std; + +dummy_container cont; + +namespace { +struct linknames : io::link_namer { + std::string link_name() { return "X"; } +} dummy_link_namer; +} + +void test_new() { + pn_connection_t* c = 0; + thread_safe<connection>* p = 0; + { + io::connection_engine e(cont, dummy_link_namer, new dummy_event_loop); + c = unwrap(e.connection()); + int r = pn_refcount(c); + ASSERT(r >= 1); // engine may have internal refs (transport, collector). + p = make_thread_safe(e.connection()).release(); + ASSERT_EQUAL(r+1, pn_refcount(c)); + delete p; + ASSERT_EQUAL(r, pn_refcount(c)); + p = make_thread_safe(e.connection()).release(); + } + ASSERT_EQUAL(1, pn_refcount(c)); // Engine gone, thread_safe keeping c alive. + delete p; + +#if PN_CPP_HAS_CPP11 + { + std::shared_ptr<thread_safe<connection> > sp; + { + io::connection_engine e(cont, dummy_link_namer, new dummy_event_loop); + c = unwrap(e.connection()); + sp = make_shared_thread_safe(e.connection()); + } + ASSERT_EQUAL(1, pn_refcount(c)); // Engine gone, sp keeping c alive. + } + { + std::unique_ptr<thread_safe<connection> > up; + { + io::connection_engine e(cont, dummy_link_namer, new dummy_event_loop); + c = unwrap(e.connection()); + up = make_unique_thread_safe(e.connection()); + } + ASSERT_EQUAL(1, pn_refcount(c)); // Engine gone, sp keeping c alive. + } +#endif +} + +void test_convert() { + // Verify refcounts as expected with conversion between proton::object + // and thread_safe. + connection c; + pn_connection_t* pc = 0; + { + io::connection_engine eng(cont, dummy_link_namer, new dummy_event_loop); + c = eng.connection(); + pc = unwrap(c); // Unwrap in separate scope to avoid confusion from temp values. + } + { + ASSERT_EQUAL(1, pn_refcount(pc)); + returned<connection> pptr = make_thread_safe(c); + ASSERT_EQUAL(2, pn_refcount(pc)); + returned<connection> pp2 = pptr; + ASSERT(!pptr.release()); // Transferred to pp2 + ASSERT_EQUAL(2, pn_refcount(pc)); + connection c2 = pp2; // Transfer and convert to target + ASSERT_EQUAL(3, pn_refcount(pc)); // c, c2, thread_safe. + ASSERT(c == c2); + } + ASSERT_EQUAL(1, pn_refcount(pc)); // only c is left +} + +} + +int main(int, char**) { + int failed = 0; + RUN_TEST(failed, test_new()); + RUN_TEST(failed, test_convert()); + return failed; +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b8450d6/proton-c/bindings/python/docs/tutorial.rst ---------------------------------------------------------------------- diff --git a/proton-c/bindings/python/docs/tutorial.rst b/proton-c/bindings/python/docs/tutorial.rst index 302a3a4..ee8a12f 100644 --- a/proton-c/bindings/python/docs/tutorial.rst +++ b/proton-c/bindings/python/docs/tutorial.rst @@ -189,7 +189,7 @@ There are only two differences here. On line 13, instead of initiating a link (and implicitly a connection), we listen for incoming connections. On line 25, when we have received all the expected messages, we then stop listening for incoming connections by closing -the acceptor object. +the listener object. You can use the original send example now to send to this receiver directly. (Note: you will need to stop any broker that is listening on @@ -207,7 +207,7 @@ receiver to connect to it. Again that just requires two modifications: As with the modified receiver, instead of initiating establishment of a link, we listen for incoming connections on line 15 and then on line 28, when we have received confirmation of all the messages we sent, we -can close the acceptor in order to exit. The symmetry in the +can close the listener in order to exit. The symmetry in the underlying AMQP that enables this is quite unique and elegant, and in reflecting this the proton API provides a flexible toolkit for implementing all sorts of interesting intermediaries (the broker.py http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1b8450d6/tests/tools/apps/cpp/reactor_send.cpp ---------------------------------------------------------------------- diff --git a/tests/tools/apps/cpp/reactor_send.cpp b/tests/tools/apps/cpp/reactor_send.cpp index b99db0c..eae4d46 100644 --- a/tests/tools/apps/cpp/reactor_send.cpp +++ b/tests/tools/apps/cpp/reactor_send.cpp @@ -23,7 +23,7 @@ #include "proton/binary.hpp" #include "proton/connection.hpp" -#include "proton/container.hpp" +#include "proton/default_container.hpp" #include "proton/decoder.hpp" #include "proton/delivery.hpp" #include "proton/handler.hpp" @@ -36,10 +36,6 @@ #include <stdlib.h> #include <stdio.h> -#if __cplusplus < 201103L -#define override -#endif - class reactor_send : public proton::handler { private: std::string url_; @@ -65,12 +61,12 @@ class reactor_send : public proton::handler { message_.body(content); } - void on_container_start(proton::container &c) override { + void on_container_start(proton::container &c) PN_CPP_OVERRIDE { c.receiver_options(proton::receiver_options().credit_window(1024)); c.open_sender(url_); } - void on_sendable(proton::sender &sender) override { + void on_sendable(proton::sender &sender) PN_CPP_OVERRIDE { while (sender.credit() && sent_ < total_) { id_value_ = sent_ + 1; message_.correlation_id(id_value_); @@ -80,7 +76,7 @@ class reactor_send : public proton::handler { } } - void on_tracker_accept(proton::tracker &t) override { + void on_tracker_accept(proton::tracker &t) PN_CPP_OVERRIDE { confirmed_++; t.settle(); if (confirmed_ == total_) { @@ -90,7 +86,7 @@ class reactor_send : public proton::handler { } } - void on_message(proton::delivery &d, proton::message &msg) override { + void on_message(proton::delivery &d, proton::message &msg) PN_CPP_OVERRIDE { received_content_ = proton::get<proton::binary>(msg.body()); received_bytes_ += received_content_.size(); if (received_ < total_) { @@ -103,7 +99,7 @@ class reactor_send : public proton::handler { } } - void on_transport_close(proton::transport &) override { + void on_transport_close(proton::transport &) PN_CPP_OVERRIDE { sent_ = confirmed_; } }; @@ -122,7 +118,7 @@ int main(int argc, char **argv) { try { opts.parse(); reactor_send send(address, message_count, message_size, replying); - proton::container(send).run(); + proton::default_container(send).run(); return 0; } catch (const example::bad_option& e) { std::cout << opts << std::endl << e.what() << std::endl; --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
