qpid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From acon...@apache.org
Subject [7/7] qpid-proton git commit: PROTON-865: C++ reactor binding for proton.
Date Fri, 04 Sep 2015 19:14:34 GMT
PROTON-865: C++ reactor binding for proton.

This is a C++ interface to proton, providing an event-driven API similar to the
python reactive API.

Each of the proton "classes" such as pn_link_t, pn_connection_t etc. is
represented by a C++ "facade" class that provides the relevant member
functions. These classes take up no memory, they are actually pointers to the
proton C structs with some casting magic to translate C++ member function calls
into C function calls.

A C++ smart pointer, proton::counted_ptr, automates proton reference
counting. It can be converted automatically to standard C++ shared_ptr,
unique_ptr etc. with the expected semantics.

The goal is to provide very low overhead access to the proton C library with the
convenience and safety of C++. There is no additional memory allocation or
reference counting imposed by the C++ layer. It is possible to mix C and C++
code.

The C++ documentation includes a tutorial and examples similar to the python
tutorial/examples.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/445f8873
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/445f8873
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/445f8873

Branch: refs/heads/master
Commit: 445f8873968e2317218ec348444284a4bd7c8be0
Parents: f37e2af
Author: Alan Conway <aconway@redhat.com>
Authored: Fri Sep 4 15:13:46 2015 -0400
Committer: Alan Conway <aconway@redhat.com>
Committed: Fri Sep 4 15:13:46 2015 -0400

----------------------------------------------------------------------
 CMakeLists.txt                                  |   21 +-
 docs/markdown/memory_management.md              |   18 +-
 examples/CMakeLists.txt                         |    3 +
 examples/cpp/CMakeLists.txt                     |   55 +
 examples/cpp/README.hpp                         |  120 ++
 examples/cpp/broker.cpp                         |  215 +++
 examples/cpp/client.cpp                         |   96 +
 examples/cpp/direct_recv.cpp                    |   86 +
 examples/cpp/direct_send.cpp                    |   93 +
 examples/cpp/encode_decode.cpp                  |  261 +++
 examples/cpp/example_test.py                    |  228 +++
 examples/cpp/helloworld.cpp                     |   66 +
 examples/cpp/helloworld_blocking.cpp            |   52 +
 examples/cpp/helloworld_direct.cpp              |   74 +
 examples/cpp/options.hpp                        |  173 ++
 examples/cpp/server.cpp                         |   86 +
 examples/cpp/server_direct.cpp                  |  105 ++
 examples/cpp/simple_recv.cpp                    |   85 +
 examples/cpp/simple_send.cpp                    |   90 +
 examples/cpp/sync_client.cpp                    |   67 +
 examples/go/README.md                           |   69 -
 examples/go/event/broker.go                     |  255 ---
 examples/go/receive.go                          |  176 --
 examples/go/send.go                             |  158 --
 proton-c/CMakeLists.txt                         |   71 +-
 proton-c/bindings/CMakeLists.txt                |  175 +-
 proton-c/bindings/cpp/CMakeLists.txt            |  151 ++
 proton-c/bindings/cpp/README.md                 |   40 +
 proton-c/bindings/cpp/docs/CMakeLists.txt       |   33 +
 proton-c/bindings/cpp/docs/mainpage.md          |  123 ++
 proton-c/bindings/cpp/docs/tutorial.hpp         |  427 +++++
 proton-c/bindings/cpp/docs/user.doxygen.in      | 1702 ++++++++++++++++++
 .../bindings/cpp/include/proton/acceptor.hpp    |   43 +
 proton-c/bindings/cpp/include/proton/acking.hpp |   50 +
 .../cpp/include/proton/blocking_connection.hpp  |   62 +
 .../cpp/include/proton/blocking_link.hpp        |   57 +
 .../cpp/include/proton/blocking_receiver.hpp    |   62 +
 .../cpp/include/proton/blocking_sender.hpp      |   50 +
 .../bindings/cpp/include/proton/comparable.hpp  |   38 +
 proton-c/bindings/cpp/include/proton/config.hpp |   57 +
 .../bindings/cpp/include/proton/connection.hpp  |   81 +
 .../bindings/cpp/include/proton/container.hpp   |   90 +
 .../bindings/cpp/include/proton/counted.hpp     |   48 +
 .../bindings/cpp/include/proton/counted_ptr.hpp |  117 ++
 proton-c/bindings/cpp/include/proton/data.hpp   |  130 ++
 .../bindings/cpp/include/proton/decoder.hpp     |  234 +++
 .../bindings/cpp/include/proton/delivery.hpp    |   72 +
 .../bindings/cpp/include/proton/duration.hpp    |   53 +
 .../bindings/cpp/include/proton/encoder.hpp     |  187 ++
 .../bindings/cpp/include/proton/endpoint.hpp    |   66 +
 proton-c/bindings/cpp/include/proton/error.hpp  |   45 +
 proton-c/bindings/cpp/include/proton/event.hpp  |   69 +
 proton-c/bindings/cpp/include/proton/export.hpp |   49 +
 proton-c/bindings/cpp/include/proton/facade.hpp |  145 ++
 .../bindings/cpp/include/proton/handler.hpp     |   61 +
 proton-c/bindings/cpp/include/proton/link.hpp   |  107 ++
 proton-c/bindings/cpp/include/proton/memory.hpp |   33 +
 .../bindings/cpp/include/proton/message.hpp     |  225 +++
 .../cpp/include/proton/messaging_adapter.hpp    |   78 +
 .../cpp/include/proton/messaging_event.hpp      |  108 ++
 .../cpp/include/proton/messaging_handler.hpp    |  110 ++
 .../cpp/include/proton/proton_event.hpp         |  296 +++
 .../cpp/include/proton/proton_handler.hpp       |   86 +
 .../bindings/cpp/include/proton/reactor.hpp     |   75 +
 .../bindings/cpp/include/proton/receiver.hpp    |   46 +
 proton-c/bindings/cpp/include/proton/sender.hpp |   49 +
 .../bindings/cpp/include/proton/session.hpp     |   83 +
 .../include/proton/sync_request_response.hpp    |   63 +
 .../bindings/cpp/include/proton/terminus.hpp    |   77 +
 .../bindings/cpp/include/proton/transport.hpp   |   45 +
 .../bindings/cpp/include/proton/type_traits.hpp |  118 ++
 proton-c/bindings/cpp/include/proton/types.hpp  |  248 +++
 proton-c/bindings/cpp/include/proton/url.hpp    |  128 ++
 proton-c/bindings/cpp/src/acceptor.cpp          |   30 +
 .../bindings/cpp/src/blocking_connection.cpp    |   39 +
 .../cpp/src/blocking_connection_impl.cpp        |  103 ++
 .../cpp/src/blocking_connection_impl.hpp        |   60 +
 proton-c/bindings/cpp/src/blocking_fetcher.cpp  |   66 +
 proton-c/bindings/cpp/src/blocking_fetcher.hpp  |   48 +
 proton-c/bindings/cpp/src/blocking_link.cpp     |   85 +
 proton-c/bindings/cpp/src/blocking_receiver.cpp |  102 ++
 proton-c/bindings/cpp/src/blocking_sender.cpp   |   68 +
 proton-c/bindings/cpp/src/connection.cpp        |   82 +
 proton-c/bindings/cpp/src/connector.cpp         |   62 +
 proton-c/bindings/cpp/src/connector.hpp         |   58 +
 proton-c/bindings/cpp/src/container.cpp         |   73 +
 proton-c/bindings/cpp/src/container_impl.cpp    |  181 ++
 proton-c/bindings/cpp/src/container_impl.hpp    |   77 +
 proton-c/bindings/cpp/src/contexts.cpp          |  116 ++
 proton-c/bindings/cpp/src/contexts.hpp          |   61 +
 proton-c/bindings/cpp/src/conversion_test.cpp   |   74 +
 proton-c/bindings/cpp/src/data.cpp              |  134 ++
 proton-c/bindings/cpp/src/decoder.cpp           |  328 ++++
 proton-c/bindings/cpp/src/delivery.cpp          |   38 +
 proton-c/bindings/cpp/src/duration.cpp          |   31 +
 proton-c/bindings/cpp/src/encoder.cpp           |  135 ++
 proton-c/bindings/cpp/src/endpoint.cpp          |   38 +
 proton-c/bindings/cpp/src/error.cpp             |   34 +
 proton-c/bindings/cpp/src/event.cpp             |   71 +
 proton-c/bindings/cpp/src/facade.cpp            |   71 +
 proton-c/bindings/cpp/src/grep                  |   47 +
 proton-c/bindings/cpp/src/handler.cpp           |   35 +
 proton-c/bindings/cpp/src/interop_test.cpp      |  123 ++
 proton-c/bindings/cpp/src/link.cpp              |   92 +
 proton-c/bindings/cpp/src/message.cpp           |  215 +++
 proton-c/bindings/cpp/src/messaging_adapter.cpp |  395 ++++
 proton-c/bindings/cpp/src/messaging_event.cpp   |  150 ++
 proton-c/bindings/cpp/src/messaging_handler.cpp |  122 ++
 proton-c/bindings/cpp/src/msg.hpp               |   58 +
 proton-c/bindings/cpp/src/proton_bits.cpp       |   56 +
 proton-c/bindings/cpp/src/proton_bits.hpp       |   45 +
 proton-c/bindings/cpp/src/proton_event.cpp      |  183 ++
 proton-c/bindings/cpp/src/proton_handler.cpp    |   73 +
 proton-c/bindings/cpp/src/reactor.cpp           |   57 +
 proton-c/bindings/cpp/src/receiver.cpp          |   38 +
 proton-c/bindings/cpp/src/sender.cpp            |   59 +
 proton-c/bindings/cpp/src/session.cpp           |   78 +
 .../bindings/cpp/src/sync_request_response.cpp  |   57 +
 proton-c/bindings/cpp/src/terminus.cpp          |   68 +
 proton-c/bindings/cpp/src/test_bits.hpp         |   48 +
 proton-c/bindings/cpp/src/transport.cpp         |   31 +
 proton-c/bindings/cpp/src/types.cpp             |   96 +
 proton-c/bindings/cpp/src/url.cpp               |  114 ++
 proton-c/bindings/cpp/src/uuid.cpp              |   59 +
 proton-c/bindings/cpp/src/uuid.hpp              |   39 +
 proton-c/bindings/go/README.md                  |    5 -
 proton-c/docs/api/user.doxygen.in               |    4 +-
 proton-c/include/proton/codec.h                 |   20 +-
 proton-c/include/proton/event.h                 |    3 +-
 proton-c/include/proton/handlers.h              |    1 -
 proton-c/include/proton/reactor.h               |    1 -
 proton-c/include/proton/selectable.h            |    1 +
 proton-c/src/codec/codec.c                      |   10 +-
 proton-c/src/windows/io.c                       |   13 +-
 134 files changed, 13050 insertions(+), 826 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/445f8873/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cfe5566..5ef9f56 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,16 +20,15 @@ cmake_minimum_required (VERSION 2.6)
 
 project (Proton C)
 
