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 <cliffjan...@apache.org>
Authored: Wed Sep 23 08:28:49 2015 -0700
Committer: Clifford Jansen <cliffjan...@apache.org>
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: commits-unsubscr...@qpid.apache.org
For additional commands, e-mail: commits-h...@qpid.apache.org

Reply via email to