PROTON-865: add timer tasks, cancellation, recurring_timer 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/705284bc Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/705284bc Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/705284bc Branch: refs/heads/proton-go Commit: 705284bc41fbb0849208a1f42845e0facab42c23 Parents: 911e9a2 Author: Clifford Jansen <[email protected]> Authored: Wed Sep 23 08:28:49 2015 -0700 Committer: Clifford Jansen <[email protected]> Committed: Wed Sep 23 08:33:44 2015 -0700 ---------------------------------------------------------------------- examples/cpp/CMakeLists.txt | 1 + examples/cpp/example_test.py | 11 ++ examples/cpp/recurring_timer.cpp | 101 +++++++++++++++++++ proton-c/bindings/cpp/CMakeLists.txt | 1 + .../bindings/cpp/include/proton/container.hpp | 4 + .../bindings/cpp/include/proton/handler.hpp | 5 + proton-c/bindings/cpp/include/proton/task.hpp | 40 ++++++++ proton-c/bindings/cpp/src/container.cpp | 2 + proton-c/bindings/cpp/src/container_impl.cpp | 12 +++ proton-c/bindings/cpp/src/container_impl.hpp | 1 + proton-c/bindings/cpp/src/handler.cpp | 2 + proton-c/bindings/cpp/src/task.cpp | 29 ++++++ 12 files changed, 209 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/705284bc/examples/cpp/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt index a367710..1ac1b1e 100644 --- a/examples/cpp/CMakeLists.txt +++ b/examples/cpp/CMakeLists.txt @@ -36,6 +36,7 @@ foreach(example client server server_direct + recurring_timer encode_decode) add_executable(${example} ${example}.cpp) target_link_libraries(${example} qpid-proton-cpp) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/705284bc/examples/cpp/example_test.py ---------------------------------------------------------------------- diff --git a/examples/cpp/example_test.py b/examples/cpp/example_test.py index dbb8e40..cc27a1f 100644 --- a/examples/cpp/example_test.py +++ b/examples/cpp/example_test.py @@ -223,5 +223,16 @@ Values: map{string("k1"):int(42), symbol(:"k2"):bool(false)} """ self.maxDiff = None self.assertEqual(expect, execute("encode_decode")) + + def test_recurring_timer(self): + expect="""Tick... +Tick... +Tock... +Tick... +Tock... +""" + self.maxDiff = None + self.assertEqual(expect, execute("recurring_timer", "-t", "3")) + if __name__ == "__main__": unittest.main() http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/705284bc/examples/cpp/recurring_timer.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/recurring_timer.cpp b/examples/cpp/recurring_timer.cpp new file mode 100644 index 0000000..b6141fd --- /dev/null +++ b/examples/cpp/recurring_timer.cpp @@ -0,0 +1,101 @@ +/* + * + * 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 "proton/container.hpp" +#include "proton/messaging_handler.hpp" +#include "proton/task.hpp" + +#include <iostream> +#include <map> + +class ticker : public proton::messaging_handler { + void on_timer_task(proton::event &e) { + std::cout << "Tick..." << std::endl; + } +}; + +class tocker : public proton::messaging_handler { + void on_timer_task(proton::event &e) { + std::cout << "Tock..." << std::endl; + } +}; + + +class recurring : public proton::messaging_handler { + private: + int remaining_secs; + ticker tick_handler; + tocker tock_handler; + proton::task *cancel_task; + public: + + recurring(int secs) : remaining_secs(secs), cancel_task(0) {} + + proton::task& ticktock(proton::event &e) { + // Show timer events in separate handlers. + e.container().schedule(250, &tick_handler); + return e.container().schedule(750, &tock_handler); + } + + void on_start(proton::event &e) { + if (remaining_secs <= 0) + return; + proton::task& first_tock = ticktock(e); + e.container().schedule(1000); + remaining_secs--; + // Show a cancel operation. + cancel_task = &first_tock; + e.container().schedule(500); + } + + void on_timer_task(proton::event &e) { + if (cancel_task) { + cancel_task->cancel(); + cancel_task = 0; + return; + } + if (remaining_secs) { + ticktock(e); + e.container().schedule(1000); + remaining_secs--; + } + } +}; + +int main(int argc, char **argv) { + // Command line options + int running_time_in_secs = 5; + options opts(argc, argv); + opts.add_value(running_time_in_secs, 't', "running time", "running time in seconds", "RUNTIME"); + try { + opts.parse(); + recurring recurring_handler(running_time_in_secs); + proton::container(recurring_handler).run(); + return 0; + } catch (const bad_option& e) { + std::cout << opts << std::endl << e.what() << std::endl; + } catch (const std::exception& e) { + std::cerr << e.what() << std::endl; + } + return 1; +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/705284bc/proton-c/bindings/cpp/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/CMakeLists.txt b/proton-c/bindings/cpp/CMakeLists.txt index fc3a37b..868bbb9 100644 --- a/proton-c/bindings/cpp/CMakeLists.txt +++ b/proton-c/bindings/cpp/CMakeLists.txt @@ -60,6 +60,7 @@ set(qpid-proton-cpp-source src/sender.cpp src/session.cpp src/sync_request_response.cpp + src/task.cpp src/terminus.cpp src/transport.cpp src/types.cpp http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/705284bc/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 78d8239..98754cf 100644 --- a/proton-c/bindings/cpp/include/proton/container.hpp +++ b/proton-c/bindings/cpp/include/proton/container.hpp @@ -38,6 +38,7 @@ class sender; class receiver; class link; class handler; +class task; class container_impl; /** @@ -81,6 +82,9 @@ class container /// The reactor associated with this container. PN_CPP_EXTERN class reactor& reactor(); + // Schedule a timer task event in delay milliseconds. + PN_CPP_EXTERN task& schedule(int delay, handler *h = 0); + private: pn_unique_ptr<container_impl> impl_; }; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/705284bc/proton-c/bindings/cpp/include/proton/handler.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/handler.hpp b/proton-c/bindings/cpp/include/proton/handler.hpp index cfd2689..65ff437 100644 --- a/proton-c/bindings/cpp/include/proton/handler.hpp +++ b/proton-c/bindings/cpp/include/proton/handler.hpp @@ -24,6 +24,7 @@ #include "proton/export.hpp" #include "proton/event.hpp" #include "proton/event.h" +#include "proton/reactor.h" #include <vector> namespace proton { @@ -54,6 +55,10 @@ class handler : public std::vector<handler*> { /// Add a child handler, equivalent to this->push_back(&h) /// h must not be deleted before this handler. PN_CPP_EXTERN virtual void add_child_handler(handler &h); + + private: + counted_ptr<pn_handler_t> pn_handler_; + friend class container_impl; }; } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/705284bc/proton-c/bindings/cpp/include/proton/task.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/task.hpp b/proton-c/bindings/cpp/include/proton/task.hpp new file mode 100644 index 0000000..6764f45 --- /dev/null +++ b/proton-c/bindings/cpp/include/proton/task.hpp @@ -0,0 +1,40 @@ +#ifndef PROTON_CPP_TASK_H +#define PROTON_CPP_TASK_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/export.hpp" +#include "proton/facade.hpp" + +#include "proton/reactor.h" + +namespace proton { + +/** A task for timer events */ +class task : public counted_facade<pn_task_t, task> { + public: + /** Cancel the scheduled task. */ + PN_CPP_EXTERN void cancel(); +}; + +} + +#endif /*!PROTON_CPP_TASK_H*/ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/705284bc/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 574f5a7..f9dc06e 100644 --- a/proton-c/bindings/cpp/src/container.cpp +++ b/proton-c/bindings/cpp/src/container.cpp @@ -70,4 +70,6 @@ acceptor& container::listen(const proton::url &url) { void container::link_prefix(const std::string& s) { impl_->prefix_ = s; } std::string container::link_prefix() { return impl_->prefix_; } +task& container::schedule(int delay, handler *h) { return impl_->schedule(delay, h); } + } // namespace proton http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/705284bc/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 index ca864a7..3aab33f 100644 --- a/proton-c/bindings/cpp/src/container_impl.cpp +++ b/proton-c/bindings/cpp/src/container_impl.cpp @@ -29,6 +29,7 @@ #include "proton/url.hpp" #include "proton/sender.hpp" #include "proton/receiver.hpp" +#include "proton/task.hpp" #include "msg.hpp" #include "container_impl.hpp" @@ -101,6 +102,8 @@ class override_handler : public handler counted_ptr<pn_handler_t> container_impl::cpp_handler(handler *h) { + if (h->pn_handler_) + return h->pn_handler_; counted_ptr<pn_handler_t> handler( pn_handler_new(&handler_context::dispatch, sizeof(struct handler_context), &handler_context::cleanup), @@ -108,6 +111,7 @@ counted_ptr<pn_handler_t> container_impl::cpp_handler(handler *h) handler_context &hc = handler_context::get(handler.get()); hc.container_ = &container_; hc.handler_ = h; + h->pn_handler_ = handler; return handler; } @@ -186,4 +190,12 @@ std::string container_impl::next_link_name() { return s.str(); } +task& container_impl::schedule(int delay, handler *h) { + counted_ptr<pn_handler_t> task_handler; + if (h) + task_handler = cpp_handler(h); + task *t = task::cast(pn_reactor_schedule(pn_cast(reactor_.get()), delay, task_handler.get())); + return *t; +} + } http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/705284bc/proton-c/bindings/cpp/src/container_impl.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/container_impl.hpp b/proton-c/bindings/cpp/src/container_impl.hpp index dda41e7..6210b23 100644 --- a/proton-c/bindings/cpp/src/container_impl.hpp +++ b/proton-c/bindings/cpp/src/container_impl.hpp @@ -53,6 +53,7 @@ class container_impl PN_CPP_EXTERN duration timeout(); PN_CPP_EXTERN void timeout(duration timeout); + task& schedule(int delay, handler *h); counted_ptr<pn_handler_t> cpp_handler(handler *h); std::string next_link_name(); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/705284bc/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 8e0f675..d045dbd 100644 --- a/proton-c/bindings/cpp/src/handler.cpp +++ b/proton-c/bindings/cpp/src/handler.cpp @@ -23,6 +23,8 @@ namespace proton { +// container_impl.cpp sets pn_handler_ as needed. + handler::handler() {} handler::~handler() {} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/705284bc/proton-c/bindings/cpp/src/task.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/task.cpp b/proton-c/bindings/cpp/src/task.cpp new file mode 100644 index 0000000..6e6b4a6 --- /dev/null +++ b/proton-c/bindings/cpp/src/task.cpp @@ -0,0 +1,29 @@ +/* + * + * 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/task.hpp" +#include "proton/reactor.h" + +namespace proton { + +void task::cancel() { pn_task_cancel(pn_cast(this)); } + +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