+# Enable C++ now for examples and bindings subdirectories, but make it optional.
+enable_language(CXX OPTIONAL)
+
 if (MSVC)
   # No C99 capability, use C++
   set(DEFAULT_BUILD_WITH_CXX ON)
 endif (MSVC)
 option(BUILD_WITH_CXX "Compile Proton using C++" ${DEFAULT_BUILD_WITH_CXX})
 
-if (BUILD_WITH_CXX)
-  enable_language (CXX)
-endif (BUILD_WITH_CXX)
-
 if (CMAKE_CONFIGURATION_TYPES)
   # There is no single "build type"...
   message(STATUS "Build types are ${CMAKE_CONFIGURATION_TYPES}")
@@ -140,7 +139,21 @@ if (BUILD_JAVA)
   add_subdirectory(proton-j)
 endif()
 
+# Check for valgrind here so tests under proton-c/ and examples/ can use it.
+find_program(VALGRIND_EXE valgrind DOC "Location of the valgrind program")
+option(ENABLE_VALGRIND "Use valgrind to detect run-time problems" ON)
+if (ENABLE_VALGRIND)
+  if (NOT VALGRIND_EXE)
+    message(STATUS "Can't locate the valgrind command; no run-time error detection")
+  else ()
+    set (VALGRIND_ENV "VALGRIND=${VALGRIND_EXE}")
+  endif ()
+endif (ENABLE_VALGRIND)
+
+mark_as_advanced (VALGRIND_EXE)
+
 add_subdirectory(proton-c)
+add_subdirectory(examples)
 
 install (FILES LICENSE README.md TODO
          DESTINATION ${PROTON_SHARE})

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/445f8873/docs/markdown/memory_management.md
----------------------------------------------------------------------
diff --git a/docs/markdown/memory_management.md b/docs/markdown/memory_management.md
index e81318f..5a70911 100644
--- a/docs/markdown/memory_management.md
+++ b/docs/markdown/memory_management.md
@@ -1,7 +1,3 @@
-
-*Warning*: contains remarks about unreleased (but design-complete as far as the
-remarks are concerned) C++ and Go bindings.
-
 Proton memory mangement
 =======================
 
@@ -69,9 +65,9 @@ The proton C API has standard reference counting rules (but see [1] below)
 
 - A pointer *returned* by a `pn_` function is either *borrowed* by the caller,
   or the caller *owns* a reference (the API doc says which.)
-- The owner of a reference must call `pn_object_decref()` exactly once to
+- The owner of a reference must call `pn_decref()` exactly once to
   release it.
-- To keep a borrowed pointer, call `pn_object_incref()`. This adds a new
+- To keep a borrowed pointer, call `pn_incref()`. This adds a new
   reference, which you now own.
 - A pointer *passed* to a `pn_` function has no change of ownership. If you
   owned a reference you still do, if you didn't you still don't.
@@ -80,7 +76,7 @@ The proton C API has standard reference counting rules (but see [1] below)
 
 A *borrowed* pointer is valid within some scope (typically the scope of an event
 handling function) but beyond that scope you cannot assume it is valid unless
-you make a new reference with `pn_object_incref`. The API documentation for the
+you make a new reference with `pn_incref`. The API documentation for the
 function that returned the pointer should tell you what the scope is.
 
 There are "container" relationships in proton: e.g. a connection contains
@@ -96,11 +92,11 @@ container are released [1]. This is useful for bindings to langauges with
 objects in memory for as long as any binding object needs them.
 
 For example: if you call `pn_message()` then you *own* a reference to the
-newly-created `pn_message_t` and you must call `pn_object_decref` when you are
+newly-created `pn_message_t` and you must call `pn_decref` when you are
 done [2]. If you call `pn_event_link()` in an event handler then you get a
 *borrowed* reference to the link. You can use it in the scope of the event
-handler, but if you want to save it for later you must call `pn_object_incref`
-to add a reference and of course call `pn_object_decref` when you are done with
+handler, but if you want to save it for later you must call `pn_incref`
+to add a reference and of course call `pn_decref` when you are done with
 that reference.
 
 [1] *Internally* the proton library plays tricks with reference counts to
@@ -111,7 +107,7 @@ implementation of the proton C library itself you may need to learn more, ask on
 proton@qpid.apache.org.
 
 [2] Actually if you call `pn_message()` then you must *either* call
-`pn_object_decref()` *or* `pn_message_free()`, definitely not both. It is
+`pn_decref()` *or* `pn_message_free()`, definitely not both. It is
 possible to mix reference couting and 'free' style memory management in the same
 codebase (`free` is sort-of an alias for `decref`) but it is probably not a good
 idea.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/445f8873/examples/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index feac758..5724e59 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -21,3 +21,6 @@ set (Proton_DIR ${CMAKE_CURRENT_SOURCE_DIR})
 
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
 add_subdirectory(c/messenger)
+if (BUILD_CPP)
+  add_subdirectory(cpp)
+endif()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/445f8873/examples/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt
new file mode 100644
index 0000000..77cc9c5
--- /dev/null
+++ b/examples/cpp/CMakeLists.txt
@@ -0,0 +1,55 @@
+#
+# 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_directories(
+  "${CMAKE_SOURCE_DIR}/proton-c/include"
+  "${CMAKE_SOURCE_DIR}/proton-c/bindings/cpp/include")
+
+foreach(example
+    broker
+    helloworld
+    helloworld_blocking
+    helloworld_direct
+    simple_recv
+    simple_send
+    direct_recv
+    direct_send
+    sync_client
+    client
+    server
+    server_direct
+    encode_decode)
+  add_executable(${example} ${example}.cpp)
+  target_link_libraries(${example} qpid-proton-cpp)
+  set_source_files_properties(${example}.cpp PROPERTIES COMPILE_FLAGS "${CXX_WARNING_FLAGS}")
+endforeach()
+
+set(env_py "${CMAKE_SOURCE_DIR}/proton-c/env.py")
+set(test_bin_dir "$<TARGET_FILE_DIR:broker>")
+if (WIN32)
+  # Ignore existing path (usualy containting spaces, escape chars).
+  # Choose just enough path for Windows, ';' separated.
+  set(test_path "${test_bin_dir}" "$<TARGET_FILE_DIR:qpid-proton>" "$<TARGET_FILE_DIR:qpid-proton-cpp>")
+else(WIN32)
+  # ':' separated path with test_bin_dir first.
+  set(test_path "${test_bin_dir}:$ENV{PATH}")
+endif(WIN32)
+
+add_test(NAME cpp_example_test
+  COMMAND ${PYTHON_EXECUTABLE} ${env_py} -- "PATH=${test_path}" "PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR}" ${VALGRIND_ENV} ${PYTHON_EXECUTABLE} -m unittest -v example_test)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/445f8873/examples/cpp/README.hpp
----------------------------------------------------------------------
diff --git a/examples/cpp/README.hpp b/examples/cpp/README.hpp
new file mode 100644
index 0000000..d2a51eb
--- /dev/null
+++ b/examples/cpp/README.hpp
@@ -0,0 +1,120 @@
+// Examples overview.
+//
+// For a better overview, see the tutorial in the generated documentation.
+// In your build directory do:
+//     make docs-cpp
+// then open proton-c/bindings/cpp/docs/html/tutorial.html in your browser.
+//
+
+// DEVELOPER NOTE: if you are adding or modifying examples you should keep this
+// file and ../proton-c/bindings/cpp/docs/tutorial.hpp up to date.
+
+/** \example broker.cpp
+
+A very simple "mini broker". You can use this to run other examples that reqiure
+an intermediary, or you can use any AMQP 1.0 broker. This broker creates queues
+automatically when a client tries to send or subscribe.
+
+*/
+
+/** \example helloworld.cpp
+
+Basic example that connects to an intermediary on 127.0.0.1:5672,
+establishes a subscription from the 'examples' nodeu on that
+intermediary, then creates a sending link to the same node and sends
+one message. On receving the message back via the subcription, the
+connection is closed.
+
+*/
+
+/** \example helloworld_direct.cpp
+
+A variant of the basic helloworld example, that does not use an
+intermediary, but listens for incoming connections itself. It
+establishes a connection to itself with a link over which a single
+message is sent. This demonstrates the ease with which a simple daemon
+can be built using the API.
+
+*/
+
+/** \example helloworld_blocking.cpp
+
+The same as the basic helloworld.cpp, but using a
+synchronous/sequential style wrapper on top of the
+asynchronous/reactive API. The purpose of this example is just to show
+how different functionality can be easily layered should it be
+desired.
+
+*/
+
+/** \example simple_send.cpp
+
+An example of sending a fixed number of messages and tracking their
+(asynchronous) acknowledgement. Messages are sent through the 'examples' node on
+an intermediary accessible on 127.0.0.1:5672.
+
+*/
+
+/** \example simple_recv.cpp
+
+Subscribes to the 'examples' node on an intermediary accessible
+on 127.0.0.1:5672. Simply prints out the body of received messages.
+
+*/
+
+/** \example direct_send.cpp
+
+Accepts an incoming connection and then sends like `simple_send`.  You can
+connect directly to `direct_send` *without* a broker using \ref simple_recv.cpp.
+Make sure to stop the broker first or use a different port for `direct_send`.
+
+*/
+
+/** \example direct_recv.cpp
+
+Accepts an incoming connection and then receives like `simple_recv`.  You can
+connect directly to `direct_recv` *without* a broker using \ref simple_send.cpp.
+Make sure to stop the broker first or use a different port for `direct_recv`.
+
+*/
+
+/** \example encode_decode.cpp
+
+Shows how C++ data types can be converted to and from AMQP types.
+
+*/
+
+/** \example client.cpp
+
+The client part of a request-response example. Sends requests and
+prints out responses. Requires an intermediary that supports the AMQP
+1.0 dynamic nodes on which the responses are received. The requests
+are sent through the 'examples' node.
+
+*/
+
+/** \example server.cpp
+
+The server part of a request-response example, that receives requests
+via the examples node, converts the body to uppercase and sends the
+result back to the indicated reply address.
+
+*/
+
+/** \example server_direct.cpp
+
+A variant of the server part of a request-response example, that
+accepts incoming connections and does not need an intermediary. Much
+like the original server, it receives incoming requests, converts the
+body to uppercase and sends the result back to the indicated reply
+address. Can be used in conjunction with any of the client
+alternatives.
+
+*/
+
+/** \example sync_client.cpp
+
+A variant of the client part, that uses a blocking/synchronous style
+instead of the reactive/asynchronous style.
+
+*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/445f8873/examples/cpp/broker.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/broker.cpp b/examples/cpp/broker.cpp
new file mode 100644
index 0000000..7f32650
--- /dev/null
+++ b/examples/cpp/broker.cpp
@@ -0,0 +1,215 @@
+/*
+ *
+ * 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/acceptor.hpp"
+#include "proton/container.hpp"
+#include "proton/messaging_handler.hpp"
+#include "proton/url.hpp"
+
+#include <iostream>
+#include <sstream>
+#include <deque>
+#include <map>
+#include <list>
+#include <string>
+
+class queue {
+  public:
+    bool dynamic;
+    typedef std::deque<proton::message_value> message_queue;
+    typedef std::list<proton::counted_ptr<proton::sender> > sender_list;
+    message_queue messages;
+    sender_list consumers;
+
+    queue(bool dyn = false) : dynamic(dyn) {}
+
+    void subscribe(proton::sender &c) {
+        consumers.push_back(c.ptr());
+    }
+
+    bool unsubscribe(proton::sender &c) {
+        consumers.remove(c.ptr());
+        return (consumers.size() == 0 && (dynamic || messages.size() == 0));
+    }
+
+    void publish(const proton::message_value &m) {
+        messages.push_back(m);
+        dispatch(0);
+    }
+
+    void dispatch(proton::sender *s) {
+        while (deliver_to(s)) {}
+    }
+
+    bool deliver_to(proton::sender *consumer) {
+        // deliver to single consumer if supplied, else all consumers
+        int count = consumer ? 1 : consumers.size();
+        if (!count) return false;
+        bool result = false;
+        sender_list::iterator it = consumers.begin();
+        if (!consumer && count)
+            consumer = it->get();
+
+        while (messages.size()) {
+            if (consumer->credit()) {
+                consumer->send(messages.front());
+                messages.pop_front();
+                result = true;
+            }
+            if (--count)
+                it++;
+            else
+                return result;
+        }
+        return false;
+    }
+};
+
+class broker : public proton::messaging_handler {
+  private:
+    typedef std::map<std::string, queue *> queue_map;
+    proton::url url;
+    queue_map queues;
+    uint64_t queue_count;       // Use to generate unique queue IDs.
+
+  public:
+
+    broker(const proton::url &u) : url(u), queue_count(0) {}
+
+    void on_start(proton::event &e) {
+        e.container().listen(url);
+        std::cout << "broker listening on " << url << std::endl;
+    }
+
+    class queue &get_queue(std::string &address) {
+        queue_map::iterator it = queues.find(address);
+        if (it == queues.end()) {
+            queues[address] = new queue();
+            return *queues[address];
+        }
+        else {
+            return *it->second;
+        }
+    }
+
+    std::string queue_name() {
+        std::ostringstream os;
+        os << "q" << queue_count++;
+        return os.str();
+    }
+
+    void on_link_opening(proton::event &e) {
+        proton::link& lnk = e.link();
+        if (lnk.is_sender()) {
+            proton::sender &sender(lnk.sender());
+            proton::terminus &remote_source(lnk.remote_source());
+            if (remote_source.is_dynamic()) {
+                std::string address = queue_name();
+                lnk.source().address(address);
+                queue *q = new queue(true);
+                queues[address] = q;
+                q->subscribe(sender);
+                std::cout << "broker dynamic outgoing link from " << address << std::endl;
+            }
+            else {
+                std::string address = remote_source.address();
+                if (!address.empty()) {
+                    lnk.source().address(address);
+                    get_queue(address).subscribe(sender);
+                    std::cout << "broker outgoing link from " << address << std::endl;
+                }
+            }
+        }
+        else {
+            std::string address = lnk.remote_target().address();
+            if (!address.empty())
+                lnk.target().address(address);
+            std::cout << "broker incoming link to " << address << std::endl;
+        }
+    }
+
+    void unsubscribe (proton::sender &lnk) {
+        std::string address = lnk.source().address();
+        queue_map::iterator it = queues.find(address);
+        if (it != queues.end() && it->second->unsubscribe(lnk)) {
+            delete it->second;
+            queues.erase(it);
+        }
+    }
+
+    void on_link_closing(proton::event &e) {
+        proton::link &lnk = e.link();
+        if (lnk.is_sender()) {
+            unsubscribe(lnk.sender());
+        }
+    }
+
+    void on_connection_closing(proton::event &e) {
+        remove_stale_consumers(e.connection());
+    }
+
+    void on_disconnected(proton::event &e) {
+        remove_stale_consumers(e.connection());
+    }
+
+    void remove_stale_consumers(proton::connection &connection) {
+        proton::link *l = connection.link_head(proton::endpoint::REMOTE_ACTIVE);
+        while (l) {
+            if (l->is_sender()) {
+                unsubscribe(l->sender());
+            }
+            l = l->next(proton::endpoint::REMOTE_ACTIVE);
+        }
+    }
+
+    void on_sendable(proton::event &e) {
+        proton::link& lnk = e.link();
+        std::string addr = lnk.source().address();
+        proton::sender &s(lnk.sender());
+        get_queue(addr).dispatch(&s);
+    }
+
+    void on_message(proton::event &e) {
+        std::string addr = e.link().target().address();
+        proton::message_value msg = e.message();
+        get_queue(addr).publish(msg);
+    }
+};
+
+int main(int argc, char **argv) {
+    // Command line options
+    proton::url url("0.0.0.0");
+    options opts(argc, argv);
+    opts.add_value(url, 'a', "address", "listen on URL", "URL");
+    try {
+        opts.parse();
+        broker broker(url);
+        proton::container(broker).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/445f8873/examples/cpp/client.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/client.cpp b/examples/cpp/client.cpp
new file mode 100644
index 0000000..21c83f8
--- /dev/null
+++ b/examples/cpp/client.cpp
@@ -0,0 +1,96 @@
+/*
+ *
+ * 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/connection.hpp"
+
+#include <iostream>
+#include <vector>
+
+class client : public proton::messaging_handler {
+  private:
+    proton::url url;
+    std::vector<std::string> requests;
+    proton::counted_ptr<proton::sender> sender;
+    proton::counted_ptr<proton::receiver> receiver;
+
+  public:
+    client(const proton::url &u, const std::vector<std::string>& r) : url(u), requests(r) {}
+
+    void on_start(proton::event &e) {
+        sender = e.container().create_sender(url).ptr();
+        // Create a receiver with a dynamically chosen unique address.
+        receiver = sender->connection().create_receiver("", true/*dynamic*/).ptr();
+    }
+
+    void send_request() {
+        proton::message_value req;
+        req.body(requests.front());
+        req.reply_to(receiver->remote_source().address());
+        sender->send(req);
+    }
+
+    void on_link_opened(proton::event &e) {
+        if (&e.link() == receiver.get())
+            send_request();
+    }
+
+    void on_message(proton::event &e) {
+        if (requests.empty()) return; // Spurious extra message!
+        proton::message& response = e.message();
+        std::cout << '"' << requests.front() << '"' << " => " << response.body() << std::endl;
+        requests.erase(requests.begin());
+        if (!requests.empty()) {
+            send_request();
+        } else {
+            e.connection().close();
+        }
+    }
+};
+
+int main(int argc, char **argv) {
+    // Command line options
+    proton::url url("127.0.0.1:5672/examples");
+    options opts(argc, argv);
+    opts.add_value(url, 'a', "address", "connect and send to URL", "URL");
+
+    try {
+        opts.parse();
+
+        std::vector<std::string> requests;
+        requests.push_back("Twas brillig, and the slithy toves");
+        requests.push_back("Did gire and gymble in the wabe.");
+        requests.push_back("All mimsy were the borogroves,");
+        requests.push_back("And the mome raths outgrabe.");
+
+        client c(url, requests);
+        proton::container(c).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/445f8873/examples/cpp/direct_recv.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/direct_recv.cpp b/examples/cpp/direct_recv.cpp
new file mode 100644
index 0000000..b6e0e9e
--- /dev/null
+++ b/examples/cpp/direct_recv.cpp
@@ -0,0 +1,86 @@
+/*
+ *
+ * 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/acceptor.hpp"
+#include "proton/messaging_handler.hpp"
+#include "proton/link.hpp"
+#include "proton/url.hpp"
+
+#include <iostream>
+#include <map>
+
+class direct_recv : public proton::messaging_handler {
+  private:
+    proton::url url;
+    int expected;
+    int received;
+    proton::counted_ptr<proton::acceptor> acceptor;
+
+  public:
+    direct_recv(const std::string &s, int c) : url(s), expected(c), received(0) {}
+
+    void on_start(proton::event &e) {
+        acceptor = e.container().listen(url).ptr();
+        std::cout << "direct_recv listening on " << url << std::endl;
+    }
+
+    void on_message(proton::event &e) {
+        proton::message& msg = e.message();
+        proton::data_value id = msg.id();
+        if (id.type() == proton::ULONG) {
+            if (id.get<int>() < received)
+                return; // ignore duplicate
+        }
+        if (expected == 0 || received < expected) {
+            std::cout << msg.body() << std::endl;
+            received++;
+        }
+        if (received == expected) {
+            e.receiver().close();
+            e.connection().close();
+            if (acceptor) acceptor->close();
+        }
+    }
+};
+
+int main(int argc, char **argv) {
+    // Command line options
+    std::string address("127.0.0.1:5672/examples");
+    int message_count = 100;
+    options opts(argc, argv);
+    opts.add_value(address, 'a', "address", "listen and receive on URL", "URL");
+    opts.add_value(message_count, 'm', "messages", "receive COUNT messages", "COUNT");
+    try {
+        opts.parse();
+        direct_recv recv(address, message_count);
+        proton::container(recv).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/445f8873/examples/cpp/direct_send.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/direct_send.cpp b/examples/cpp/direct_send.cpp
new file mode 100644
index 0000000..02bc372
--- /dev/null
+++ b/examples/cpp/direct_send.cpp
@@ -0,0 +1,93 @@
+/*
+ *
+ * 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/acceptor.hpp"
+#include "proton/connection.hpp"
+#include "proton/container.hpp"
+#include "proton/messaging_handler.hpp"
+
+#include <iostream>
+#include <map>
+
+class simple_send : public proton::messaging_handler {
+  private:
+    proton::url url;
+    int sent;
+    int confirmed;
+    int total;
+    proton::counted_ptr<proton::acceptor> acceptor;
+  public:
+
+    simple_send(const std::string &s, int c) : url(s), sent(0), confirmed(0), total(c) {}
+
+    void on_start(proton::event &e) {
+        acceptor = e.container().listen(url).ptr();
+        std::cout << "direct_send listening on " << url << std::endl;
+    }
+
+    void on_sendable(proton::event &e) {
+        proton::sender& sender = e.sender();
+        while (sender.credit() && sent < total) {
+            proton::message_value msg;
+            msg.id(proton::data_value(sent + 1));
+            std::map<std::string, int> m;
+            m["sequence"] = sent+1;
+            msg.body(proton::as<proton::MAP>(m));
+            sender.send(msg);
+            sent++;
+        }
+    }
+
+    void on_accepted(proton::event &e) {
+        confirmed++;
+        if (confirmed == total) {
+            std::cout << "all messages confirmed" << std::endl;
+            e.connection().close();
+            acceptor->close();
+        }
+    }
+
+    void on_disconnected(proton::event &e) {
+        sent = confirmed;
+    }
+};
+
+int main(int argc, char **argv) {
+    // Command line options
+    std::string address("127.0.0.1:5672/examples");
+    int message_count = 100;
+    options opts(argc, argv);
+    opts.add_value(address, 'a', "address", "listen and send on URL", "URL");
+    opts.add_value(message_count, 'm', "messages", "send COUNT messages", "COUNT");
+    try {
+        opts.parse();
+        simple_send send(address, message_count);
+        proton::container(send).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/445f8873/examples/cpp/encode_decode.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/encode_decode.cpp b/examples/cpp/encode_decode.cpp
new file mode 100644
index 0000000..5657e73
--- /dev/null
+++ b/examples/cpp/encode_decode.cpp
@@ -0,0 +1,261 @@
+/*
+ * 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/data.hpp>
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#include <map>
+#include <sstream>
+#include <vector>
+
+using namespace std;
+
+// Examples of how to use the encoder and decoder to create and examine AMQP values.
+//
+
+// Print is defined at the end as an example of how to query and extract complex
+// values in terms of their simple components.
+void print(proton::data&);
+
+// Inserting and extracting simple C++ values.
+void simple_insert_extract() {
+    cout << endl << "== Simple values: int, string, bool" << endl;
+    proton::data_value dv;
+    dv.encoder() << 42 << "foo" << true;
+    print(dv);
+    int i;
+    string s;
+    bool b;
+    dv.decoder().rewind();
+    dv.decoder() >> i >> s >> b;
+    cout << "Extracted: " << i << ", " << s << ", " << b << endl;
+    // Encode and decode as AMQP
+    string amqp_data = dv.encoder().encode();
+    cout << "Encoded as AMQP in " << amqp_data.size() << " bytes" << endl;
+    proton::data_value  dt2;
+    dt2.decoder().decode(amqp_data);
+    dt2.decoder() >> i >> s >> b;
+    cout << "Decoded: " << i << ", " << s << ", " << b << endl;
+}
+
+// Inserting values as a specific AMQP type
+void simple_insert_extract_exact_type() {
+    proton::data_value dv;
+    cout << endl << "== Specific AMQP types: byte, long, symbol" << endl;
+    dv.encoder() << proton::amqp_byte('x') << proton::amqp_long(123456789123456789) << proton::amqp_symbol("bar");
+    print(dv);
+    dv.decoder().rewind();
+    // Check that we encoded the correct types, but note that decoding will
+    // still convert to standard C++ types, in particular any AMQP integer type
+    // can be converted to a long-enough C++ integer type..
+    int64_t i1, i2;
+    string s;
+    dv.decoder() >> i1 >> i2 >> s;
+    cout << "Extracted (with conversion) " << i1 << ", " << i2 << ", " << s << endl;
+
+    // Now use the as() function to fail unless we extract the exact AMQP type expected.
+    dv.decoder().rewind(); // amqp_byte(1) << amqp_long(2) << amqp_symbol("bar");
+    proton::amqp_long l;
+    // Fails, extracting amqp_byte as amqp_long
+    try { dv.decoder() >> proton::as<proton::LONG>(l); throw logic_error("expected error"); } catch (proton::decode_error) {}
+    proton::amqp_byte b;
+    dv.decoder() >> proton::as<proton::BYTE>(b) >> proton::as<proton::LONG>(l); // OK, extract amqp_byte as amqp_byte, amqp_long as amqp_long.
+    string str;
+    // Fails, extracting amqp_symbol as amqp_string.
+    try { dv.decoder() >> proton::as<proton::STRING>(str); throw logic_error("expected error"); } catch (proton::decode_error) {}
+    dv.decoder() >> proton::as<proton::SYMBOL>(str);       // OK, extract amqp_symbol as amqp_symbol
+    cout << "Extracted (exact) " << b << ", " << l << ", " << str << endl;
+}
+
+// Some helper templates to print map and vector results.
+namespace std {
+template<class T, class U> ostream& operator<<(ostream& o, const pair<T,U>& p) {
+    return o << p.first << ":" << p.second;
+}
+template<class T> ostream& operator<<(ostream& o, const vector<T>& v) {
+    o << "[ ";
+    ostream_iterator<T> oi(o, " ");
+    copy(v.begin(), v.end(), oi);
+    return o << "]";
+}
+template<class K, class T> ostream& operator<<(ostream& o, const map<K, T>& m) {
+    o << "{ ";
+    ostream_iterator<pair<K,T> > oi(o, " ");
+    copy(m.begin(), m.end(), oi);
+    return o << "}";
+}
+}
+
+// Insert/extract C++ containers.
+void insert_extract_containers() {
+    cout << endl << "== Array, list and map." << endl;
+
+    vector<int> a;
+    a.push_back(1);
+    a.push_back(2);
+    a.push_back(3);
+    vector<int> l;
+    l.push_back(4);
+    l.push_back(5);
+    map<string, int> m;
+    m["one"] = 1;
+    m["two"] = 2;
+
+    proton::data_value dv;
+    dv.encoder() << proton::as<proton::ARRAY>(a) << proton::as<proton::LIST>(l) << proton::as<proton::MAP>(m);
+    print(dv);
+
+    vector<int> a1, l1;
+    map<string, int> m1;
+    dv.decoder().rewind();
+    dv.decoder() >> proton::as<proton::ARRAY>(a1) >> proton::as<proton::LIST>(l1) >> proton::as<proton::MAP>(m1);
+    cout << "Extracted: " << a1 << ", " << l1 << ", " << m1 << endl;
+}
+
+// Containers with mixed types, use value to represent arbitrary AMQP types.
+void mixed_containers() {
+    cout << endl << "== List and map of mixed type values." << endl;
+    vector<proton::data_value> l;
+    l.push_back(proton::data_value(42));
+    l.push_back(proton::data_value(proton::amqp_string("foo")));
+    map<proton::data_value, proton::data_value> m;
+    m[proton::data_value("five")] = proton::data_value(5);
+    m[proton::data_value(4)] = proton::data_value("four");
+    proton::data_value dv;
+    dv.encoder() << proton::as<proton::LIST>(l) << proton::as<proton::MAP>(m);
+    print(dv);
+
+    vector<proton::data_value> l1;
+    map<proton::data_value, proton::data_value> m1;
+    dv.decoder().rewind();
+    dv.decoder() >> proton::as<proton::LIST>(l1) >> proton::as<proton::MAP>(m1);
+    cout << "Extracted: " << l1 << ", " << m1 << endl;
+}
+
+// Insert using stream operators (see print_next for example of extracting with stream ops.)
+void insert_extract_stream_operators() {
+    cout << endl << "== Insert with stream operators." << endl;
+    proton::data_value dv;
+    // Note: array elements must be encoded with the exact type, they are not
+    // automaticlly converted. Mismatched types for array elements will not
+    // be detected until dv.encode() is called.
+    dv.encoder() << proton::start::array(proton::INT) << proton::amqp_int(1) << proton::amqp_int(2) << proton::amqp_int(3) << proton::finish();
+    print(dv);
+
+    dv.clear();
+    dv.encoder() << proton::start::list() << proton::amqp_int(42) << false << proton::amqp_symbol("x") << proton::finish();
+    print(dv);
+
+    dv.clear();
+    dv.encoder() << proton::start::map() << "k1" << proton::amqp_int(42) << proton::amqp_symbol("k2") << false << proton::finish();
+    print(dv);
+}
+
+int main(int, char**) {
+    try {
+        simple_insert_extract();
+        simple_insert_extract_exact_type();
+        insert_extract_containers();
+        mixed_containers();
+        insert_extract_stream_operators();
+        return 0;
+    } catch (const exception& e) {
+        cerr << endl << "error: " << e.what() << endl;
+    }
+    return 1;
+}
+
+// print_next prints the next value from values by recursively descending into complex values.
+//
+// NOTE this is for example puroses only: There is a built in ostream operator<< for values.
+//
+//
+void print_next(proton::data& dv) {
+    proton::type_id type = dv.type();
+    proton::start s;
+    switch (type) {
+      case proton::ARRAY: {
+          dv.decoder() >> s;
+          cout << "array<" << s.element;
+          if (s.is_described) {
+              cout  << ", descriptor=";
+              print_next(dv);
+          }
+          cout << ">[";
+          for (size_t i = 0; i < s.size; ++i) {
+              if (i) cout << ", ";
+              print_next(dv);
+          }
+          cout << "]";
+          dv.decoder() >> proton::finish();
+          break;
+      }
+      case proton::LIST: {
+          dv.decoder() >> s;
+          cout << "list[";
+          for (size_t i = 0; i < s.size; ++i) {
+              if (i) cout << ", ";
+              print_next(dv);
+          }
+          cout << "]";
+          dv.decoder() >> proton::finish();
+          break;
+      }
+      case proton::MAP: {
+          dv.decoder() >> s;
+          cout << "map{";
+          for (size_t i = 0; i < s.size/2; ++i) {
+              if (i) cout << ", ";
+              print_next(dv);
+              cout << ":";        // key:value
+              print_next(dv);
+          }
+          cout << "}";
+          dv.decoder() >> proton::finish();
+          break;
+      }
+      case proton::DESCRIBED: {
+          dv.decoder() >> s;
+          cout << "described(";
+          print_next(dv);      // Descriptor
+          print_next(dv);      // value
+          dv.decoder() >> proton::finish();
+          break;
+      }
+      default:
+        // A simple type. We could continue the switch for all AMQP types but
+        // instead we us the `value` type which can hold and print any AMQP
+        // value.
+        proton::data_value v;
+        dv.decoder() >> v;
+        cout << type << "(" << v << ")";
+    }
+}
+
+// Print all the values with print_next
+void print(proton::data& dv) {
+    dv.decoder().rewind();
+    cout << "Values: ";
+    while (dv.decoder().more()) {
+        print_next(dv);
+        if (dv.decoder().more()) cout << ", ";
+    }
+    cout << endl;
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/445f8873/examples/cpp/example_test.py
----------------------------------------------------------------------
diff --git a/examples/cpp/example_test.py b/examples/cpp/example_test.py
new file mode 100644
index 0000000..7922deb
--- /dev/null
+++ b/examples/cpp/example_test.py
@@ -0,0 +1,228 @@
+#
+# 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
+#
+
+# This is a test script to run the examples and verify that they behave as expected.
+
+import unittest
+import os, sys, socket, time
+from  random import randrange
+from subprocess import Popen, PIPE, STDOUT
+import platform
+
+def cmdline(*args):
+    """Adjust executable name args[0] for windows and/or valgrind"""
+    args = list(args)
+    if platform.system() == "Windows":
+        args[0] += ".exe"
+    else:
+        args[0] = "./" + args[0]
+    if "VALGRIND" in os.environ and os.environ["VALGRIND"]:
+        args = [os.environ["VALGRIND"], "-q"] + args
+    return args
+
+def background(*args):
+    """Run executable in the backround, return the popen"""
+    p = Popen(cmdline(*args), stdout=PIPE, stderr=sys.stderr)
+    p.args = args               # Save arguments for debugging output
+    return p
+
+def verify(p):
+    """Wait for executable to exit and verify status."""
+    try:
+        out, err = p.communicate()
+    except Exception as e:
+        raise Exception("Error running %s: %s", p.args, e)
+    if p.returncode:
+        raise Exception("""%s exit code %s
+vvvvvvvvvvvvvvvv
+%s
+^^^^^^^^^^^^^^^^
+""" % (p.args, p.returncode, out))
+    if platform.system() == "Windows":
+        # Just \n please
+        out = out.translate(None, '\r')
+    return out
+
+def execute(*args):
+    return verify(background(*args))
+
+NULL = open(os.devnull, 'w')
+
+def wait_addr(addr, timeout=10):
+    """Wait up to timeout for something to listen on port"""
+    deadline = time.time() + timeout
+    while time.time() < deadline:
+        try:
+            c = socket.create_connection(addr.split(":"), deadline - time.time())
+            c.close()
+            return
+        except socket.error as e:
+            time.sleep(0.01)
+    raise Exception("Timed out waiting for %s", addr)
+
+def pick_addr():
+    """Pick a new host:port address."""
+    # TODO aconway 2015-07-14: need a safer way to pick ports.
+    p =  randrange(10000, 20000)
+    return "127.0.0.1:%s" % p
+
+class Broker(object):
+    """Run the test broker"""
+
+    @classmethod
+    def get(cls):
+        if not hasattr(cls, "_broker"):
+            cls._broker = Broker()
+        return cls._broker
+
+    @classmethod
+    def stop(cls):
+        if cls.get() and cls._broker.process:
+            cls._broker.process.kill()
+            cls._broker = None
+
+    def __init__(self):
+        self.addr = pick_addr()
+        cmd = cmdline("broker", "-a", self.addr)
+        try:
+            self.process = Popen(cmd, stdout=NULL, stderr=sys.stderr)
+            wait_addr(self.addr)
+            self.addr += "/examples"
+        except Exception as e:
+            raise Exception("Error running %s: %s", cmd, e)
+
+class ExampleTest(unittest.TestCase):
+    """Run the examples, verify they behave as expected."""
+
+    @classmethod
+    def tearDownClass(self):
+        Broker.stop()
+
+    def test_helloworld(self):
+        b = Broker.get()
+        hw = execute("helloworld", b.addr)
+        self.assertEqual('"Hello World!"\n', hw)
+
+    def test_helloworld_blocking(self):
+        b = Broker.get()
+        hw = execute("helloworld_blocking", b.addr, b.addr)
+        self.assertEqual('"Hello World!"\n', hw)
+
+    def test_helloworld_direct(self):
+        addr = pick_addr()
+        hw = execute("helloworld_direct", addr)
+        self.assertEqual('"Hello World!"\n', hw)
+
+    def test_simple_send_recv(self):
+        b = Broker.get()
+        send = execute("simple_send", "-a", b.addr)
+        self.assertEqual("all messages confirmed\n", send)
+        recv = execute("simple_recv", "-a", b.addr)
+        recv_expect = "simple_recv listening on amqp://%s\n" % (b.addr)
+        recv_expect += "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)])
+        self.assertEqual(recv_expect, recv)
+
+    def test_simple_send_direct_recv(self):
+        addr = pick_addr()
+        recv = background("direct_recv", "-a", addr)
+        wait_addr(addr)
+        self.assertEqual("all messages confirmed\n", execute("simple_send", "-a", addr))
+        recv_expect = "direct_recv listening on amqp://%s\n" % (addr)
+        recv_expect += "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)])
+        self.assertEqual(recv_expect, verify(recv))
+
+    def test_simple_recv_direct_send(self):
+        addr = pick_addr()
+        send = background("direct_send", "-a", addr)
+        wait_addr(addr)
+        recv_expect = "simple_recv listening on amqp://%s\n" % (addr)
+        recv_expect += "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)])
+        self.assertEqual(recv_expect, execute("simple_recv", "-a", addr))
+        send_expect = "direct_send listening on amqp://%s\nall messages confirmed\n" % (addr)
+        self.assertEqual(send_expect, verify(send))
+
+    CLIENT_EXPECT=""""Twas brillig, and the slithy toves" => "TWAS BRILLIG, AND THE SLITHY TOVES"
+"Did gire and gymble in the wabe." => "DID GIRE AND GYMBLE IN THE WABE."
+"All mimsy were the borogroves," => "ALL MIMSY WERE THE BOROGROVES,"
+"And the mome raths outgrabe." => "AND THE MOME RATHS OUTGRABE."
+"""
+    def test_simple_recv_send(self):
+        # Start receiver first, then run sender"""
+        b = Broker.get()
+        recv = background("simple_recv", "-a", b.addr)
+        self.assertEqual("all messages confirmed\n", execute("simple_send", "-a", b.addr))
+        recv_expect = "simple_recv listening on amqp://%s\n" % (b.addr)
+        recv_expect += "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)])
+        self.assertEqual(recv_expect, verify(recv))
+
+    def test_request_response(self):
+        b = Broker.get()
+        server = background("server", "-a", b.addr)
+        try:
+            self.assertEqual(execute("client", "-a", b.addr), self.CLIENT_EXPECT)
+        finally:
+            server.kill()
+
+    def test_sync_request_response(self):
+        b = Broker.get()
+        server = background("server", "-a", b.addr)
+        try:
+            self.assertEqual(execute("sync_client", "-a", b.addr), self.CLIENT_EXPECT)
+        finally:
+            server.kill()
+
+    def test_request_response_direct(self):
+        addr = pick_addr()
+        server = background("server_direct", "-a", addr+"/examples")
+        wait_addr(addr)
+        try:
+            self.assertEqual(execute("client", "-a", addr+"/examples"), self.CLIENT_EXPECT)
+        finally:
+            server.kill()
+
+    def test_encode_decode(self):
+        expect="""
+== Simple values: int, string, bool
+Values: int(42), string("foo"), bool(true)
+Extracted: 42, foo, 1
+Encoded as AMQP in 8 bytes
+Decoded: 42, foo, 1
+
+== Specific AMQP types: byte, long, symbol
+Values: byte(120), long(123456789123456789), symbol(:bar)
+Extracted (with conversion) 120, 123456789123456789, bar
+Extracted (exact) x, 123456789123456789, bar
+
+== Array, list and map.
+Values: array<int>[int(1), int(2), int(3)], list[int(4), int(5)], map{string("one"):int(1), string("two"):int(2)}
+Extracted: [ 1 2 3 ], [ 4 5 ], { one:1 two:2 }
+
+== List and map of mixed type values.
+Values: list[int(42), string("foo")], map{int(4):string("four"), string("five"):int(5)}
+Extracted: [ 42 "foo" ], { 4:"four" "five":5 }
+
+== Insert with stream operators.
+Values: array<int>[int(1), int(2), int(3)]
+Values: list[int(42), bool(false), symbol(:x)]
+Values: map{string("k1"):int(42), symbol(:"k2"):bool(false)}
+"""
+        self.maxDiff = None
+        self.assertEqual(expect, execute("encode_decode"))
+if __name__ == "__main__":
+    unittest.main()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/445f8873/examples/cpp/helloworld.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/helloworld.cpp b/examples/cpp/helloworld.cpp
new file mode 100644
index 0000000..bbb5330
--- /dev/null
+++ b/examples/cpp/helloworld.cpp
@@ -0,0 +1,66 @@
+/*
+ *
+ * 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/messaging_handler.hpp"
+#include "proton/url.hpp"
+
+#include <iostream>
+
+class hello_world : public proton::messaging_handler {
+  private:
+    proton::url url;
+
+  public:
+
+    hello_world(const proton::url& u) : url(u) {}
+
+    void on_start(proton::event &e) {
+        proton::connection& conn = e.container().connect(url);
+        conn.create_receiver(url.path());
+        conn.create_sender(url.path());
+    }
+
+    void on_sendable(proton::event &e) {
+        proton::message_value m;
+        m.body("Hello World!");
+        e.sender().send(m);
+        e.sender().close();
+    }
+
+    void on_message(proton::event &e) {
+        proton::data& body(e.message().body());
+        std::cout << body << std::endl;
+        e.connection().close();
+    }
+};
+
+int main(int argc, char **argv) {
+    try {
+        std::string url = argc > 1 ? argv[1] : "127.0.0.1:5672/examples";
+        hello_world hw(url);
+        proton::container(hw).run();
+        return 0;
+    } catch (const std::exception& e) {
+        std::cerr << e.what() << std::endl;
+    }
+    return 1;
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/445f8873/examples/cpp/helloworld_blocking.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/helloworld_blocking.cpp b/examples/cpp/helloworld_blocking.cpp
new file mode 100644
index 0000000..49094a3
--- /dev/null
+++ b/examples/cpp/helloworld_blocking.cpp
@@ -0,0 +1,52 @@
+/*
+ *
+ * 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/messaging_handler.hpp"
+#include "proton/blocking_connection.hpp"
+#include "proton/blocking_sender.hpp"
+#include "proton/blocking_receiver.hpp"
+#include "proton/duration.hpp"
+
+#include <iostream>
+
+int main(int argc, char **argv) {
+    try {
+        proton::url url(argc > 1 ? argv[1] : "127.0.0.1:5672/examples");
+        proton::blocking_connection conn(url);
+        proton::blocking_receiver receiver(conn, url.path());
+        proton::blocking_sender sender(conn, url.path());
+
+        proton::message_value m;
+        m.body("Hello World!");
+        sender.send(m);
+
+        proton::duration timeout(30000);
+        proton::message_value m2 = receiver.receive(timeout);
+        std::cout << m2.body() << std::endl;
+        receiver.accept();
+
+        conn.close();
+        return 0;
+    } catch (const std::exception& e) {
+        std::cerr << e.what() << std::endl;
+    }
+    return 1;
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/445f8873/examples/cpp/helloworld_direct.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/helloworld_direct.cpp b/examples/cpp/helloworld_direct.cpp
new file mode 100644
index 0000000..119d134
--- /dev/null
+++ b/examples/cpp/helloworld_direct.cpp
@@ -0,0 +1,74 @@
+/*
+ *
+ * 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/acceptor.hpp"
+#include "proton/container.hpp"
+#include "proton/messaging_handler.hpp"
+
+//#include "proton/acceptor.hpp"
+#include <iostream>
+
+class hello_world_direct : public proton::messaging_handler {
+  private:
+    proton::url url;
+    proton::counted_ptr<proton::acceptor> acceptor;
+  public:
+
+    hello_world_direct(const proton::url& u) : url(u) {}
+
+    void on_start(proton::event &e) {
+        acceptor = e.container().listen(url).ptr();
+        e.container().create_sender(url);
+    }
+
+    void on_sendable(proton::event &e) {
+        proton::message_value m;
+        m.body("Hello World!");
+        e.sender().send(m);
+        e.sender().close();
+    }
+
+    void on_message(proton::event &e) {
+        std::cout << e.message().body() << std::endl;
+    }
+
+    void on_accepted(proton::event &e) {
+        e.connection().close();
+    }
+
+    void on_connection_closed(proton::event &e) {
+        acceptor->close();
+    }
+};
+
+int main(int argc, char **argv) {
+    try {
+        // Pick an "unusual" port since we are going to be talking to ourselves, not a broker.
+        std::string url = argc > 1 ? argv[1] : "127.0.0.1:8888/examples";
+
+        hello_world_direct hwd(url);
+        proton::container(hwd).run();
+        return 0;
+    } catch (const std::exception& e) {
+        std::cerr << e.what() << std::endl;
+    }
+    return 1;
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/445f8873/examples/cpp/options.hpp
----------------------------------------------------------------------
diff --git a/examples/cpp/options.hpp b/examples/cpp/options.hpp
new file mode 100644
index 0000000..bd477b5
--- /dev/null
+++ b/examples/cpp/options.hpp
@@ -0,0 +1,173 @@
+#ifndef OPTIONS_HPP
+#define OPTIONS_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 <string>
+#include <sstream>
+#include <ostream>
+#include <vector>
+#include <stdexcept>
+
+/** bad_option is thrown for option parsing errors */
+struct bad_option : public std::runtime_error {
+    bad_option(const std::string& s) : std::runtime_error(s) {}
+};
+
+/** Simple command-line option parser for example programs */
+class options {
+  public:
+
+    options(int argc, char const * const * argv) : argc_(argc), argv_(argv), prog_(argv[0]), help_() {
+        size_t slash = prog_.find_last_of("/\\");
+        if (slash != std::string::npos)
+            prog_ = prog_.substr(slash+1); // Extract prog name from path
+        add_flag(help_, 'h', "help", "Print the help message");
+    }
+
+    ~options() {
+        for (opts::iterator i = opts_.begin(); i != opts_.end(); ++i)
+            delete *i;
+    }
+
+    /** Updates value when parse() is called if option is present with a value. */
+    template<class T>
+    void add_value(T& value, char short_name, const std::string& long_name, const std::string& description, const std::string var) {
+        opts_.push_back(new option_value<T>(value, short_name, long_name, description, var));
+    }
+
+    /** Sets flag when parse() is called if option is present. */
+    void add_flag(bool& flag, char short_name, const std::string& long_name, const std::string& description) {
+        opts_.push_back(new option_flag(flag, short_name, long_name, description));
+    }
+
+    /** Parse the command line, return the index of the first non-option argument.
+     *@throws bad_option if there is a parsing error or unknown option.
+     */
+    int parse() {
+        int arg = 1;
+        for (; arg < argc_ && argv_[arg][0] == '-'; ++arg) {
+            opts::iterator i = opts_.begin();
+            while (i != opts_.end() && !(*i)->parse(argc_, argv_, arg))
+                ++i;
+            if (i == opts_.end())
+                throw bad_option(std::string("unknown option ") + argv_[arg]);
+        }
+        if (help_) throw bad_option("");
+        return arg;
+    }
+
+    /** Print a usage message */
+  friend std::ostream& operator<<(std::ostream& os, const options& op) {
+      os << std::endl << "usage: " << op.prog_ << " [options]" << std::endl;
+      os << std::endl << "options:" << std::endl;
+      for (opts::const_iterator i = op.opts_.begin(); i < op.opts_.end(); ++i)
+          os << **i << std::endl;
+      return os;
+  }
+
+ private:
+    class option {
+      public:
+        option(char s, const std::string& l, const std::string& d, const std::string v) :
+            short_(std::string("-") + s), long_("--" + l), desc_(d), var_(v) {}
+        virtual ~option() {}
+
+        virtual bool parse(int argc, char const * const * argv, int &i) = 0;
+        virtual void print_default(std::ostream&) const {};
+
+      friend std::ostream& operator<<(std::ostream& os, const option& op) {
+          os << "  " << op.short_;
+          if (!op.var_.empty()) os << " " << op.var_;
+          os << ", " << op.long_;
+          if (!op.var_.empty()) os << "=" << op.var_;
+          os << std::endl << "        " << op.desc_;
+          op.print_default(os);
+          return os;
+      }
+
+      protected:
+        std::string short_, long_, desc_, var_;
+    };
+
+    template <class T>
+    class option_value : public option {
+      public:
+        option_value(T& value, char s, const std::string& l, const std::string& d, const std::string& v) :
+            option(s, l, d, v), value_(value) {}
+
+        bool parse(int argc, char const * const * argv, int &i) {
+            std::string arg(argv[i]);
+            if (arg == short_ || arg == long_) {
+                if (i < argc-1) {
+                    set_value(arg, argv[++i]);
+                    return true;
+                } else {
+                    throw bad_option("missing value for " + arg);
+                }
+            }
+            if (arg.compare(0, long_.size(), long_) == 0 && arg[long_.size()] == '=' ) {
+                set_value(long_, arg.substr(long_.size()+1));
+                return true;
+            }
+            return false;
+        }
+
+        virtual void print_default(std::ostream& os) const { os << " (default " << value_ << ")"; }
+
+        void set_value(const std::string& opt, const std::string& s) {
+            std::istringstream is(s);
+            is >> value_;
+            if (is.fail() || is.bad())
+                throw bad_option("bad value for " + opt + ": " + s);
+        }
+
+      private:
+        T& value_;
+    };
+
+    class option_flag: public option {
+      public:
+        option_flag(bool& flag, const char s, const std::string& l, const std::string& d) :
+            option(s, l, d, ""), flag_(flag)
+        { flag_ = false; }
+
+        bool parse(int /*argc*/, char const * const * argv, int &i) {
+            if (argv[i] == short_ || argv[i] == long_) {
+                flag_ = true;
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+      private:
+        bool &flag_;
+    };
+
+    typedef std::vector<option*> opts;
+
+    int argc_;
+    char const * const * argv_;
+    std::string prog_;
+    opts opts_;
+    bool help_;
+};
+
+#endif // OPTIONS_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/445f8873/examples/cpp/server.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/server.cpp b/examples/cpp/server.cpp
new file mode 100644
index 0000000..60cc972
--- /dev/null
+++ b/examples/cpp/server.cpp
@@ -0,0 +1,86 @@
+/*
+ *
+ * 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/url.hpp"
+
+#include <iostream>
+#include <map>
+#include <string>
+#include <cctype>
+
+class server : public proton::messaging_handler {
+  private:
+    typedef std::map<std::string, proton::counted_ptr<proton::sender> > sender_map;
+    proton::url url;
+    proton::counted_ptr<proton::connection> connection;
+    sender_map senders;
+
+  public:
+
+    server(const std::string &u) : url(u) {}
+
+    void on_start(proton::event &e) {
+        connection = e.container().connect(url).ptr();
+        connection->create_receiver(url.path());
+        std::cout << "server connected to " << url << std::endl;
+    }
+
+    std::string to_upper(const std::string &s) {
+        std::string uc(s);
+        size_t l = uc.size();
+        for (size_t i=0; i<l; i++) uc[i] = std::toupper(uc[i]);
+        return uc;
+    }
+
+    void on_message(proton::event &e) {
+        std::cout << "Received " << e.message().body() << std::endl;
+        std::string reply_to = e.message().reply_to();
+        proton::message_value reply;
+        reply.address(reply_to);
+        reply.body(to_upper(e.message().body().get<std::string>()));
+        reply.correlation_id(e.message().correlation_id());
+        if (!senders[reply_to])
+            senders[reply_to] = connection->create_sender(reply_to).ptr();
+        senders[reply_to]->send(reply);
+    }
+};
+
+int main(int argc, char **argv) {
+    // Command line options
+    std::string address("amqp://127.0.0.1:5672/examples");
+    options opts(argc, argv);
+    opts.add_value(address, 'a', "address", "listen on URL", "URL");
+    try {
+        opts.parse();
+        server srv(address);
+        proton::container(srv).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/445f8873/examples/cpp/server_direct.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/server_direct.cpp b/examples/cpp/server_direct.cpp
new file mode 100644
index 0000000..1e1839c
--- /dev/null
+++ b/examples/cpp/server_direct.cpp
@@ -0,0 +1,105 @@
+/*
+ *
+ * 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/acceptor.hpp"
+#include "proton/container.hpp"
+#include "proton/messaging_handler.hpp"
+#include "proton/url.hpp"
+
+#include <iostream>
+#include <map>
+#include <string>
+#include <sstream>
+#include <cctype>
+
+class server : public proton::messaging_handler {
+  private:
+    typedef std::map<std::string, proton::counted_ptr<proton::sender> > sender_map;
+    proton::url url;
+    sender_map senders;
+    int address_counter;
+
+  public:
+
+    server(const std::string &u) : url(u), address_counter(0) {}
+
+    void on_start(proton::event &e) {
+        e.container().listen(url);
+        std::cout << "server listening on " << url << std::endl;
+    }
+
+    std::string to_upper(const std::string &s) {
+        std::string uc(s);
+        size_t l = uc.size();
+        for (size_t i=0; i<l; i++) uc[i] = std::toupper(uc[i]);
+        return uc;
+    }
+
+    std::string generate_address() {
+        std::ostringstream addr;
+        addr << "server" << address_counter++;
+        return addr.str();
+    }
+
+    void on_link_opening(proton::event& e) {
+        proton::link& link = e.link();
+        if (link.is_sender() && link.has_remote_source() && link.remote_source().is_dynamic()) {
+            link.source().address(generate_address());
+            senders[link.source().address()] = link.sender().ptr();
+        }
+    }
+
+    void on_message(proton::event &e) {
+        std::cout << "Received " << e.message().body() << std::endl;
+        std::string reply_to = e.message().reply_to();
+        sender_map::iterator it = senders.find(reply_to);
+        if (it == senders.end()) {
+            std::cout << "No link for reply_to: " << reply_to << std::endl;
+        } else {
+            proton::counted_ptr<proton::sender> sender = it->second;
+            proton::message_value reply;
+            reply.address(reply_to);
+            reply.body(to_upper(e.message().body().get<std::string>()));
+            reply.correlation_id(e.message().correlation_id());
+            sender->send(reply);
+        }
+    }
+};
+
+int main(int argc, char **argv) {
+    // Command line options
+    std::string address("amqp://127.0.0.1:5672/examples");
+    options opts(argc, argv);
+    opts.add_value(address, 'a', "address", "listen on URL", "URL");
+    try {
+        opts.parse();
+        server srv(address);
+        proton::container(srv).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/445f8873/examples/cpp/simple_recv.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/simple_recv.cpp b/examples/cpp/simple_recv.cpp
new file mode 100644
index 0000000..f669e30
--- /dev/null
+++ b/examples/cpp/simple_recv.cpp
@@ -0,0 +1,85 @@
+/*
+ *
+ * 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/link.hpp"
+
+#include <iostream>
+#include <map>
+
+
+
+class simple_recv : public proton::messaging_handler {
+  private:
+    proton::url url;
+    proton::counted_ptr<proton::receiver> receiver;
+    int expected;
+    int received;
+  public:
+
+    simple_recv(const std::string &s, int c) : url(s), expected(c), received(0) {}
+
+    void on_start(proton::event &e) {
+        receiver = e.container().create_receiver(url).ptr();
+        std::cout << "simple_recv listening on " << url << std::endl;
+    }
+
+    void on_message(proton::event &e) {
+        proton::message& msg = e.message();
+        proton::data_value id = msg.id();
+        if (id.type() == proton::ULONG) {
+            if (id.get<int>() < received)
+                return; // ignore duplicate
+        }
+        if (expected == 0 || received < expected) {
+            std::cout << msg.body() << std::endl;
+            received++;
+            if (received == expected) {
+                e.receiver().close();
+                e.connection().close();
+            }
+        }
+    }
+};
+
+int main(int argc, char **argv) {
+    // Command line options
+    std::string address("127.0.0.1:5672/examples");
+    int message_count = 100;
+    options opts(argc, argv);
+    opts.add_value(address, 'a', "address", "connect to and receive from URL", "URL");
+    opts.add_value(message_count, 'm', "messages", "receive COUNT messages", "COUNT");
+
+    try {
+        opts.parse();
+        simple_recv recv(address, message_count);
+        proton::container(recv).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/445f8873/examples/cpp/simple_send.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/simple_send.cpp b/examples/cpp/simple_send.cpp
new file mode 100644
index 0000000..11af17c
--- /dev/null
+++ b/examples/cpp/simple_send.cpp
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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/connection.hpp"
+
+#include <iostream>
+#include <map>
+
+class simple_send : public proton::messaging_handler {
+  private:
+    proton::url url;
+    proton::counted_ptr<proton::sender> sender;
+    int sent;
+    int confirmed;
+    int total;
+  public:
+
+    simple_send(const std::string &s, int c) : url(s), sent(0), confirmed(0), total(c) {}
+
+    void on_start(proton::event &e) {
+        sender = e.container().create_sender(url).ptr();
+    }
+
+    void on_sendable(proton::event &e) {
+        proton::sender& sender = e.sender();
+        while (sender.credit() && sent < total) {
+            proton::message_value msg;
+            msg.id(proton::data_value(sent + 1));
+            std::map<std::string, int> m;
+            m["sequence"] = sent+1;
+            msg.body(proton::as<proton::MAP>(m));
+            sender.send(msg);
+            sent++;
+        }
+    }
+
+    void on_accepted(proton::event &e) {
+        confirmed++;
+        if (confirmed == total) {
+            std::cout << "all messages confirmed" << std::endl;
+            e.connection().close();
+        }
+    }
+
+    void on_disconnected(proton::event &e) {
+        sent = confirmed;
+    }
+};
+
+int main(int argc, char **argv) {
+    // Command line options
+    std::string address("127.0.0.1:5672/examples");
+    int message_count = 100;
+    options opts(argc, argv);
+    opts.add_value(address, 'a', "address", "connect and send to URL", "URL");
+    opts.add_value(message_count, 'm', "messages", "receive COUNT messages", "COUNT");
+    try {
+        opts.parse();
+        simple_send send(address, message_count);
+        proton::container(send).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/445f8873/examples/cpp/sync_client.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/sync_client.cpp b/examples/cpp/sync_client.cpp
new file mode 100644
index 0000000..7bf08d9
--- /dev/null
+++ b/examples/cpp/sync_client.cpp
@@ -0,0 +1,67 @@
+/*
+ *
+ * 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/blocking_connection.hpp"
+#include "proton/sync_request_response.hpp"
+#include "proton/url.hpp"
+#include "proton/types.hpp"
+
+#include <iostream>
+#include <vector>
+#include <string>
+
+
+int main(int argc, char **argv) {
+    // Command line options
+    proton::url url("127.0.0.1:5672/examples");
+    uint64_t timeout(5000);
+    options opts(argc, argv);
+    opts.add_value(url, 'a', "address", "connect to URL", "URL");
+    opts.add_value(timeout, 't', "timeout", "give up after this TIMEOUT (milliseconds)", "TIMEOUT");
+
+    std::vector<std::string> requests;
+    requests.push_back("Twas brillig, and the slithy toves");
+    requests.push_back("Did gire and gymble in the wabe.");
+    requests.push_back("All mimsy were the borogroves,");
+    requests.push_back("And the mome raths outgrabe.");
+
+    try {
+        opts.parse();
+
+        proton::blocking_connection conn(url, proton::duration(timeout));
+        proton::sync_request_response client(conn, url.path());
+        for (std::vector<std::string>::const_iterator i=requests.begin(); i != requests.end(); i++) {
+            proton::message_value request;
+            request.body(*i);
+            proton::message_value response(client.call(request));
+            std::cout << request.body() << " => " << response.body() << std::endl;
+        }
+        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/445f8873/examples/go/README.md
----------------------------------------------------------------------
diff --git a/examples/go/README.md b/examples/go/README.md
deleted file mode 100644
index 719a3d1..0000000
--- a/examples/go/README.md
+++ /dev/null
@@ -1,69 +0,0 @@
-# Go examples for proton
-
-The Go support for proton consists of 3 packages:
-
-- proton: converts AMQP messages and data types to and from Go data types.
-- proton/messaging: easy-to-use, concurrent API for messaging clients and servers.
-- proton/event: full low-level access to the proton engine.
-
-Most applications should use the proton/messaging API. proton/event is for
-applications that need low-level access to the proton engine. proton/messaging
-itself is implemented using proton/event.
-
-## proton/messaging examples
-
-- [receive.go](receive.go) receive from many connections concurrently.
-- [send.go](send.go) send to many connections concurrently.
-
-## proton/event examples
-
-- [broker.go](event/broker.go) simple mini-broker, queues are created automatically.
-
-## Running the examples
-
-Proton needs to be installed in a standard place such as `/usr` or `/usr/local`.
-(in future the examples will be able to use the local proton build)
-
-Set your environment:
-
-    export GOPATH=<path-to-proton-checkout>/proton-c/bindings/go
-
-You can run the examples directly from source with
-
-    go run <program>.go
-
-This is a little slow (a couple of seconds) as it compiles the program and runs it in one step.
-You can compile the program first and then run the executable to avoid the delay:
-
-    go build <program>.go
-    ./<program>
-
-All the examples take a `-h` flag to show usage information, see comments in the example
-source for more details.
-
-## Example of running the examples.
-
-First start the broker:
-
-    go run event/broker.go
-
-Send messages concurrently to queues "foo" and "bar", 10 messages to each queue:
-
-    go run go/send.go -count 10 localhost:/foo localhost:/bar
-
-Receive messages concurrently from "foo" and "bar". Note -count 20 for 10 messages each on 2 queues:
-
-    go run go/receive.go -count 20 localhost:/foo localhost:/bar
-
-The broker and clients use the amqp port on the local host by default, to use a
-different address use the `-addr host:port` flag.
-
-You can mix it up by running the Go clients with the python broker:
-
-    python ../python/broker.py
-
-Or use the Go broker and the python clients:
-
-    python ../python/simple_send.py
-    python ../python/simple_recv.py`.
-


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


Mime
View raw message