Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r55497 - in sandbox/channel: boost boost/channel boost/channel/dispatchers boost/channel/executors boost/channel/name_spaces boost/channel/platforms boost/channel/queues boost/channel/streams libs libs/channel libs/channel/doc libs/channel/example libs/channel/example/buffered_async_join libs/channel/example/buffered_sync_sendrecv libs/channel/example/chat_assoc libs/channel/example/chat_direct libs/channel/example/chat_regex libs/channel/example/chat_shmem libs/channel/example/chat_thru_server libs/channel/example/dist_evt_chan libs/channel/example/filter_translator libs/channel/example/gui_evt libs/channel/example/ping_pong libs/channel/example/prime_sieve libs/channel/example/sample_dispatcher libs/channel/test
From: yigongliu_at_[hidden]
Date: 2009-08-09 21:59:25


Author: yigongliu
Date: 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
New Revision: 55497
URL: http://svn.boost.org/trac/boost/changeset/55497

Log:
updated to build with g++4.2.4, g++4.3.3, VC++205, VC++2008
Added:
   sandbox/channel/boost/
   sandbox/channel/boost/channel/
   sandbox/channel/boost/channel/binder.hpp (contents, props changed)
   sandbox/channel/boost/channel/channel.hpp (contents, props changed)
   sandbox/channel/boost/channel/connection.hpp (contents, props changed)
   sandbox/channel/boost/channel/dispatchers/
   sandbox/channel/boost/channel/dispatchers/always_latest_dispatcher.hpp (contents, props changed)
   sandbox/channel/boost/channel/dispatchers/arbiters_async.hpp (contents, props changed)
   sandbox/channel/boost/channel/dispatchers/arbiters_sync.hpp (contents, props changed)
   sandbox/channel/boost/channel/dispatchers/broadcast_dispatcher.hpp (contents, props changed)
   sandbox/channel/boost/channel/dispatchers/dispatcher_base.hpp (contents, props changed)
   sandbox/channel/boost/channel/dispatchers/pull_dispatcher.hpp (contents, props changed)
   sandbox/channel/boost/channel/dispatchers/pull_dispatcher_base.hpp (contents, props changed)
   sandbox/channel/boost/channel/dispatchers/push_dispatcher_base.hpp (contents, props changed)
   sandbox/channel/boost/channel/dispatchers/round_robin_dispatcher.hpp (contents, props changed)
   sandbox/channel/boost/channel/executors/
   sandbox/channel/boost/channel/executors/asio_executor.hpp (contents, props changed)
   sandbox/channel/boost/channel/executors/delayed_executor.hpp (contents, props changed)
   sandbox/channel/boost/channel/executors/executor_base.hpp (contents, props changed)
   sandbox/channel/boost/channel/executors/in_place_executor.hpp (contents, props changed)
   sandbox/channel/boost/channel/executors/thread_pool_executor.hpp (contents, props changed)
   sandbox/channel/boost/channel/executors/threadpool_executor.hpp (contents, props changed)
   sandbox/channel/boost/channel/interface.hpp (contents, props changed)
   sandbox/channel/boost/channel/marshaler.hpp (contents, props changed)
   sandbox/channel/boost/channel/message.hpp (contents, props changed)
   sandbox/channel/boost/channel/name.hpp (contents, props changed)
   sandbox/channel/boost/channel/name_spaces/
   sandbox/channel/boost/channel/name_spaces/assoc_id_trait.def (contents, props changed)
   sandbox/channel/boost/channel/name_spaces/assoc_id_trait.hpp (contents, props changed)
   sandbox/channel/boost/channel/name_spaces/hierarchical_id_trait.def (contents, props changed)
   sandbox/channel/boost/channel/name_spaces/hierarchical_id_trait.hpp (contents, props changed)
   sandbox/channel/boost/channel/name_spaces/hierarchical_name_space.hpp (contents, props changed)
   sandbox/channel/boost/channel/name_spaces/linear_id_trait.def (contents, props changed)
   sandbox/channel/boost/channel/name_spaces/linear_id_trait.hpp (contents, props changed)
   sandbox/channel/boost/channel/name_spaces/linear_name_space.hpp (contents, props changed)
   sandbox/channel/boost/channel/name_spaces/name.def (contents, props changed)
   sandbox/channel/boost/channel/name_spaces/name_space_change_notify.hpp (contents, props changed)
   sandbox/channel/boost/channel/name_spaces/null_name_space.hpp (contents, props changed)
   sandbox/channel/boost/channel/named_in_out.hpp (contents, props changed)
   sandbox/channel/boost/channel/peer.hpp (contents, props changed)
   sandbox/channel/boost/channel/platforms/
   sandbox/channel/boost/channel/platforms/boost_platform.hpp (contents, props changed)
   sandbox/channel/boost/channel/platforms/null_condition.hpp (contents, props changed)
   sandbox/channel/boost/channel/platforms/null_mutex.hpp (contents, props changed)
   sandbox/channel/boost/channel/platforms/synch_policy.hpp (contents, props changed)
   sandbox/channel/boost/channel/pub_sub.hpp (contents, props changed)
   sandbox/channel/boost/channel/queues/
   sandbox/channel/boost/channel/queues/bounded_queue.hpp (contents, props changed)
   sandbox/channel/boost/channel/queues/dropping_queue.hpp (contents, props changed)
   sandbox/channel/boost/channel/queues/flow_controlled_queue.hpp (contents, props changed)
   sandbox/channel/boost/channel/queues/queues.hpp (contents, props changed)
   sandbox/channel/boost/channel/queues/timed_queue.hpp (contents, props changed)
   sandbox/channel/boost/channel/queues/unbounded_queue.hpp (contents, props changed)
   sandbox/channel/boost/channel/streams/
   sandbox/channel/boost/channel/streams/asio_connector_async.hpp (contents, props changed)
   sandbox/channel/boost/channel/streams/asio_connector_sync.hpp (contents, props changed)
   sandbox/channel/boost/channel/streams/asio_stream_async.hpp (contents, props changed)
   sandbox/channel/boost/channel/streams/asio_stream_sync.hpp (contents, props changed)
   sandbox/channel/boost/channel/streams/shmem_stream.hpp (contents, props changed)
   sandbox/channel/boost/channel/unnamed_in_out.hpp (contents, props changed)
   sandbox/channel/libs/
   sandbox/channel/libs/channel/
   sandbox/channel/libs/channel/doc/
   sandbox/channel/libs/channel/doc/assoc_id_text.html (contents, props changed)
   sandbox/channel/libs/channel/doc/design.html (contents, props changed)
   sandbox/channel/libs/channel/doc/index.html (contents, props changed)
   sandbox/channel/libs/channel/example/
   sandbox/channel/libs/channel/example/buffered_async_join/
   sandbox/channel/libs/channel/example/buffered_async_join/Jamfile.v2 (contents, props changed)
   sandbox/channel/libs/channel/example/buffered_async_join/chat_defs.hpp (contents, props changed)
   sandbox/channel/libs/channel/example/buffered_async_join/chat_join.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/buffered_async_join/chat_join_2chan.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/buffered_async_join/chat_join_timer.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/buffered_async_join/sample6_text.html (contents, props changed)
   sandbox/channel/libs/channel/example/buffered_sync_sendrecv/
   sandbox/channel/libs/channel/example/buffered_sync_sendrecv/Jamfile.v2 (contents, props changed)
   sandbox/channel/libs/channel/example/buffered_sync_sendrecv/sample5_text.html (contents, props changed)
   sandbox/channel/libs/channel/example/buffered_sync_sendrecv/sync_send_recv.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/chat_assoc/
   sandbox/channel/libs/channel/example/chat_assoc/Jamfile.v2 (contents, props changed)
   sandbox/channel/libs/channel/example/chat_assoc/chat1.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/chat_assoc/chat2.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/chat_assoc/chat_defs.hpp (contents, props changed)
   sandbox/channel/libs/channel/example/chat_assoc/sample10_text.html (contents, props changed)
   sandbox/channel/libs/channel/example/chat_direct/
   sandbox/channel/libs/channel/example/chat_direct/Jamfile.v2 (contents, props changed)
   sandbox/channel/libs/channel/example/chat_direct/chat1.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/chat_direct/chat2.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/chat_direct/chat_defs.hpp (contents, props changed)
   sandbox/channel/libs/channel/example/chat_direct/sample4_text.html (contents, props changed)
   sandbox/channel/libs/channel/example/chat_regex/
   sandbox/channel/libs/channel/example/chat_regex/Jamfile.v2 (contents, props changed)
   sandbox/channel/libs/channel/example/chat_regex/chat1.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/chat_regex/chat2.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/chat_regex/chat_defs.hpp (contents, props changed)
   sandbox/channel/libs/channel/example/chat_regex/sample9_text.html (contents, props changed)
   sandbox/channel/libs/channel/example/chat_regex/test.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/chat_shmem/
   sandbox/channel/libs/channel/example/chat_shmem/Jamfile.v2 (contents, props changed)
   sandbox/channel/libs/channel/example/chat_shmem/chat1.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/chat_shmem/chat2.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/chat_shmem/chat_defs.hpp (contents, props changed)
   sandbox/channel/libs/channel/example/chat_shmem/sample8_text.html (contents, props changed)
   sandbox/channel/libs/channel/example/chat_thru_server/
   sandbox/channel/libs/channel/example/chat_thru_server/Jamfile.v2 (contents, props changed)
   sandbox/channel/libs/channel/example/chat_thru_server/chat_cli.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/chat_thru_server/chat_defs.hpp (contents, props changed)
   sandbox/channel/libs/channel/example/chat_thru_server/chat_srv.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/chat_thru_server/sample7_text.html (contents, props changed)
   sandbox/channel/libs/channel/example/dist_evt_chan/
   sandbox/channel/libs/channel/example/dist_evt_chan/Jamfile.v2 (contents, props changed)
   sandbox/channel/libs/channel/example/dist_evt_chan/evt_chan1.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/dist_evt_chan/evt_chan2.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/dist_evt_chan/evt_chan_defs.hpp (contents, props changed)
   sandbox/channel/libs/channel/example/dist_evt_chan/sample3_text.html (contents, props changed)
   sandbox/channel/libs/channel/example/filter_translator/
   sandbox/channel/libs/channel/example/filter_translator/Jamfile.v2 (contents, props changed)
   sandbox/channel/libs/channel/example/filter_translator/chat_defs.hpp (contents, props changed)
   sandbox/channel/libs/channel/example/filter_translator/cli.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/filter_translator/sample11_text.html (contents, props changed)
   sandbox/channel/libs/channel/example/filter_translator/srv.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/gui_evt/
   sandbox/channel/libs/channel/example/gui_evt/Jamfile.v2 (contents, props changed)
   sandbox/channel/libs/channel/example/gui_evt/gui_evt3.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/gui_evt/gui_evt_chan1.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/gui_evt/gui_evt_chan2.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/gui_evt/sample1_text.html (contents, props changed)
   sandbox/channel/libs/channel/example/gui_evt/sample2_text.html (contents, props changed)
   sandbox/channel/libs/channel/example/ping_pong/
   sandbox/channel/libs/channel/example/ping_pong/Jamfile.v2 (contents, props changed)
   sandbox/channel/libs/channel/example/ping_pong/ping.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/ping_pong/pingpong_defs.hpp (contents, props changed)
   sandbox/channel/libs/channel/example/ping_pong/pong.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/prime_sieve/
   sandbox/channel/libs/channel/example/prime_sieve/Jamfile.v2 (contents, props changed)
   sandbox/channel/libs/channel/example/prime_sieve/prime_sieve.cpp (contents, props changed)
   sandbox/channel/libs/channel/example/prime_sieve/sample12_text.html (contents, props changed)
   sandbox/channel/libs/channel/example/sample_dispatcher/
   sandbox/channel/libs/channel/example/sample_dispatcher/Jamfile.v2 (contents, props changed)
   sandbox/channel/libs/channel/example/sample_dispatcher/dispatcher_text.html (contents, props changed)
   sandbox/channel/libs/channel/example/sample_dispatcher/pull_dispatcher_sample.hpp (contents, props changed)
   sandbox/channel/libs/channel/example/sample_dispatcher/sync_send_recv.cpp (contents, props changed)
   sandbox/channel/libs/channel/index.html (contents, props changed)
   sandbox/channel/libs/channel/test/

Added: sandbox/channel/boost/channel/binder.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/binder.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,94 @@
+//
+// binder.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BINDER_HPP
+#define BINDER_HPP
+
+namespace boost {
+ namespace channel {
+ /**
+ * The name_space filters/translators defined here only manipulte ids/msg-types
+ * and affect name_space management
+ * message content is UNTOUCHED!
+ */
+
+ /**
+ * filter_types:
+ * 1. provision the permissions which messages/ids can flow in/out
+ * channel thru interfaces
+ * 2. ONLY works on sub/pub msgs, not other(application) msgs
+ * affect how sub/pub msgs are exchanged between local channel and
+ * remote channel - how remote and local name_spaces "merge"
+ * not affect the normal message passing process
+ * 3. Default filter_types are "transparent" - all Ids allowed in/out:
+ *
+ */
+ template<class id_type>
+ class filter_type {
+ public:
+ virtual bool block_inward(id_type&) {
+ return false;
+ }
+ virtual bool block_outward(id_type&) {
+ return false;
+ }
+ virtual ~filter_type() {
+ }
+ };
+
+ /**
+ * translator_type:
+ * 1. translate inward/outward msg ids, help integration of name_spaces
+ * 2. ONLY works on application msgs
+ * affect (potentially change) each msgs passed in/out interfaces -
+ * must be highly efficient
+ * 3. Default translator_type is non-op
+ */
+ template<class id_type>
+ class translator_type {
+ public:
+ virtual void translate_inward(id_type&) {
+ }
+ virtual void translate_outward(id_type &id) {
+ }
+ virtual ~translator_type() {
+ }
+ };
+
+ /**
+ * binder_type:
+ * 1. affect ONLY the interface - the "binding" point between local
+ * channel and remote connections
+ * 2. contains both filter and transltor
+ * 3. if filters/translators are NULL, they are no-op
+ */
+ template<class id_type>
+ class binder_type {
+ public:
+ typedef boost::channel::filter_type<id_type> filter_type;
+ typedef boost::channel::translator_type<id_type> translator_type;
+ filter_type *filter;
+ translator_type *translator;
+ binder_type(filter_type *f = NULL, translator_type *t = NULL) {
+ filter = f;
+ translator = t;
+ }
+ ~binder_type() {
+ if (filter != NULL)
+ delete filter;
+ if (translator != NULL)
+ delete translator;
+ }
+ };
+
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/channel.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/channel.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,222 @@
+//
+// channel.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef CHANNEL_HPP
+#define CHANNEL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if !defined(WIN32_LEAN_AND_MEAN)
+# define WIN32_LEAN_AND_MEAN
+# endif // !defined(WIN32_LEAN_AND_MEAN)
+#endif
+
+#include <set>
+#include <boost/channel/binder.hpp>
+#include <boost/channel/connection.hpp>
+#include <boost/channel/peer.hpp>
+#include <boost/channel/dispatchers/broadcast_dispatcher.hpp>
+#include <boost/channel/dispatchers/round_robin_dispatcher.hpp>
+#include <boost/channel/dispatchers/always_latest_dispatcher.hpp>
+#include <boost/channel/dispatchers/pull_dispatcher.hpp>
+#include <boost/channel/executors/executor_base.hpp>
+#include <boost/channel/interface.hpp>
+#include <boost/channel/name_spaces/linear_id_trait.hpp>
+#include <boost/channel/name_spaces/assoc_id_trait.hpp>
+#include <boost/channel/name_spaces/linear_name_space.hpp>
+#include <boost/channel/name_spaces/hierarchical_id_trait.hpp>
+#include <boost/channel/name_spaces/hierarchical_name_space.hpp>
+#include <boost/channel/message.hpp>
+#include <boost/channel/named_in_out.hpp>
+#include <boost/channel/unnamed_in_out.hpp>
+#include <boost/channel/platforms/synch_policy.hpp>
+#include <boost/channel/platforms/boost_platform.hpp>
+#include <boost/channel/marshaler.hpp>
+#include <boost/channel/queues/queues.hpp>
+#include <boost/channel/pub_sub.hpp>
+
+namespace boost {
+ namespace channel {
+
+ template<
+ typename idtype,
+ typename platform_type = boost_platform,
+ typename synchpolicy = mt_synch<platform_type> ,
+ typename executor_type = abstract_executor, //force in-line execution
+ typename name_space = linear_name_space<idtype, executor_type, synchpolicy>,
+ typename dispatcher = broadcast_dispatcher<name_space, platform_type>
+ >
+ class channel: public id_trait<idtype> , public name_space {
+ public:
+ typedef idtype id_type;
+ typedef boost::channel::id_trait<id_type> id_trait;
+ typedef platform_type platform;
+ typedef synchpolicy synch_policy;
+ typedef name_space name_space_type;
+ typedef executor_type executor;
+ typedef dispatcher dispatch_policy;
+ typedef channel<id_type, platform, synch_policy, executor, name_space, dispatcher> channel_type;
+ typedef message<id_type> message_type;
+ typedef named_in<name_space_type, typename dispatch_policy::recver> in;
+ typedef named_out<name_space_type, typename dispatch_policy::sender> out;
+ typedef boost::channel::subscriber<name_space_type, typename dispatch_policy::recver> subscriber;
+ typedef boost::channel::publisher<name_space_type, typename dispatch_policy::sender> publisher;
+ typedef boost::channel::port<executor, id_type, platform, synch_policy, name_space_type, dispatch_policy> port;
+ typedef boost::channel::signal<executor, id_type, platform, synch_policy, name_space_type, dispatch_policy> signal;
+ typedef boost::channel::peer_type<id_type> peer_type;
+ typedef boost::channel::binder_type<id_type> binder_type;
+ typedef boost::channel::interface<channel_type> interface;
+ typedef boost::channel::connection<id_type> connection;
+ typedef marshaler_registry<id_type, id_trait, synch_policy, text_archive> text_marshaler_registry;
+ typedef marshaler_registry<id_type, id_trait, synch_policy, binary_archive> binary_marshaler_registry;
+ typedef marshaler_registry<id_type, id_trait, synch_policy, xml_archive> xml_marshaler_registry;
+ typedef named_in<name_space_type, typename broadcast_dispatcher<name_space, platform>::recver> sys_named_in;
+ typedef named_out<name_space_type, typename broadcast_dispatcher<name_space, platform>::sender> sys_named_out;
+ typedef named_out_bundle<name_space, typename broadcast_dispatcher<name_space, platform>::sender> sys_named_outs;
+ typedef named_in_bundle<name_space, typename broadcast_dispatcher<name_space, platform>::recver> sys_named_ins;
+
+ channel(executor *e = NULL) :
+ name_space(e) {
+ }
+
+ ~channel() {
+ platform::log("... channel destructor called ...");
+ for (typename std::set<interface*>::iterator iter = intfs_.begin(); iter != intfs_.end();) {
+ typename std::set<interface*>::iterator curr = iter++;
+ //need to get to next first, release() will callback and remove iter from set
+ //release interface and kill connection; interface obj will be
+ //deleted in connection's destructor
+ (*curr)->release();
+ }
+ }
+
+ template<typename recver_type>
+ in * bind_name_in(id_type id, recver_type r, typename in::scope_type scope = in::scope_global,
+ typename in::member_type type = in::member_local, executor *e = NULL) {
+ return new in(*this, id, r, scope, type, e);
+ }
+ out * bind_name_out(id_type id, typename out::scope_type scope = out::scope_global,
+ typename out::member_type type = out::member_local, executor *e = NULL) {
+ return new out(*this, id, scope, type, e);
+ }
+
+ void add_intf(interface *c) {
+ typename synch_policy::scoped_lock lock(lock_);
+ intfs_.insert(c);
+ }
+
+ void del_intf(interface *c) {
+ typename synch_policy::scoped_lock lock(lock_);
+ intfs_.erase(c);
+ }
+
+ int num_conn(void) {
+ return intfs_.size();
+ }
+
+ private:
+ typename synch_policy::mutex lock_;
+ std::set<interface *> intfs_;
+ };
+
+ /**
+ * function to connect 2 local channels of the same type
+ */
+ template<typename channel>
+ typename channel::connection* connect(channel &peer1, channel &peer2,
+ typename channel::binder_type *binder1 = NULL,
+ typename channel::binder_type *binder2 = NULL) {
+ typedef typename channel::interface interface;
+ typedef typename channel::peer_type peer_type;
+ typedef typename channel::connection connection;
+ interface *intf1 = new interface(peer1, binder1);
+ interface *intf2 = new interface(peer2, binder2);
+ connection *conn = new connection(connection::local_connection,
+ intf1, intf2);
+ intf1->bind_peer(intf2, peer_type::active_role, conn);
+ intf2->bind_peer(intf1, peer_type::passive_role, conn);
+
+ //start connection setup hand-shaking
+ intf1->send2remote_channel_info_msg();
+
+ return conn;
+ }
+
+ /**
+ * function to connect 2 local channels of different types
+ */
+ template <typename channel1, typename channel2>
+ typename channel1::connection* connect(channel1 &peer1, channel2 &peer2,
+ typename channel1::binder_type *binder1 = NULL,
+ typename channel2::binder_type *binder2 = NULL) {
+ typedef typename channel1::interface interface1;
+ typedef typename channel2::interface interface2;
+ typedef typename channel1::peer_type peer_type;
+ typedef typename channel1::connection connection;
+ interface1 *intf1 = new interface1(peer1, binder1);
+ interface2 *intf2 = new interface2(peer2, binder2);
+ connection *conn = new connection(connection::local_connection,
+ intf1, intf2);
+ intf1->bind_peer(intf2, peer_type::active_role, conn);
+ intf2->bind_peer(intf1, peer_type::passive_role, conn);
+
+ //start connection setup hand-shaking
+ intf1->send2remote_channel_info_msg();
+
+ return conn;
+ }
+
+ /**
+ * function to connect local channel to remote peer thru a stream obj
+ */
+ template <typename channel, typename stream_t>
+ typename channel::connection* connect(channel &peer,
+ stream_t * stream,
+ bool active,
+ typename channel::binder_type *binder = NULL
+ )
+ {
+ typedef typename channel::interface interface;
+ typedef typename channel::peer_type peer_type;
+ typedef typename channel::connection connection;
+ interface *intf = new interface(peer, binder);
+ connection *conn = new connection(connection::remote_connection,
+ intf, stream);
+ intf->bind_peer(stream, active?peer_type::active_role:peer_type::passive_role, conn);
+ stream->bind_peer(intf, active?peer_type::active_role:peer_type::passive_role, conn);
+
+ if (active) {
+ //start connection setup hand-shaking
+ intf->send2remote_channel_info_msg();
+ }
+
+ return conn;
+ }
+
+ /**
+ * generic functions to directly bind/unbind any pair of named_out and named_in
+ */
+ template <typename name>
+ void bind(name *named_out, name *named_in) {
+ named_out->bind(named_in);
+ named_in->bind(named_out);
+ }
+ template <typename name>
+ void unbind(name *named_out, name *named_in) {
+ named_out->unbind(named_in);
+ named_in->unbind(named_out);
+ }
+
+}
+}
+
+#endif

Added: sandbox/channel/boost/channel/connection.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/connection.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,43 @@
+//
+// connection.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef CONNECTION_HPP
+#define CONNECTION_HPP
+
+#include <set>
+#include <boost/channel/peer.hpp>
+
+namespace boost {
+ namespace channel {
+
+ template<typename id_type>
+ class connection {
+ public:
+ typedef boost::channel::peer_type<id_type> peer_type;
+ enum type {
+ local_connection = 0, remote_connection
+ };
+ type type_;
+ peer_type *peer1_, *peer2_;
+ connection(type t, peer_type *peer1, peer_type *peer2) :
+ type_(t), peer1_(peer1), peer2_(peer2) {
+ }
+
+ ~connection() {
+ peer1_->unbind();
+ peer2_->unbind();
+ delete peer1_;
+ if (type_ == local_connection)
+ delete peer2_; //should we delete stream for remote_conn?
+ }
+ };
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/dispatchers/always_latest_dispatcher.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/dispatchers/always_latest_dispatcher.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,64 @@
+//
+// always_latest_dispatcher.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ALWAYS_LATEST_DISPATCHER_HPP
+#define ALWAYS_LATEST_DISPATCHER_HPP
+
+////imitate plan9/inferno's "union" name_space:
+////later bound names will overlap older names, ie. latest mounted server will
+////take over and serve all msgs on the covered names
+////so always the latest bound name get dispatched
+
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <boost/shared_ptr.hpp>
+#include <boost/channel/platforms/synch_policy.hpp>
+#include <boost/channel/message.hpp>
+#include <boost/channel/name.hpp>
+#include <boost/channel/named_in_out.hpp>
+#include <boost/channel/dispatchers/dispatcher_base.hpp>
+#include <boost/channel/dispatchers/push_dispatcher_base.hpp>
+
+namespace boost {
+ namespace channel {
+
+ namespace detail {
+
+ template<typename name_space, typename platform>
+ struct always_latest_algo {
+ typedef typename name_space::id_type id_type;
+ typedef message<id_type> msg_type;
+ typedef push_recver_base<name_space,platform> recver_type;
+ typedef named_in<name_space, recver_type> named_in_type;
+
+ template<typename bindings_type>
+ void operator() (bindings_type &bindings,
+ boost::shared_ptr<msg_type> msg) {
+ if (!bindings.empty()) {
+ typename bindings_type::iterator iter = bindings.begin();
+ named_in_type *named_in = (named_in_type *)(*iter);
+ recver_type *recver = (recver_type *)named_in;
+ recver->push(msg);
+ }
+ }
+ };
+
+ }
+
+ template <typename name_space, typename platform>
+ struct always_latest_dispatcher {
+ typedef detail::push_sender_base<name_space,platform,detail::always_latest_algo> sender;
+ typedef detail::push_recver_base<name_space,platform> recver;
+ };
+
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/dispatchers/arbiters_async.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/dispatchers/arbiters_async.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,331 @@
+//
+// arbiters_async.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+
+#ifndef ARBITERS_ASYNC_HPP
+#define ARBITERS_ASYNC_HPP
+
+#include <deque>
+#include <list>
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+#include <boost/channel/queues/unbounded_queue.hpp>
+#include <boost/channel/dispatchers/pull_dispatcher_base.hpp>
+
+namespace boost {
+ namespace channel {
+ namespace detail {
+
+ /**
+ * Async arbiters:
+ * asynch message passing synchronization patterns (choice, join)
+ * part of pull_dispatcher
+ * see CCR and Comega document
+ */
+ /**
+ * choice
+ */
+ template<typename name_space, typename platform,
+ template<class , class , class > class queue_type = unbounded_que>
+ class choice_arbiter_async {
+ public:
+ typedef pull_recver_base<name_space, platform, queue_type> recver_type;
+ typedef pull_sender_base<name_space, platform, queue_type> sender_type;
+ typedef typename name_space::id_type id_type;
+ typedef typename name_space::name name;
+ typedef typename name_space::synch_policy synch_policy;
+ typedef typename name_space::executor executor;
+ typedef message<id_type> msg_type;
+ typedef named_in<name_space, recver_type> named_in_type;
+ typedef named_out<name_space, sender_type> named_out_type;
+ typedef choice_arbiter_async<name_space,platform,queue_type> my_type;
+
+ typedef boost::function1<void, boost::shared_ptr<void> > call_back_t;
+
+ name_space *ch_;
+ executor *exec_;
+ struct entry {
+ named_in_type *in_;
+ call_back_t handler_;
+ ~entry() {
+ if (in_ != NULL) delete in_;
+ }
+ };
+ std::map<id_type, entry*> ins_map_;
+ std::deque<entry*> ins_;
+ typename synch_policy::mutex mutex_;
+
+ choice_arbiter_async(name_space &ch, executor *e = NULL) :
+ ch_(&ch),
+ exec_(e!=NULL?e:ch.get_exec()) {}
+
+ choice_arbiter_async(executor *e = NULL) :
+ ch_(NULL),
+ exec_(e) {}
+
+ ~choice_arbiter_async() {
+ typename synch_policy::scoped_lock lock(mutex_);
+ typename std::deque<entry*>::iterator iter;
+ for (iter = ins_.begin(); iter != ins_.end(); iter++)
+ if ((*iter) != NULL) {
+ delete (*iter);
+ }
+ }
+
+ //called from inside dispatcher
+ void invoke(named_in_type * &in, id_type, boost::shared_ptr<void>) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ typename std::deque<entry*>::iterator iter;
+ bool found = false;
+ for(iter = ins_.begin(); iter != ins_.end() && !found; iter++)
+ if(in == (*iter)->in_) {
+ found = true;
+ break;
+ }
+ if(found && in->claim()) {
+ boost::shared_ptr<msg_type> msg;
+ if (in->pull(msg) > 0) {
+ //successfully get a msg here, should we use executor to run callback?
+ //since invoke already run in executor, so dont delay again
+ (*iter)->handler_(msg->data_);
+ }
+ }
+ }
+
+ bool bind(id_type & id,
+ call_back_t cb,
+ typename named_in_type::scope_type scope = named_in_type::scope_global) {
+ if (ch_ == NULL) return false;
+ typename synch_policy::scoped_lock lock(mutex_);
+ if (ins_map_.find(id) == ins_map_.end()) {
+ entry * ent = new entry();
+ ent->in_ = new named_in_type(*ch_,id,
+ boost::bind(&my_type::invoke, this, boost::ref(ent->in_), _1, _2),
+ scope,named_in_type::member_local,exec_);
+ ent->handler_ = cb;
+ ins_.push_back(ent);
+ ins_map_[id] = ent;
+ return true;
+ }
+ return false;
+ }
+
+ bool unbind(id_type & id) {
+ if (ch_ == NULL) return false;
+ typename synch_policy::scoped_lock lock(mutex_);
+ typename std::map<id_type, entry*>::iterator iter = ins_map_.find(id);
+ if (iter != ins_map_.end()) {
+ delete iter->second;
+ ins_.erase(iter->second);
+ ins_map_.erase(iter);
+ return true;
+ }
+ return false;
+ }
+
+ bool bind(named_out_type & no, call_back_t cb) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ entry * ent = new entry();
+ ent->in_ = new named_in_type(boost::bind(&my_type::invoke, this, boost::ref(ent->in_), _1, _2),
+ exec_);
+ ent->handler_ = cb;
+ ins_.push_back(ent);
+ //bind named_out and named_in
+ no.bind(ent->in_);
+ ent->in_->bind(&no);
+ return true;
+ }
+
+ bool unbind(named_out_type & no) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ std::list<name *> & bindings = no.bindings();
+ typename std::list<name *>::iterator iter, curr;
+ typename std::deque<entry*>::iterator iterq;
+ for(iter = bindings.begin(); iter != bindings.end(); ) {
+ curr = iter; iter++;
+ named_in_type *ni = (*curr);
+ iterq = std::find(ins_.begin(), ins_.end(),ni);
+ if (iterq != ins_.end()) {
+ ins_.erase(iterq);
+ delete ni;
+ }
+ }
+ return true;
+ }
+
+ };
+
+ /**
+ * join
+ */
+ template <typename name_space, typename platform,
+ template <class,class,class> class queue_type = unbounded_que>
+ class join_arbiter_async {
+ public:
+ public:
+ typedef pull_recver_base<name_space,platform,queue_type> recver_type;
+ typedef pull_sender_base<name_space,platform,queue_type> sender_type;
+ typedef typename name_space::id_type id_type;
+ typedef typename name_space::name name;
+ typedef typename name_space::synch_policy synch_policy;
+ typedef typename name_space::executor executor;
+ typedef message<id_type> msg_type;
+ typedef named_in<name_space, recver_type> named_in_type;
+ typedef named_out<name_space, sender_type> named_out_type;
+ typedef join_arbiter_async<name_space,platform,queue_type> my_type;
+
+ typedef boost::function1<void, std::vector<boost::shared_ptr<void> >& > call_back_t;
+
+ name_space *ch_;
+ executor *exec_;
+ call_back_t handler_;
+ std::deque<named_in_type*> ins_;
+ std::map<id_type, named_in_type*> ins_map_; //keep locking order
+ typename synch_policy::mutex mutex_;
+
+ join_arbiter_async(name_space &ch,
+ std::vector<std::pair<id_type, typename named_in_type::scope_type> > & ids,
+ call_back_t cb,
+ executor *e = NULL) :
+ ch_(&ch),
+ exec_(e!=NULL?e:ch.get_exec()),
+ handler_(cb) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ typename std::vector<std::pair<id_type,
+ typename named_in_type::scope_type> >::iterator iter;
+ for(iter = ids.begin(); iter != ids.end(); iter++) {
+ named_in_type * ni = new named_in_type(*ch_,iter->first,
+ boost::bind(&my_type::invoke, this, _1, _2),
+ iter->second,
+ named_in_type::member_local,exec_);
+ ins_.push_back(ni); //keep order to avoid deadlock
+ ins_map_[iter->first] = ni;
+ }
+ }
+
+ join_arbiter_async(name_space &ch,
+ call_back_t cb,
+ executor *e = NULL) :
+ ch_(&ch),
+ exec_(e!=NULL?e:ch.get_exec()),
+ handler_(cb) {
+ }
+
+ join_arbiter_async(call_back_t cb, executor *e = NULL) :
+ ch_(NULL),
+ exec_(e),
+ handler_(cb) {}
+
+ ~join_arbiter_async() {
+ typename synch_policy::scoped_lock lock(mutex_);
+ typename std::deque<named_in_type*>::iterator iter;
+ for (iter = ins_.begin(); iter != ins_.end(); iter++)
+ delete (*iter);
+ }
+
+ //called from inside dispatcher
+ //2 phase protocol
+ void invoke(id_type, boost::shared_ptr<void>) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ typename std::deque<named_in_type*>::iterator iter;
+ //first claim the messages
+ //for (typename std::map<id_type,named_in_type*>::iterator iter1 = ins_map_.begin(); iter1 != ins_map_.end(); iter1++) {
+ for (iter = ins_.begin(); iter != ins_.end(); iter++) {
+ named_in_type *in = (*iter);
+ if(!in->claim()) {
+ //roll back
+ //for (typename std::map<id_type,named_in_type*>::iterator iter2 = ins_map_.begin();
+ //iter2 != iter1; iter2++)
+ for (typename std::deque<named_in_type*>::iterator iter2 = ins_.begin();
+ iter2 != iter; iter2++)
+ (*iter2)->unclaim();
+ return;
+ }
+ }
+ //reaching here, we have claimed all the member messages,
+ //commit (pull msgs and run callback)
+ boost::shared_ptr<msg_type> msg;
+ std::vector<boost::shared_ptr<void> > result;
+ for (iter = ins_.begin(); iter != ins_.end(); iter++) {
+ named_in_type *in = (*iter);
+ msg.reset();
+ in->pull(msg);
+ result.push_back(msg->data_);
+ }
+ handler_(result);
+ }
+
+ bool bind(id_type & id,
+ typename named_in_type::scope_type scope = named_in_type::scope_global) {
+ if (ch_ == NULL) return false;
+ typename synch_policy::scoped_lock lock(mutex_);
+ typename std::deque<named_in_type*>::iterator iter;
+ for(iter = ins_.begin(); iter != ins_.end(); iter++)
+ if ((*iter)->id_ == id)
+ return false;
+ named_in_type * ni = new named_in_type(*ch_,id,
+ boost::bind(&my_type::invoke, this, _1, _2),
+ scope,
+ named_in_type::member_local,exec_);
+ ins_.push_back(ni); //keep order to avoid deadlock
+ ins_map_[id] = ni;
+ return true;
+ }
+
+ bool unbind(id_type & id) {
+ if (ch_ == NULL) return false;
+ typename synch_policy::scoped_lock lock(mutex_);
+ typename std::deque<named_in_type*>::iterator iter;
+ for(iter = ins_.begin(); iter != ins_.end(); iter++)
+ if ((*iter)->id_ == id) {
+ ins_map_.erase(id);
+ delete (*iter);
+ ins_.erase(iter);
+ return true;
+ }
+ return false;
+ }
+
+ bool bind(named_out_type & no, call_back_t cb) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ named_in_type * ni = new named_in_type(boost::bind(&my_type::invoke, this, _1, _2),
+ exec_);
+ ins_.push_back(ni);
+ //bind named_out and named_in
+ no.bind(ni);
+ ni->bind(&no);
+ return true;
+ }
+
+ bool unbind(named_out_type & no) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ std::list<name *> & bindings = no.bindings();
+ typename std::list<name *>::iterator iter, curr;
+ typename std::deque<name *>::iterator iterq;
+ for(iter = bindings.begin(); iter != bindings.end(); ) {
+ curr = iter; iter++;
+ named_in_type *ni = (*curr);
+ iterq = std::find(ins_.begin(), ins_.end(),ni);
+ if (iterq != ins_.end()) {
+ ins_.erase(iterq);
+ delete ni;
+ }
+ }
+ return true;
+ }
+ };
+
+ }
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/dispatchers/arbiters_sync.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/dispatchers/arbiters_sync.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,450 @@
+//
+// arbiters_sync.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+
+#ifndef ARBITERS_SYNC_HPP
+#define ARBITERS_SYNC_HPP
+
+#include <deque>
+#include <list>
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+#include <boost/channel/queues/unbounded_queue.hpp>
+#include <boost/channel/dispatchers/pull_dispatcher_base.hpp>
+
+namespace boost {
+ namespace channel {
+
+ namespace detail {
+
+ /**
+ * synchronous arbiters:
+ * message passing synchronization patterns (choice, join)
+ * part of pull_dispatcher
+ * see CCR and Comega document
+ */
+ /**
+ * choice
+ */
+ template<typename name_space, typename platform,
+ template<class , class , class > class queue_type = unbounded_que>
+ class choice_arbiter_sync {
+ public:
+ typedef pull_recver_base<name_space, platform, queue_type> recver_type;
+ typedef pull_sender_base<name_space, platform, queue_type> sender_type;
+ typedef typename name_space::id_type id_type;
+ typedef typename name_space::name name;
+ typedef typename name_space::synch_policy synch_policy;
+ typedef message<id_type> msg_type;
+ typedef named_in<name_space, recver_type> named_in_type;
+ typedef named_out<name_space, sender_type> named_out_type;
+ typedef choice_arbiter_sync<name_space,platform,queue_type> my_type;
+
+ typedef boost::function1<void, boost::shared_ptr<void> > call_back_t;
+
+ name_space *ch_;
+ struct entry {
+ named_in_type *in_;
+ call_back_t handler_;
+ ~entry() {
+ if (in_ != NULL) delete in_;
+ }
+ };
+ std::map<id_type, entry*> ins_map_;
+ std::deque<entry*> ins_;
+ typename synch_policy::mutex mutex_;
+ typename synch_policy::condition cond_;
+ int num_waiting_;
+ bool ready_in_set;
+ named_in_type *ready_in;
+
+ choice_arbiter_sync(name_space &ch) :
+ ch_(&ch), num_waiting_(0), ready_in_set(false), ready_in(NULL) {}
+
+ ~choice_arbiter_sync() {
+ typename synch_policy::scoped_lock lock(mutex_);
+ typename std::deque<entry*>::iterator iter;
+ for (iter = ins_.begin(); iter != ins_.end(); iter++)
+ if ((*iter) != NULL) {
+ delete (*iter);
+ }
+ }
+
+ //recving thread will block here and wait for notify from senders
+ void recv(id_type & id, boost::shared_ptr<void> & msg) {
+ boost::shared_ptr<msg_type> mesg;
+ typename std::deque<entry*>::iterator iter;
+ typename synch_policy::scoped_lock lock(mutex_);
+ while(1) {
+ //pull data
+ if (ready_in_set) {
+ ready_in_set = false;
+ named_in_type *in = ready_in;
+ bool found = false;
+ for(iter = ins_.begin(); iter != ins_.end() && !found; iter++)
+ if(in == (*iter)->in_) {
+ found = true;
+ break;
+ }
+ if(found && in->claim()) {
+ if (in->pull(mesg) > 0) {
+ if ((*iter)->handler_)
+ (*iter)->handler_(mesg->data_);
+ id = mesg->id_;
+ msg = mesg->data_;
+ return;
+ }
+ }
+ }
+ else {
+ for(iter = ins_.begin(); iter != ins_.end(); iter++) {
+ named_in_type *in = (*iter)->in_;
+ if(in->claim()) {
+ if (in->pull(mesg) > 0) {
+ if ((*iter)->handler_)
+ (*iter)->handler_(mesg->data_);
+ id = mesg->id_;
+ msg = mesg->data_;
+ return;
+ }
+ }
+ }
+ }
+ num_waiting_++;
+ cond_.wait(lock);
+ num_waiting_--;
+ }
+ }
+
+ //recving thread will block here and wait for notify from senders
+ void wait(void) {
+ boost::shared_ptr<msg_type> mesg;
+ typename std::map<id_type, entry>::iterator iter;
+ typename synch_policy::scoped_lock lock(mutex_);
+ while(1) {
+ //pull data
+ if (ready_in_set) {
+ ready_in_set = false;
+ named_in_type *in = ready_in;
+ bool found = false;
+ for(iter = ins_.begin(); iter != ins_.end() && !found; iter++)
+ if(in == iter->in_) {
+ found = true;
+ break;
+ }
+ if(found && in->claim()) {
+ if (in->pull(mesg) > 0) {
+ if (iter->handler_)
+ iter->handler_(mesg->data_);
+ return;
+ }
+ }
+ }
+ else {
+ for(iter = ins_.begin(); iter != ins_.end(); iter++) {
+ named_in_type *in = iter->in_;
+ if(in->claim()) {
+ if (in->pull(mesg) > 0) {
+ if (iter->handler_)
+ iter->handler_(mesg->data_);
+ return;
+ }
+ }
+ }
+ }
+ num_waiting_++;
+ cond_.wait(lock);
+ num_waiting_--;
+ }
+ }
+
+ //called from inside dispatcher
+ void invoke(named_in_type * &ni, id_type, boost::shared_ptr<void>) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ ready_in = ni;
+ ready_in_set = true;
+ if (num_waiting_ > 0)
+ cond_.notify_one();
+ }
+
+ bool bind(id_type & id,
+ call_back_t cb = 0,
+ typename named_in_type::scope_type scope = named_in_type::scope_global) {
+ if (ch_ == NULL) return false;
+ typename synch_policy::scoped_lock lock(mutex_);
+ if (ch_ != NULL && ins_map_.find(id) == ins_map_.end()) {
+ entry *ent = new entry();
+ ent->in_ = new named_in_type(*ch_,id,
+ boost::bind(&my_type::invoke, this, boost::ref(ent->in_), _1, _2),
+ scope);
+ ent->handler_ = cb;
+ ins_.push_back(ent);
+ ins_map_[id] = ent;
+ return true;
+ }
+ return false;
+ }
+
+ bool unbind(id_type & id) {
+ if (ch_ == NULL) return false;
+ typename synch_policy::scoped_lock lock(mutex_);
+ typename std::map<id_type, entry*>::iterator iter = ins_map_.find(id);
+ if (iter != ins_map_.end()) {
+ delete iter->second;
+ ins_.erase(iter->second);
+ ins_map_.erase(iter);
+ return true;
+ }
+ return false;
+ }
+
+ bool bind(named_out_type & no, call_back_t cb) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ entry * ent = new entry();
+ ent->in_ = new named_in_type(boost::bind(&my_type::invoke, this, boost::ref(ent->in_), _1, _2));
+ ent->handler_ = cb;
+ ins_.push_back(ent);
+ //bind named_out and named_in
+ no.bind(ent->in_);
+ ent->in_->bind(&no);
+ return true;
+ }
+
+ bool unbind(named_out_type & no) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ std::list<name *> & bindings = no.bindings();
+ typename std::list<name *>::iterator iter, curr;
+ typename std::deque<entry*>::iterator iterq;
+ for(iter = bindings.begin(); iter != bindings.end(); ) {
+ curr = iter; iter++;
+ named_in_type *ni = (*curr);
+ iterq = ins_.find(ni);
+ if (iterq != ins_.end()) {
+ ins_.erase(ni);
+ delete ni;
+ }
+ }
+ return true;
+ }
+
+ };
+
+ /**
+ * join
+ */
+ template <typename name_space, typename platform,
+ template <class,class,class> class queue_type = unbounded_que>
+ class join_arbiter_sync {
+ public:
+ public:
+ typedef pull_recver_base<name_space,platform,queue_type> recver_type;
+ typedef pull_sender_base<name_space,platform,queue_type> sender_type;
+ typedef typename name_space::id_type id_type;
+ typedef typename name_space::name name;
+ typedef typename name_space::synch_policy synch_policy;
+ typedef message<id_type> msg_type;
+ typedef named_in<name_space, recver_type> named_in_type;
+ typedef named_out<name_space, sender_type> named_out_type;
+ typedef join_arbiter_sync<name_space,platform,queue_type> my_type;
+
+ typedef boost::function1<void, std::vector<boost::shared_ptr<void> >& > call_back_t;
+
+ name_space *ch_;
+ call_back_t handler_;
+ std::deque<named_in_type*> ins_; //keep parameter order
+ std::map<id_type, named_in_type*> ins_map_; //keep locking order
+ typename synch_policy::mutex mutex_;
+ typename synch_policy::condition cond_;
+ int num_waiting_;
+
+ join_arbiter_sync(name_space &ch,
+ std::vector<std::pair<id_type, typename named_in_type::scope_type> > & ids,
+ call_back_t cb = 0) :
+ ch_(&ch),
+ handler_(cb), num_waiting_(0) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ typename std::vector<std::pair<id_type,
+ typename named_in_type::scope_type> >::iterator iter;
+ for(iter = ids.begin(); iter != ids.end(); iter++) {
+ named_in_type * ni = new named_in_type(*ch_,iter->first,
+ boost::bind(&my_type::invoke, this, _1, _2),
+ iter->second);
+ ins_.push_back(ni);
+ ins_map_[iter->first] = ni;
+ }
+ }
+
+ join_arbiter_sync(name_space &ch,
+ call_back_t cb = 0) :
+ ch_(&ch),
+ handler_(cb), num_waiting_(0) {
+ }
+
+ join_arbiter_sync(call_back_t cb = 0) :
+ ch_(NULL),
+ handler_(cb), num_waiting_(0) {
+ }
+
+ ~join_arbiter_sync() {
+ typename synch_policy::scoped_lock lock(mutex_);
+ typename std::deque<named_in_type*>::iterator iter;
+ for (iter = ins_.begin(); iter != ins_.end(); iter++)
+ delete (*iter);
+ }
+
+ //called from inside dispatcher
+ //2 phase protocol
+ void recv(std::vector<boost::shared_ptr<void> > & result) {
+ boost::shared_ptr<msg_type> msg;
+ typename std::deque<named_in_type*>::iterator iter;
+ typename synch_policy::scoped_lock lock(mutex_);
+ while(1) {
+ bool claimed = true;
+ //first claim the messages in proper order based on ids to avoid deadlock
+ for (iter = ins_.begin(); iter != ins_.end() && claimed; iter++) {
+ named_in_type *in = (*iter);
+ if(!in->claim()) {
+ //roll back
+ for (typename std::deque<named_in_type*>::iterator iter2 = ins_.begin();
+ iter2 != iter; iter2++)
+ (*iter2)->unclaim();
+ claimed = false;
+ }
+ }
+ if(claimed) {
+ //reaching here, we have claimed all the member messages,
+ //commit (pull msgs and run callback)
+ result.clear();
+ for (iter = ins_.begin(); iter != ins_.end(); iter++) {
+ named_in_type *in = (*iter);
+ msg.reset();
+ in->pull(msg);
+ result.push_back(msg->data_);
+ }
+ if(handler_)
+ handler_(result);
+ return;
+ } else {
+ num_waiting_++;
+ cond_.wait(lock);
+ num_waiting_--;
+ }
+ }
+ }
+ void wait(void) {
+ boost::shared_ptr<msg_type> msg;
+ std::vector<boost::shared_ptr<void> > result;
+ typename std::deque<named_in_type*>::iterator iter;
+ typename synch_policy::scoped_lock lock(mutex_);
+ while(1) {
+ bool claimed = true;
+ //first claim the messages in proper order based on ids to avoid deadlock
+ for (iter = ins_.begin(); iter != ins_.end() && claimed; iter++) {
+ named_in_type *in = (*iter);
+ if(!in->claim()) {
+ //roll back
+ for (typename std::deque<named_in_type*>::iterator iter2 = ins_.begin();
+ iter2 != iter; iter2++)
+ (*iter2)->unclaim();
+ claimed = false;
+ }
+ }
+ if(claimed) {
+ //reaching here, we have claimed all the member messages,
+ //commit (pull msgs and run callback)
+ result.clear();
+ for (iter = ins_.begin(); iter != ins_.end(); iter++) {
+ named_in_type *in = (*iter);
+ msg.reset();
+ in->pull(msg);
+ result.push_back(msg->data_);
+ }
+ if(handler_)
+ handler_(result);
+ return;
+ } else {
+ num_waiting_++;
+ cond_.wait(lock);
+ num_waiting_--;
+ }
+ }
+ }
+
+ void invoke(id_type, boost::shared_ptr<void>) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ if (num_waiting_ > 0)
+ cond_.notify_one();
+ }
+
+ bool bind(id_type & id,
+ typename named_in_type::scope_type scope = named_in_type::scope_global) {
+ if (ch_ == NULL) return false;
+ typename synch_policy::scoped_lock lock(mutex_);
+ typename std::deque<named_in_type*>::iterator iter;
+ for(iter = ins_.begin(); iter != ins_.end(); iter++)
+ if ((*iter)->id_ == id)
+ return false;
+ named_in_type * ni = new named_in_type(*ch_,id,
+ boost::bind(&my_type::invoke, this, _1, _2),
+ scope);
+ ins_.push_back(ni); //keep order to avoid deadlock
+ ins_map_[id] = ni;
+ return true;
+ }
+
+ bool unbind(id_type & id) {
+ if (ch_ == NULL) return false;
+ typename synch_policy::scoped_lock lock(mutex_);
+ typename std::deque<named_in_type*>::iterator iter;
+ for(iter = ins_.begin(); iter != ins_.end(); iter++)
+ if ((*iter)->id_ == id) {
+ ins_map_.erase(id);
+ delete (*iter);
+ ins_.erase(iter);
+ return true;
+ }
+ return false;
+ }
+
+ bool bind(named_out_type & no, call_back_t cb) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ named_in_type * ni = new named_in_type(boost::bind(&my_type::invoke, this, _1, _2));
+ ins_.push_back(ni);
+ //bind named_out and named_in
+ no.bind(ni);
+ ni->bind(&no);
+ return true;
+ }
+
+ bool unbind(named_out_type & no) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ std::list<name *> & bindings = no.bindings();
+ typename std::list<name *>::iterator iter, curr;
+ typename std::deque<name *>::iterator iterq;
+ for(iter = bindings.begin(); iter != bindings.end(); ) {
+ curr = iter; iter++;
+ named_in_type *ni = (*curr);
+ iterq = ins_.find(ni);
+ if (iterq != ins_.end()) {
+ ins_.erase(ni);
+ delete ni;
+ }
+ }
+ return true;
+ }
+ };
+
+ }
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/dispatchers/broadcast_dispatcher.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/dispatchers/broadcast_dispatcher.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,65 @@
+//
+// broadcast_dispatcher.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+
+//// broadcast dispatcher
+
+#ifndef BROADCAST_DISPATCHER_HPP
+#define BROADCAST_DISPATCHER_HPP
+
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <boost/shared_ptr.hpp>
+#include <boost/channel/platforms/synch_policy.hpp>
+#include <boost/channel/message.hpp>
+#include <boost/channel/name.hpp>
+#include <boost/channel/named_in_out.hpp>
+#include <boost/channel/dispatchers/dispatcher_base.hpp>
+#include <boost/channel/dispatchers/push_dispatcher_base.hpp>
+
+namespace boost {
+ namespace channel {
+
+ namespace detail {
+
+ //the following is for 3 simple "push" dispatchers: broadcast, roundrobin, union
+ template<typename name_space, typename platform>
+ struct broadcast_algo {
+ typedef typename name_space::id_type id_type;
+ typedef message<id_type> msg_type;
+ typedef push_recver_base<name_space,platform> recver_type;
+ typedef named_in<name_space, recver_type> named_in_type;
+
+ template<typename bindings_type>
+ void operator() (bindings_type &bindings,
+ boost::shared_ptr<msg_type> msg) {
+ if (!bindings.empty()) {
+ for(typename bindings_type::iterator iter = bindings.begin();
+ iter != bindings.end(); iter++) {
+ named_in_type *named_in = (named_in_type *)(*iter);
+ recver_type *recver = (recver_type *)named_in;
+ recver->push(msg);
+ }
+ }
+ }
+ };
+
+ }
+
+ template <typename name_space, typename platform>
+ struct broadcast_dispatcher {
+ typedef detail::push_sender_base<name_space,platform,detail::broadcast_algo> sender;
+ typedef detail::push_recver_base<name_space,platform> recver;
+ };
+
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/dispatchers/dispatcher_base.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/dispatchers/dispatcher_base.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,138 @@
+//
+// dispatcher_base.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+
+//// dispatcher_base:
+//// base handler definitions; should we use boost::function instead?
+////
+
+#ifndef DISPATCHER_BASE_HPP
+#define DISPATCHER_BASE_HPP
+
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <boost/shared_ptr.hpp>
+
+namespace boost {
+ namespace channel {
+
+ namespace detail {
+
+ //message handlers; should i use boost::function instead of
+ //duplicating all these code?
+ template<typename id_type>
+ class msg_handler_base {
+ public:
+ void invoke(id_type id, boost::shared_ptr<void> msg) {
+ invoke_func_(this, id, msg);
+ }
+
+ void destroy() {
+ destroy_func_(this);
+ }
+
+ protected:
+ typedef void (*invoke_func_type)(msg_handler_base*, id_type id,
+ boost::shared_ptr<void> msg);
+ typedef void (*destroy_func_type)(msg_handler_base*);
+
+ msg_handler_base(invoke_func_type invoke_func,
+ destroy_func_type destroy_func) :
+ invoke_func_(invoke_func), destroy_func_(destroy_func) {
+ }
+
+ ~msg_handler_base() {
+ }
+
+ private:
+ invoke_func_type invoke_func_;
+ destroy_func_type destroy_func_;
+ };
+
+ template<typename id_type, typename handler_type>
+ class msg_handler: public msg_handler_base<id_type> {
+ typedef detail::msg_handler_base<id_type> msg_handler_base;
+ public:
+ msg_handler(handler_type handler) :
+ msg_handler_base(&msg_handler<id_type, handler_type>::invoke_handler,
+ &msg_handler<id_type, handler_type>::destroy_handler),
+ handler_(handler) {
+ }
+
+ static void invoke_handler(msg_handler_base* base, id_type id,
+ boost::shared_ptr<void> msg) {
+ static_cast<msg_handler<id_type, handler_type>*> (base)->handler_(id,
+ msg);
+ }
+
+ static void destroy_handler(msg_handler_base* base) {
+ delete static_cast<msg_handler<id_type, handler_type>*> (base);
+ }
+
+ private:
+ handler_type handler_;
+ };
+
+ template<typename id_type>
+ class msg_handler_base2 {
+ public:
+ void invoke(id_type id) {
+ invoke_func_(this, id);
+ }
+
+ void destroy() {
+ destroy_func_(this);
+ }
+
+ protected:
+ typedef void (*invoke_func_type)(msg_handler_base2*, id_type id);
+ typedef void (*destroy_func_type)(msg_handler_base2*);
+
+ msg_handler_base2(invoke_func_type invoke_func,
+ destroy_func_type destroy_func) :
+ invoke_func_(invoke_func), destroy_func_(destroy_func) {
+ }
+
+ ~msg_handler_base2() {
+ }
+
+ private:
+ invoke_func_type invoke_func_;
+ destroy_func_type destroy_func_;
+ };
+
+ template<typename id_type, typename handler_type>
+ class msg_handler2: public msg_handler_base2<id_type> {
+ typedef detail::msg_handler_base2<id_type> msg_handler_base2;
+ public:
+ msg_handler2(handler_type handler) :
+ msg_handler_base2(&msg_handler2<id_type, handler_type>::invoke_handler,
+ &msg_handler2<id_type, handler_type>::destroy_handler),
+ handler_(handler) {
+ }
+
+ static void invoke_handler(msg_handler_base2* base, id_type id) {
+ static_cast<msg_handler2<id_type, handler_type>*> (base)->handler_(id);
+ }
+
+ static void destroy_handler(msg_handler_base2* base) {
+ delete static_cast<msg_handler2<id_type, handler_type>*> (base);
+ }
+
+ private:
+ handler_type handler_;
+ };
+
+ }
+
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/dispatchers/pull_dispatcher.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/dispatchers/pull_dispatcher.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,40 @@
+//
+// pull_dispatcher.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+
+#ifndef PULL_DISPATCHER_HPP
+#define PULL_DISPATCHER_HPP
+
+#include <boost/channel/queues/unbounded_queue.hpp>
+#include <boost/channel/dispatchers/pull_dispatcher_base.hpp>
+#include <boost/channel/dispatchers/arbiters_async.hpp>
+#include <boost/channel/dispatchers/arbiters_sync.hpp>
+
+namespace boost {
+ namespace channel {
+
+ template<typename name_space, typename platform,
+ template<class , class , class > class queue_type = unbounded_que>
+ struct pull_dispatcher {
+ typedef detail::pull_sender_base<name_space, platform, queue_type> sender;
+ typedef detail::pull_recver_base<name_space, platform, queue_type> recver;
+ typedef detail::choice_arbiter_async<name_space, platform, queue_type>
+ choice_async;
+ typedef detail::join_arbiter_async<name_space, platform, queue_type>
+ join_async;
+ typedef detail::choice_arbiter_sync<name_space, platform, queue_type>
+ choice_sync;
+ typedef detail::join_arbiter_sync<name_space, platform, queue_type>
+ join_sync;
+ };
+
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/dispatchers/pull_dispatcher_base.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/dispatchers/pull_dispatcher_base.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,245 @@
+//
+// pull_dispatcher_base.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+
+#ifndef PULL_DISPATCHER_BASE_HPP
+#define PULL_DISPATCHER_BASE_HPP
+
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+#include <boost/channel/platforms/synch_policy.hpp>
+#include <boost/channel/message.hpp>
+#include <boost/channel/name.hpp>
+#include <boost/channel/named_in_out.hpp>
+#include <boost/channel/dispatchers/dispatcher_base.hpp>
+
+namespace boost {
+ namespace channel {
+ namespace detail {
+
+ template<class , class , template<class , class , class > class> class pull_recver_base;
+
+ //base pull_sender class, shared by most pull dispatchers
+ template<typename name_space, typename platform,
+ template<class , class , class > class msg_queue_type>
+ struct pull_sender_base: public msg_queue_type<boost::shared_ptr<message<
+ typename name_space::id_type> >, typename name_space::synch_policy,
+ platform> {
+ typedef typename name_space::id_type id_type;
+ typedef typename name_space::synch_policy synch_policy;
+ typedef typename name_space::executor executor;
+ typedef name<id_type,executor,synch_policy> name_type;
+ typedef message<id_type> msg_type;
+ typedef msg_queue_type<boost::shared_ptr<msg_type>,
+ synch_policy,
+ platform> que_type;
+ typedef typename name_type::binding_set_type binding_set_type;
+ typedef pull_recver_base<name_space, platform,msg_queue_type> recver_type;
+ typedef named_in<name_space, recver_type> named_in_type;
+
+ name_type * name_;
+ executor *exec_;
+ typename synch_policy::mutex claim_lock_;
+ int num_claimed_;
+
+ pull_sender_base(name_type *n, executor *e) : que_type(), name_(n),
+ exec_(e), num_claimed_(0) {}
+ ~pull_sender_base() {}
+
+ void notify(boost::shared_ptr<msg_type> msg) {
+ //first store msg in que, only buffered msgs destined for local
+ //msgs destined for remote will not be buffered, sent using always_first?
+ if (name_->scope_ != name_base::scope_remote) {
+ this->put(msg);
+ }
+ //notify recevers
+ typename synch_policy::scoped_lock lock(this->name_->bind_lock_);
+ binding_set_type &bindings = this->name_->bindings_;
+ if (!bindings.empty()) {
+ ///let all interested recvers know that a message is available
+ for(typename binding_set_type::iterator iter = bindings.begin();
+ iter != bindings.end(); iter++) {
+ named_in_type *named_in = (named_in_type *)(*iter);
+ recver_type *recver = (recver_type *)named_in;
+
+ if (name_->scope_ == name_base::scope_remote || //for msgs sent to remote, treat it as always_first?
+ named_in->type_ == named_in_type::member_local) {//for pull dispatchers, only send msgs to local receviers
+ recver->notify(msg);
+ if (name_->scope_ == name_base::scope_remote)
+ return;
+ }
+ }
+ }
+ }
+
+ //recvers will call this to retrv/pull data
+ int pull(boost::shared_ptr<msg_type> & msg) {
+ if (!this->empty()) {
+ this->get(msg);
+ return 1;
+ }
+ return 0;
+ }
+
+ //--- for 2 phase msg consumption protocol ---
+
+ //to support 2-phase protocol at recver side
+ bool claim_one(void) {
+ typename synch_policy::scoped_lock lock(this->claim_lock_);
+ if ((int)this->size() > num_claimed_) {
+ num_claimed_++;
+ return true;
+ }
+ return false;
+ }
+
+ void unclaim_one(void) {
+ typename synch_policy::scoped_lock lock(this->claim_lock_);
+ num_claimed_--;
+ if (num_claimed_ < 0) num_claimed_ = 0;
+ }
+ //--- api interface ---
+ //after sending, channel becomes owner
+ template <typename user_msg_type>
+ void send(user_msg_type *msg) {
+ boost::shared_ptr<void> m0(msg);
+ boost::shared_ptr<msg_type> m(new msg_type(name_->id_, m0));
+ notify (m);
+ }
+
+ //after sending: 1> channel becomes owner, if deleter does real deletion
+ // 2> sender still owns msg, if deleter does nothing
+ template <typename user_msg_type, typename deleter>
+ void send(user_msg_type *msg, deleter deler) {
+ boost::shared_ptr<void> m0(msg, deler);
+ boost::shared_ptr<msg_type> m(new msg_type(name_->id_, m0));
+ notify (m);
+ }
+
+ //user_msg is already smarter pointer, channel becomes owner
+ template <typename user_msg_type>
+ void send(boost::shared_ptr<user_msg_type> msg) {
+ boost::shared_ptr<void> m0(msg);
+ boost::shared_ptr<msg_type> m(new msg_type(name_->id_, m0));
+ notify (m);
+ }
+
+ //for channel internal use on wildcard named_out
+ template <typename user_msg_type>
+ void send(id_type id, boost::shared_ptr<user_msg_type> msg) {
+ boost::shared_ptr<void> m0(msg);
+ boost::shared_ptr<msg_type> m(new msg_type(id, m0));
+ notify (m);
+ }
+
+ };
+
+ //pull_recver_base class, base for join/choice pattern
+ template <typename name_space, typename platform, template <class,class,class> class msg_que_type>
+ class pull_recver_base {
+ public:
+ typedef typename name_space::id_type id_type;
+ typedef typename name_space::synch_policy synch_policy;
+ typedef typename name_space::executor executor;
+ typedef name<id_type,executor,synch_policy> name_type;
+ typedef message<id_type> msg_type;
+ typedef typename name_type::binding_set_type binding_set_type;
+ typedef pull_sender_base<name_space, platform, msg_que_type> sender_type;
+ typedef named_out<name_space, sender_type> named_out_type;
+
+ name_type * name_;
+ //msg_handler_base2<id_type> * recver_;
+ msg_handler_base<id_type> * recver_;
+ executor *exec_;
+ sender_type *claimed_sender_;
+
+ template<typename recver_type>
+ pull_recver_base(name_type *n, recver_type rc, executor *e) :
+ name_(n), exec_(e), claimed_sender_(NULL)
+ {
+ //recver_ = new msg_handler2<id_type, recver_type>(rc);
+ recver_ = new msg_handler<id_type, recver_type>(rc);
+ }
+
+ ~pull_recver_base() {
+ if (recver_ != NULL)
+ recver_->destroy();
+ if (claimed_sender_ != NULL)
+ claimed_sender_->unclaim_one();
+ }
+
+ void set_exe(executor *e) {exec_ = e;}
+
+ //senders call this to notify about some data coming
+ //put this recver into activation list
+ bool notify(boost::shared_ptr<msg_type> msg) {
+ /*
+ if (exec_ != NULL) //run recv_handler in executor
+ exec_->execute(boost::bind(&msg_handler_base2<id_type>::invoke, recver_,id));
+ else //run recv_handler in place
+ recver_->invoke(id);
+ */
+ if (exec_ != NULL) //run recv_handler in executor
+ exec_->execute(boost::bind(&msg_handler_base<id_type>::invoke, recver_, msg->id_, msg->data_));
+ else //run recv_handler in place
+ recver_->invoke(msg->id_, msg->data_);
+
+ return true; //always return true to force sender to notify others
+ }
+
+ //claim data at sender
+ bool claim(void) {
+ if (claimed_sender_ != NULL) { //should not happen
+ claimed_sender_->unclaim_one();
+ claimed_sender_ = NULL;
+ }
+ //go-thru binding_set to claim
+ typename synch_policy::scoped_lock lock(name_->bind_lock_);
+ binding_set_type &bindings = name_->bindings_;
+ if (!bindings.empty()) {
+ for(typename binding_set_type::iterator iter = bindings.begin();
+ iter != bindings.end() && claimed_sender_ == NULL; iter++) {
+ named_out_type *named_out = (named_out_type *)(*iter);
+ sender_type *sender = (sender_type *)(named_out);
+ if(sender->claim_one()) claimed_sender_ = sender;
+ }
+ }
+ if (claimed_sender_ != NULL) return true;
+ else return false;
+ }
+
+ //
+ void unclaim(void) {
+ if (claimed_sender_ != NULL) {
+ claimed_sender_->unclaim_one();
+ claimed_sender_ = NULL;
+ }
+ }
+
+ //pull data from sender
+ int pull(boost::shared_ptr<msg_type> & msg) {
+ int sz = 0;
+ if (claimed_sender_ != NULL) {
+ sz = claimed_sender_->pull(msg);
+ claimed_sender_->unclaim_one();
+ claimed_sender_ = NULL;
+ }
+ return sz;
+ }
+ };
+
+}
+
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/dispatchers/push_dispatcher_base.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/dispatchers/push_dispatcher_base.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,143 @@
+//
+// pull_dispatcher_base.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+
+//// push dispatchers:
+//// define push-style message passing process:
+//// including:
+//// . provide both sender/recver sides
+
+#ifndef PUSH_DISPATCHER_BASE_HPP
+#define PUSH_DISPATCHER_BASE_HPP
+
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <boost/shared_ptr.hpp>
+#include <boost/channel/platforms/synch_policy.hpp>
+#include <boost/channel/message.hpp>
+#include <boost/channel/name.hpp>
+#include <boost/channel/named_in_out.hpp>
+#include <boost/channel/dispatchers/dispatcher_base.hpp>
+
+namespace boost {
+ namespace channel {
+
+ namespace detail {
+
+ //base sender class, shared by most push dispatchers
+ template<typename name_space, typename platform,
+ template<typename , typename > class sending_algo>
+ struct push_sender_base {
+ typedef typename name_space::id_type id_type;
+ typedef typename name_space::synch_policy synch_policy;
+ typedef typename name_space::executor executor;
+ typedef name<id_type,executor,synch_policy> name_type;
+ typedef message<id_type> msg_type;
+ typedef typename name_type::binding_set_type binding_set_type;
+
+ name_type * name_;
+ executor *exec_;
+ sending_algo<name_space, platform> algo;
+
+ push_sender_base(name_type * n, executor *e) : name_(n), exec_(e) {}
+
+ //assuming msgs contained inside shared_ptr
+ void push(boost::shared_ptr<msg_type> msg) {
+ typename synch_policy::scoped_lock lock(name_->bind_lock_);
+ typename name_type::binding_set_type &bindings = name_->bindings_;
+ algo(bindings, msg);
+ }
+
+ //after sending, channel becomes owner of msgs
+ template <typename user_msg_type>
+ void send(user_msg_type *msg) {
+ boost::shared_ptr<void> m0(msg);
+ boost::shared_ptr<msg_type> m(new msg_type(name_->id_, m0));
+ push (m);
+ }
+
+ //after sending: 1> channel becomes owner, if deleter does real deletion
+ // 2> sender still owns msg, if deleter does nothing
+ template <typename user_msg_type, typename deleter>
+ void send(user_msg_type *msg, deleter deler) {
+ boost::shared_ptr<void> m0(msg, deler);
+ boost::shared_ptr<msg_type> m(new msg_type(name_->id_, m0));
+ push (m);
+ }
+
+ //user_msg is already smarter pointer, channel becomes owner
+ template <typename user_msg_type>
+ void send(boost::shared_ptr<user_msg_type> msg) {
+ boost::shared_ptr<void> m0(msg);
+ boost::shared_ptr<msg_type> m(new msg_type(name_->id_, m0));
+ push (m);
+ }
+
+ //for channel internal use on wildcard named_out
+ template <typename user_msg_type>
+ void send(id_type id, boost::shared_ptr<user_msg_type> msg) {
+ boost::shared_ptr<void> m0(msg);
+ boost::shared_ptr<msg_type> m(new msg_type(id, m0));
+ push (m);
+ }
+
+ };
+
+ //base recver class, shared by most push dispatchers
+ template <typename name_space, typename platform>
+ struct push_recver_base {
+ typedef typename name_space::id_type id_type;
+ typedef typename name_space::synch_policy synch_policy;
+ typedef typename name_space::executor executor;
+ typedef message<id_type> msg_type;
+ typedef name<id_type,executor,synch_policy> name_type;
+
+ name_type * name_;
+ executor *exec_;
+ msg_handler_base<id_type> *recver_;
+
+ template<typename recver_type>
+ push_recver_base(name_type * n, recver_type rc, executor *e) :
+ name_(n), exec_(e)
+ {
+ recver_ = new msg_handler<id_type, recver_type>(rc);
+ }
+
+ ~push_recver_base() {
+ if (recver_ != NULL)
+ recver_->destroy();
+ }
+
+ void set_exe(executor *e) {exec_ = e;}
+
+ template<typename recver_type>
+ void set_recver(recver_type rc) {
+ if (recver_ != NULL) recver_->destroy();
+ recver_ = new msg_handler<id_type, recver_type>(rc);
+ }
+
+ //senders call this to push into here
+ void push(boost::shared_ptr<msg_type> msg)
+ {
+ if (exec_ != NULL) //run recv_handler in executor
+ exec_->execute(boost::bind(&msg_handler_base<id_type>::invoke,
+ recver_,msg->id_, msg->data_));
+ else //run recv_handler in place
+ recver_->invoke(msg->id_, msg->data_);
+ }
+
+ };
+
+ }
+
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/dispatchers/round_robin_dispatcher.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/dispatchers/round_robin_dispatcher.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,77 @@
+//
+// round_robin_dispatcher.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+
+//// pull dispatchers:
+//// define the whole message passing process:
+//// including:
+//// . sending, buffering, recving
+//// . provide both sender/recver sides
+
+#ifndef ROUND_ROBIN_DISPATCHER_HPP
+#define ROUND_ROBIN_DISPATCHER_HPP
+
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <boost/shared_ptr.hpp>
+#include <boost/channel/platforms/synch_policy.hpp>
+#include <boost/channel/message.hpp>
+#include <boost/channel/name.hpp>
+#include <boost/channel/named_in_out.hpp>
+#include <boost/channel/dispatchers/dispatcher_base.hpp>
+#include <boost/channel/dispatchers/push_dispatcher_base.hpp>
+
+namespace boost {
+ namespace channel {
+
+ namespace detail {
+
+ //we need random-access iterator for roundrobin?
+ //here a temp fix: convert set<name*> to vector<name*>
+ //for a name_space targeted for round_robin dispatching app,
+ //we should change name_space container type to vector instead of set
+ //or make name_space container type configurable?
+ template<typename name_space, typename platform>
+ class round_robin_algo {
+ public:
+ typedef typename name_space::id_type id_type;
+ typedef message<id_type> msg_type;
+ typedef push_recver_base<name_space,platform> recver_type;
+ typedef named_in<name_space, recver_type> named_in_type;
+
+ round_robin_algo(): last_(-1) {}
+ template<typename bindings_type>
+ void operator() (bindings_type &bindings,
+ boost::shared_ptr<msg_type> msg) {
+ if (!bindings.empty()) {
+ std::vector<typename bindings_type::value_type> v(bindings.begin(), bindings.end());
+ int sz = v.size();
+ last_ = (last_+1) % sz;
+ named_in_type *named_in = (named_in_type *)(v[last_]);
+ recver_type *recver = (recver_type *)named_in;
+ recver->push(msg);
+ }
+ }
+ private:
+ int last_;
+ };
+
+ }
+
+ template <typename name_space, typename platform>
+ struct round_robin_dispatcher {
+ typedef detail::push_sender_base<name_space,platform,detail::round_robin_algo> sender;
+ typedef detail::push_recver_base<name_space,platform> recver;
+ };
+
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/executors/asio_executor.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/executors/asio_executor.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,36 @@
+//
+// asio_executor.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_EXECUTOR_HPP
+#define ASIO_EXECUTOR_HPP
+
+#include <boost/asio.hpp>
+
+namespace boost {
+ namespace channel {
+
+ //integration with Boost.Asio
+ //submit async tasks to asio's completion_event queue to be executed by main thread
+ class asio_executor {
+ public:
+ boost::asio::io_service& io_service_;
+ asio_executor(boost::asio::io_service& io_service) :
+ io_service_(io_service) {
+ }
+ template<typename task_type>
+ void execute(task_type task) {
+ io_service_.post(task);
+ }
+ };
+
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/executors/delayed_executor.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/executors/delayed_executor.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,71 @@
+//
+// delayed_executor.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef DELAYED_EXECUTOR_HPP
+#define DELAYED_EXECUTOR_HPP
+
+#include <deque>
+#include <algorithm>
+#include <boost/bind.hpp>
+#include <boost/channel/executors/executor_base.hpp>
+
+namespace boost {
+ namespace channel {
+
+ //in single-thread async app: operations can be delayed:
+ //executed later by the same (single) thread, the original calling context is gone
+ template<typename synch_policy>
+ class delayed_executor {
+ public:
+ std::deque<async_task_base *> tasks_;
+ typename synch_policy::mutex mutex_;
+
+ delayed_executor() {
+ }
+ ~delayed_executor() {
+ typename synch_policy::scoped_lock lock(mutex_);
+ typename std::deque<async_task_base *>::iterator iter;
+ for (iter = tasks_.begin(); iter != tasks_.end(); iter++)
+ (*iter)->destroy();
+ }
+ template<typename task_type>
+ async_task_base * execute(task_type task) {
+ async_task_base *t = new async_task<task_type> (task);
+ typename synch_policy::scoped_lock lock(mutex_);
+ tasks_.push_back(t);
+ return t;
+ }
+ bool cancel(async_task_base *task) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ typename std::deque<async_task_base *>::iterator iter;
+ iter = std::find(tasks_.begin(), tasks_.end(), task);
+ if (iter != tasks_.end()) {
+ (*iter)->destroy();
+ tasks_.erase(iter);
+ return true;
+ }
+ return false;
+ }
+ //complete scheduled tasks
+ void run(void) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ typename std::deque<async_task_base *>::iterator iter;
+ for (iter = tasks_.begin(); iter != tasks_.end(); iter++) {
+ (*iter)->execute();
+ (*iter)->destroy();
+ }
+ tasks_.clear();
+ }
+ };
+
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/executors/executor_base.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/executors/executor_base.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,99 @@
+//
+// executor_base.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef EXECUTOR_BASE_HPP
+#define EXECUTOR_BASE_HPP
+
+namespace boost {
+ namespace channel {
+
+ //async tasks: to be later executed in executor:
+ //1. although in same thread, not in orginal calling context
+ //2. in diff thread
+ class async_task_base {
+ public:
+ enum state {
+ waiting, running, completed
+ };
+
+ // Perform the task.
+ void execute() {
+ st_ = running;
+ exec_func_(this);
+ st_ = completed;
+ }
+
+ // Destroy the task.
+ void destroy() {
+ destroy_func_(this);
+ }
+
+ protected:
+ typedef void (*exec_func_type)(async_task_base*);
+ typedef void (*destroy_func_type)(async_task_base*);
+
+ // Construct an task
+ async_task_base(exec_func_type exec_func, destroy_func_type destroy_func) :
+ exec_func_(exec_func), destroy_func_(destroy_func), st_(waiting) {
+ }
+
+ // Prevent deletion through this type.
+ ~async_task_base() {
+ }
+
+ private:
+ exec_func_type exec_func_;
+ destroy_func_type destroy_func_;
+ state st_;
+ };
+
+ //
+ template<typename task_type>
+ class async_task: public async_task_base {
+ public:
+ // Constructor.
+ async_task(task_type task) :
+ async_task_base(&async_task<task_type>::exec_task, &async_task<
+ task_type>::destroy_task), task_(task) {
+ }
+
+ // Invoke the task.
+ static void exec_task(async_task_base* base) {
+ static_cast<async_task<task_type>*> (base)->task_();
+ }
+
+ // Delete the task.
+ static void destroy_task(async_task_base* base) {
+ delete static_cast<async_task<task_type>*> (base);
+ }
+
+ private:
+ task_type task_;
+ };
+
+ //define an abstract class, so that it cannt be
+ //instantiated and execution must be in-line;
+ //or it can provide a base class for dynamic
+ //polymorphism of executors;
+ class abstract_executor {
+ public:
+ template<typename task_type>
+ async_task_base * execute(task_type task) {
+ return NULL;
+ }
+ virtual bool cancel(async_task_base *task) = 0;
+ virtual ~abstract_executor() {
+ }
+ };
+
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/executors/in_place_executor.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/executors/in_place_executor.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,31 @@
+//
+// in_place_executor.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef IN_PLACE_EXECUTOR_HPP
+#define IN_PLACE_EXECUTOR_HPP
+
+#include <boost/channel/executors/executor_base.hpp>
+
+namespace boost {
+ namespace channel {
+
+ //the simplest: execute async_task in place: ie. in current thread & calling context
+ class in_place_executor {
+ public:
+ template<typename task_type>
+ void execute(task_type task) {
+ task();
+ }
+ };
+
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/executors/thread_pool_executor.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/executors/thread_pool_executor.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,144 @@
+//
+// thread_pool_executor.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef THREAD_POOL_EXECUTOR_HPP
+#define THREAD_POOL_EXECUTOR_HPP
+
+#include <deque>
+#include <algorithm>
+#include <boost/thread.hpp>
+#include <boost/bind.hpp>
+#include <boost/channel/executors/executor_base.hpp>
+
+namespace boost {
+ namespace channel {
+
+ //a dedicated pool of threads to exec async tasks
+ //a simple thread pool executor with unlimited buffering
+ template<typename synch_policy>
+ class thread_pool_executor {
+ public:
+ enum state {
+ running, stop
+ };
+
+ thread_pool_executor(int num_thr) :
+ num_thr_(num_thr) {
+ st_ = running;
+ for (int i = 0; i < num_thr; i++)
+ threads_.create_thread(
+ boost::bind(&thread_pool_executor::run, this));
+ }
+
+ ~thread_pool_executor() {
+ typename synch_policy::scoped_lock lock(mutex_);
+ if (st_ == running) {
+ lock.unlock();
+ shut_down_wait();
+ }
+ }
+
+ ///executor life cycle
+ state get_state(void) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ return st_;
+ }
+
+ //gracefully shut down
+ void shut_down_wait() {
+ typename synch_policy::scoped_lock lock(mutex_);
+ if (st_ == running) {
+ st_ = stop;
+ lock.unlock();
+ cond_.notify_all();
+ //waiting for the threads to exit
+ threads_.join_all();
+ }
+ }
+
+ void wait() {
+ typename synch_policy::scoped_lock lock(mutex_);
+ while (st_ == running && !tasks_.empty()) {
+ cond_wait_.wait(lock);
+ }
+ }
+
+ //abruptively shut down
+ void shut_down_now() {
+ typename synch_policy::scoped_lock lock(mutex_);
+ st_ = stop;
+ //kill threads
+ }
+
+ ///submit a task
+ template<typename task_type>
+ async_task_base * execute(task_type task) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ if (st_ == running) {
+ async_task_base * t = new async_task<task_type> (task);
+ tasks_.push_back(t);
+ cond_.notify_one();
+ return t;
+ }
+ return NULL;
+ }
+
+ ///scancel a task
+ bool cancel(async_task_base *task) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ if (st_ == running) {
+ typename std::deque<async_task_base *>::iterator iter;
+ iter = std::find(tasks_.begin(), tasks_.end(), task);
+ if (iter != tasks_.end()) {
+ (*iter)->destroy();
+ tasks_.erase(iter);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private:
+ async_task_base * next_task(void) {
+ async_task_base * t = NULL;
+ typename synch_policy::scoped_lock lock(mutex_);
+ while (tasks_.empty() && st_ != stop) {
+ cond_wait_.notify_one();
+ cond_.wait(lock);
+ }
+ if (st_ == stop)
+ return NULL;
+ t = tasks_.front();
+ tasks_.pop_front();
+ return t;
+ }
+
+ void run(void) {
+ while (st_ != stop) {
+ async_task_base * t = next_task();
+ if (st_ != stop && t != NULL)
+ t->execute();
+ }
+ }
+
+ private:
+ std::deque<async_task_base *> tasks_;
+ boost::thread_group threads_;
+ typename synch_policy::mutex mutex_;
+ typename synch_policy::condition cond_;
+ typename synch_policy::condition cond_wait_;
+ state st_;
+ int num_thr_;
+ };
+
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/executors/threadpool_executor.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/executors/threadpool_executor.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,72 @@
+//
+// threadpool_executor.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef THREADPOOL_EXECUTOR_HPP
+#define THREADPOOL_EXECUTOR_HPP
+
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/threadpool/threadpool.hpp>
+
+namespace boost {
+ namespace channel {
+
+ //a wrapper over Philipp Henkel's threadpool library
+ template<typename pool_type = boost::threadpool::pool<boost::function0<void>,
+ boost::threadpool::fifo_scheduler<boost::function0<void> > > >
+ class threadpool_executor {
+ public:
+ threadpool_executor(int num_thr) :
+ num_thr_(num_thr) {
+ pool_ = pool_type::create_pool(num_thr_);
+ }
+
+ ~threadpool_executor() {
+ shut_down_wait();
+ }
+
+ //gracefully shut down
+ void shut_down_wait() {
+ pool_->clear();
+ pool_->resize(0);
+ pool_->wait();
+ }
+
+ //gracefully shut down
+ void wait() {
+ pool_->wait();
+ }
+
+ //abruptively shut down
+ void shut_down_now() {
+ //how ?
+ }
+
+ ///submit a task
+ template<typename task_type>
+ bool execute(task_type task) {
+ return pool_->schedule(task);
+ }
+
+ ///cancel a task.
+ ///will implement it on top of "future" when it becomes available soon
+ bool cancel(async_task_base *task) {
+ return true;
+ }
+
+ private:
+ int num_thr_;
+ boost::shared_ptr<pool_type> pool_;
+ };
+
+}
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/interface.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/interface.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,514 @@
+//
+// interface.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+
+#ifndef INTERFACE_HPP
+#define INTERFACE_HPP
+
+#include <string>
+#include <vector>
+#include <boost/shared_ptr.hpp>
+#include <boost/bind.hpp>
+#include <boost/channel/binder.hpp>
+#include <boost/channel/named_in_out.hpp>
+#include <boost/channel/dispatchers/broadcast_dispatcher.hpp>
+#include <boost/channel/message.hpp>
+#include <boost/channel/peer.hpp>
+#include <boost/channel/name.hpp>
+
+namespace boost {
+ namespace channel {
+
+ //interface to other channel_ts or streams
+ template<typename channel_t>
+ class interface: public peer_type<typename channel_t::id_type> {
+ public:
+ enum state_type {
+ intf_init = 0, intf_active
+ };
+
+ typedef typename channel_t::platform platform;
+ typedef typename channel_t::name_space_type name_space;
+ typedef typename channel_t::dispatch_policy dispatcher;
+ typedef typename name_space::synch_policy synch_policy;
+ typedef typename channel_t::id_type id_type;
+ typedef typename channel_t::id_trait id_trait;
+ typedef typename name_space::name name;
+ typedef typename boost::channel::named_out<name_space, typename broadcast_dispatcher<name_space,platform>::sender> ns_named_out;
+ typedef typename channel_t::out named_out;
+ typedef typename channel_t::in named_in;
+ typedef boost::channel::peer_type<id_type> peer_type;
+ typedef message<id_type> message_type;
+ // typedef connection<id_type> connection_type;
+ typedef typename channel_t::connection connection_type;
+ typedef typename channel_t::executor executor;
+ typedef boost::channel::named_out_bundle<name_space, typename broadcast_dispatcher<name_space,platform>::sender> ns_named_out_bundle;
+ typedef boost::channel::named_in_bundle<name_space, typename broadcast_dispatcher<name_space,platform>::recver> ns_named_in_bundle;
+ typedef boost::channel::named_out_bundle<name_space, typename channel_t::dispatch_policy::sender> named_out_bundle;
+ typedef boost::channel::named_in_bundle<name_space, typename channel_t::dispatch_policy::recver> named_in_bundle;
+ typedef boost::channel::binder_type<id_type> binder_type;
+ typedef boost::channel::translator_type<id_type> translator_type;
+ typedef boost::channel::filter_type<id_type> filter_type;
+ typedef boost::channel::pubsub_info_msg_t<id_type> pubsub_info_msg_t;
+
+ typedef interface<channel_t> interface_type;
+
+ private:
+ ///
+ channel_t &ch_;
+ state_type state_;
+
+ //ids bound at local channel_t
+ //for namespace change, using broadcast dispatching
+ ns_named_in_bundle ns_named_ins_;
+ ns_named_out_bundle ns_named_outs_;
+ //for application messages, using channel_t specific dispatching
+ named_in_bundle named_ins_;
+ named_out_bundle named_outs_;
+
+ ///outgoing-msg buffering when connection to remote peer is not ready yet
+ std::vector<boost::shared_ptr<message_type> > pending_msgs_;
+ typename synch_policy::mutex lock_;///lock to maintain interface internal state
+
+ ///filter & translators: policies for remote connections
+ filter_type *filter_;
+ translator_type *translator_;
+
+ public:
+ interface (channel_t &chan, binder_type *binder) :
+ ch_(chan),
+ ns_named_ins_(chan, boost::bind(&interface::recv,this, _1,_2), name_base::member_remote),
+ ns_named_outs_(chan, name_base::member_remote),
+ named_ins_(chan, boost::bind(&interface::recv,this, _1,_2),name_base::member_remote),
+ named_outs_(chan, name_base::member_remote)
+ {
+ state_ = intf_init;
+ ch_.add_intf(this);
+ if (binder == NULL) {
+ filter_ = NULL;
+ translator_ = NULL;
+ } else {
+ filter_ = binder->filter;
+ translator_ = binder->translator;
+ }
+ //subscribe to system msgs from local channel_t on behalf of the remote side
+ //since channel_t_(DIS)CONN_msg and init_SUB/PUB_info_msg
+ //are generated inside interface, no need to subscribe to them in channel_ts
+ ns_named_ins_.bind(channel_t::subscription_info_msg, name_base::scope_local);
+ ns_named_ins_.bind(channel_t::unsubscription_info_msg, name_base::scope_local);
+ ns_named_ins_.bind(channel_t::publication_info_msg, name_base::scope_local);
+ ns_named_ins_.bind(channel_t::unpublication_info_msg, name_base::scope_local);
+ //publish system msgs at local channel_t on behalf of the remote side
+ ns_named_outs_.bind(channel_t::channel_conn_msg, name_base::scope_local);
+ ns_named_outs_.bind(channel_t::channel_disconn_msg, name_base::scope_local);
+ ns_named_outs_.bind(channel_t::init_subscription_info_msg, name_base::scope_local);
+ ns_named_outs_.bind(channel_t::connection_ready_msg, name_base::scope_local);
+ ns_named_outs_.bind(channel_t::subscription_info_msg, name_base::scope_local);
+ ns_named_outs_.bind(channel_t::unsubscription_info_msg, name_base::scope_local);
+ ns_named_outs_.bind(channel_t::publication_info_msg, name_base::scope_local);
+ ns_named_outs_.bind(channel_t::unpublication_info_msg, name_base::scope_local);
+ }
+
+ ~interface ()
+ {
+ //destructors of named_in/out_bundles will unbind and destroy
+ //all named_in_out objects; so we dont need to explicitly unbind/delete
+ //named_ins_,named_outs_,ns_named_ins_,ns_named_outs_
+ ch_.del_intf(this);
+ platform::log("... interface destructor called ...");
+ }
+
+ /*
+ void unbind() {
+ //unbind app ids at remote end
+ platform::log("... interface unbind enter ...");
+ std::vector<id_type> ids;
+ typename std::vector<id_type>::iterator iter;
+ if (named_ins_.get_ids(ids)) {
+ for(iter = ids.begin(); iter != ids.end(); iter++)
+ send2remote_pubsub_msg (name_base::unbind_in_ev, *iter);
+ }
+ ids.clear();
+ if (named_outs_.get_ids(ids)) {
+ for(iter = ids.begin(); iter != ids.end(); iter++)
+ send2remote_pubsub_msg (name_base::unbind_out_ev, *iter);
+ }
+ peer_type::unbind();
+ platform::log("... interface unbind exit ...");
+ }
+ */
+
+ bool sys_msg(id_type id) {
+ if(id == channel_t::channel_conn_msg ||
+ id == channel_t::channel_disconn_msg ||
+ id == channel_t::init_subscription_info_msg ||
+ id == channel_t::connection_ready_msg ||
+ id == channel_t::subscription_info_msg ||
+ id == channel_t::unsubscription_info_msg ||
+ id == channel_t::publication_info_msg ||
+ id == channel_t::unpublication_info_msg)
+ return true;
+ return false;
+ }
+
+ ///called from inside channel_t, forward msgs from inside channel_t to peers
+ void recv(id_type id, boost::shared_ptr<void> msg)
+ {
+ platform::log("interface::recv ["+id_trait::id_to_string(id)+"]");
+ if(state_ != intf_active) {
+ boost::shared_ptr<message_type> m(new message_type(id,msg));
+ add_pending_msg(m);
+ platform::log("... msgs["+id_trait::id_to_string(id)+"] buffered ");
+ } else {
+ bool need_send = false;
+
+ if (sys_msg(id)) {
+ //check pub/unpub, sub/unsub msgs
+ pubsub_info_msg_t *info = (pubsub_info_msg_t *)msg.get();
+ if (id == channel_t::subscription_info_msg) {
+ for(size_t i=0; i<info->msg_types.size() && !need_send; i++) {
+ if (filter_ != NULL && filter_->block_inward(info->msg_types[i]))
+ continue;
+ if (!sys_msg(info->msg_types[i]) && named_outs_.find(info->msg_types[i]) == NULL) {
+ if (translator_ != NULL)
+ translator_->translate_outward(info->msg_types[i]);
+ need_send = true;
+ }
+ }
+ }
+ else if (id == channel_t::unsubscription_info_msg) {
+ for(size_t i=0; i<info->msg_types.size() && !need_send; i++) {
+ named_out *no;
+ if (!sys_msg(info->msg_types[i]) && (no = named_outs_.find(info->msg_types[i])) != NULL) {
+ if (no->num_bindings() == 0) {
+ if (translator_ != NULL)
+ translator_->translate_outward(info->msg_types[i]);
+ need_send = true;
+ }
+ }
+ }
+ }
+ else if (id == channel_t::publication_info_msg) {
+ for(size_t i=0; i<info->msg_types.size() && !need_send; i++) {
+ if (filter_ != NULL && filter_->block_outward(info->msg_types[i]))
+ continue;
+ if (!sys_msg(info->msg_types[i]) && named_ins_.find(info->msg_types[i]) == NULL) {
+ if (translator_ != NULL)
+ translator_->translate_outward(info->msg_types[i]);
+ need_send = true;
+ }
+ }
+ }
+ else if (id == channel_t::unpublication_info_msg) {
+ for(size_t i=0; i<info->msg_types.size() && !need_send; i++) {
+ named_in *ni;
+ if (!sys_msg(info->msg_types[i]) && (ni = named_ins_.find(info->msg_types[i])) != NULL) {
+ if (ni->num_bindings() == 0) {
+ if (translator_ != NULL)
+ translator_->translate_outward(info->msg_types[i]);
+ need_send = true;
+ }
+ }
+ }
+ }
+ } else { //applicaion msgs
+ //translate application msgs if set
+ if (translator_ != NULL) {
+ translator_->translate_outward(id);
+ }
+ need_send = true;
+ }
+
+ if(need_send)
+ peer_send(id, msg);
+ }
+ }
+
+ ///called by peers, forward msgs from outside peer to channel_t
+ void send(id_type id, boost::shared_ptr<void> msg)
+ {
+ platform::log("interface::send_msg: recv MSG ["+id_trait::id_to_string(id)+"]...");
+ pubsub_info_msg_t *subinfo;
+
+ /// --- connection setup hand-shaking ----
+ if (id == channel_t::channel_conn_msg) {
+ //connector or stream should already intercept this msg for its own internal
+ //processing, such as connection management; here we forward it to subscribed
+ //user code
+ switch(this->role_) {
+ case peer_type::active_role:
+ platform::log("active end recv channel_info_msg ...");
+ send2remote_init_subscribe_msg();
+ break;
+ case peer_type::passive_role:
+ platform::log("passive end recv channel_info_msg ...");
+ ///send my chan info
+ send2remote_channel_info_msg();
+ break;
+ default:
+ break;
+ }
+ }
+ else if(id == channel_t::channel_disconn_msg) {
+ //connector or stream should already intercept this msg for its own internal
+ //processing, such as connection management; here we forward it to subscribed
+ //user code
+ }
+ else if (id == channel_t::init_subscription_info_msg) {
+ platform::log("recv init_subscription_info_msg...");
+ subinfo = (pubsub_info_msg_t *)msg.get();
+ std::vector<id_type> pub_msgs;
+ ch_.bound_ids_for_out(name::exported_name, pub_msgs);
+ for(size_t i=0; i<subinfo->msg_types.size(); i++) {
+ if (translator_ != NULL)
+ translator_->translate_inward(subinfo->msg_types[i]);
+ if (filter_ != NULL && filter_->block_outward(subinfo->msg_types[i]))
+ continue;
+ if(std::find_if(pub_msgs.begin(), pub_msgs.end(),
+ boost::bind(&id_trait::match, _1, subinfo->msg_types[i])) !=
+ pub_msgs.end()) {
+ platform::log("remote subsc to ["+id_trait::id_to_string(subinfo->msg_types[i])+"]");
+ named_ins_.bind(subinfo->msg_types[i], name_base::scope_local);
+ send2remote_pubsub_msg (name_base::bind_out_ev, subinfo->msg_types[i]);
+ }
+ }
+ if(this->role_ == peer_type::passive_role) {
+ ///send my subscription info
+ send2remote_init_subscribe_msg();
+ } else if(this->role_ == peer_type::active_role) {
+ send2remote_conn_ready_msg();
+ }
+ } else if (id == channel_t::connection_ready_msg) {
+ platform::log("recv conn_ready...");
+ platform::log((this->role_ == peer_type::active_role)?"i am active":"i am passive");
+ state_ = intf_active;
+ platform::log("conn active now...");
+ resend_pending_msgs();
+ if (this->role_ == peer_type::passive_role) {
+ send2remote_conn_ready_msg();
+ }
+ }
+ /// --- name_space change msgs during normal operations ---
+ ///init_sub_msgs
+ else if (id == channel_t::subscription_info_msg) {
+ platform::log("recv subscription_info_msg ...");
+ subinfo = (pubsub_info_msg_t *)msg.get();
+ std::vector<id_type> global_msgs;
+ ch_.bound_ids_for_out(name::exported_name, global_msgs);
+ for(size_t i=0; i<subinfo->msg_types.size(); i++) {
+ if (translator_ != NULL)
+ translator_->translate_inward(subinfo->msg_types[i]);
+ if (filter_ != NULL && filter_->block_outward(subinfo->msg_types[i]))
+ continue;
+ if (named_ins_.find(subinfo->msg_types[i]) == NULL) {
+ if(std::find_if(global_msgs.begin(), global_msgs.end(),
+ boost::bind(&id_trait::match, _1, subinfo->msg_types[i])) !=
+ global_msgs.end()) {
+ platform::log("remote subsc to ["+id_trait::id_to_string(subinfo->msg_types[i])+"]");
+ if(named_ins_.bind(subinfo->msg_types[i], name_base::scope_local))
+ send2remote_pubsub_msg (name_base::bind_out_ev, subinfo->msg_types[i]);
+ }
+ }
+ }
+ }
+ else if (id == channel_t::unsubscription_info_msg) {
+ platform::log("recv unsubscription_info_msg...");
+ subinfo = (pubsub_info_msg_t *)msg.get();
+ for(size_t i=0; i<subinfo->msg_types.size(); i++) {
+ if (translator_ != NULL)
+ translator_->translate_inward(subinfo->msg_types[i]);
+ if(named_ins_.unbind(subinfo->msg_types[i]))
+ send2remote_pubsub_msg (name_base::unbind_out_ev, subinfo->msg_types[i]);
+ }
+ }
+ else if (id == channel_t::publication_info_msg) {
+ platform::log("recv publication_info_msg...");
+ pubsub_info_msg_t *pubinfo = (pubsub_info_msg_t *)msg.get();
+ std::vector<id_type> mtypes;
+ ch_.bound_ids_for_in(name::exported_name, mtypes);
+ for(size_t i=0; i<pubinfo->msg_types.size(); i++) {
+ if (translator_ != NULL)
+ translator_->translate_inward(pubinfo->msg_types[i]);
+ if (filter_ != NULL && filter_->block_inward(pubinfo->msg_types[i]))
+ continue;
+ if (named_outs_.find (pubinfo->msg_types[i]) == NULL) {
+ //platform::log("remote pub msg, try to match ["+id_trait::id_to_string(pubinfo->msg_types[i])+"]");
+ if(std::find_if(mtypes.begin(), mtypes.end(),
+ boost::bind(&id_trait::match, _1, pubinfo->msg_types[i])) !=
+ mtypes.end()) {
+ platform::log("remote pub msg ["+id_trait::id_to_string(pubinfo->msg_types[i])+"]");
+ ///remote msgs only for local destinations
+ if(named_outs_.bind (pubinfo->msg_types[i], name_base::scope_local))
+ send2remote_pubsub_msg(name_base::bind_in_ev, pubinfo->msg_types[i]);
+ }
+ }
+ }
+ }
+ else if (id == channel_t::unpublication_info_msg) {
+ platform::log("recv unpublication_info_msg...");
+ subinfo = (pubsub_info_msg_t *)msg.get();
+ for(size_t i=0; i<subinfo->msg_types.size(); i++) {
+ if (translator_ != NULL)
+ translator_->translate_inward(subinfo->msg_types[i]);
+ if(named_outs_.unbind(subinfo->msg_types[i]))
+ send2remote_pubsub_msg (name_base::unbind_in_ev, subinfo->msg_types[i]);
+ }
+ }
+ /// --- application msgs ----
+ else {
+ //application msgs go to channel_t
+ //translate it if set
+ if (translator_ != NULL) {
+ translator_->translate_inward(id);
+ }
+ //platform::log("recv an application msg ["+id_trait::id_to_string(id)+"]");
+ }
+
+ ///forward all msgs to local channel_t
+ if(sys_msg(id)) { //forward system msgs
+ ns_named_out *no = ns_named_outs_.find(id);
+ if (no != NULL)
+ no->send (msg);
+ }
+ else { //forward application msgs
+ typename channel_t::out *no = named_outs_.find(id); //find exact match
+ if (no != NULL) { //exact match found
+ no->send (msg);
+ } else {
+ //platform::log("interface::send try to match a local wildcard with name: "+id_trait::id_to_string(id));
+ no = named_outs_.find_match(id);
+ if (no != NULL) { //assoc/fuzzy match found
+ if (id_trait::wildcard_name(no->id_)) {
+ platform::log("interface::send match a local wildcard name: "+id_trait::id_to_string(no->id_));
+ no->send (id,msg);
+ } else
+ no->send (msg);
+ }
+ }
+ }
+ }
+
+ ///send owner channel info to remote
+ void send2remote_channel_info_msg(void)
+ {
+ platform::log("send_chan_info_to_remote...");
+ std::pair<typename peer_type::type, std::string> info = this->peer_get_info();
+ boost::shared_ptr<channel_info_msg_t> msg(new channel_info_msg_t());
+ msg->intf = this;
+ msg->is_local = true;
+ if (info.first == peer_type::remote_peer)
+ {
+ msg->is_local = false;
+ msg->host_addr = info.second;
+ }
+ peer_send(channel_t::channel_conn_msg,msg);
+ }
+
+ private:
+
+ /**
+ * methods handling msg buffering before remote connection is ready
+ */
+ void add_pending_msg(boost::shared_ptr<message_type> m) {
+ typename synch_policy::scoped_lock lock(lock_);
+ pending_msgs_.push_back(m);
+ }
+ void resend_pending_msgs(void)
+ {
+ if(this->peer_ != NULL) {
+ typename synch_policy::scoped_lock lock(lock_);
+ for(size_t i=0; i<pending_msgs_.size();i++) {
+ boost::shared_ptr<message_type> m = pending_msgs_[i];
+ peer_send(m->id_,m->data_);
+ platform::log("...resend 1 msg");
+ }
+ pending_msgs_.clear();
+ }
+ }
+
+ /* ----- */
+
+ ///send channel_t conn ready msg to remote
+ void send2remote_conn_ready_msg(void)
+ {
+ platform::log("send_conn_ready_to_remote...");
+ std::pair<typename peer_type::type, std::string> info = this->peer_get_info();
+ boost::shared_ptr<channel_info_msg_t> msg(new channel_info_msg_t());
+ msg->intf = this;
+ msg->is_local = true;
+ if (info.first == peer_type::remote_peer)
+ {
+ msg->is_local = false;
+ msg->host_addr = info.second;
+ }
+ peer_send(channel_t::connection_ready_msg,msg);
+ }
+
+ ///when 2 channel_ts just connected, send all current sub info
+ ///to remote
+ void send2remote_init_subscribe_msg(void)
+ {
+ ///send subscription msg
+ boost::shared_ptr<pubsub_info_msg_t> sub(new pubsub_info_msg_t());
+ std::vector<id_type> mtypes;
+ ch_.bound_ids_for_in(name::exported_name, mtypes);
+ for(size_t i=0; i<mtypes.size(); i++) {
+ if (sys_msg(mtypes[i]) || (filter_ != NULL && filter_->block_inward(mtypes[i])))
+ continue;
+ if (translator_ != NULL)
+ translator_->translate_outward(mtypes[i]);
+ sub->msg_types.push_back(mtypes[i]);
+ }
+ platform::log("send init_subscription info...");
+ peer_send(channel_t::init_subscription_info_msg, sub);
+ }
+
+ ///forward local/owner channel_t memebers' pub/sub operations to remote
+ void send2remote_pubsub_msg(typename name_base::binding_event op, id_type t)
+ {
+ boost::shared_ptr<pubsub_info_msg_t> sub(new pubsub_info_msg_t());
+ id_type mt;
+ switch(op) {
+ case name_base::bind_out_ev:
+ if (filter_ != NULL && filter_->block_outward(t)) {
+ return;
+ }
+ mt = channel_t::publication_info_msg;
+ platform::log("interface::send2remote_pubsub_msg publish ");
+ break;
+ case name_base::unbind_out_ev:
+ mt = channel_t::unpublication_info_msg;
+ platform::log("interface::send2remote_pubsub_msg unpublish ");
+ break;
+ case name_base::bind_in_ev:
+ if (filter_ != NULL && filter_->block_inward(t)) {
+ return;
+ }
+ mt = channel_t::subscription_info_msg;
+ platform::log("interface::send2remote_pubsub_msg subscribe ");
+ break;
+ case name_base::unbind_in_ev:
+ mt = channel_t::unsubscription_info_msg;
+ platform::log("interface::send2remote_pubsub_msg unsubscribe ");
+ break;
+ default:
+ platform::log("interface::send2remote_pubsub_msg invalid id_type ");
+ return;
+ }
+ if (translator_ != NULL)
+ translator_->translate_outward(t);
+ sub->msg_types.push_back(t);
+ peer_send(mt, sub);
+ }
+ };
+
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/marshaler.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/marshaler.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,254 @@
+//
+// marshaler.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef MARSHALER_HPP
+#define MARSHALER_HPP
+
+#include <vector>
+#include <map>
+#include <boost/shared_ptr.hpp>
+#include <boost/channel/message.hpp>
+#include <boost/archive/text_iarchive.hpp>
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/binary_iarchive.hpp>
+#include <boost/archive/binary_oarchive.hpp>
+#include <boost/archive/xml_iarchive.hpp>
+#include <boost/archive/xml_oarchive.hpp>
+#include <boost/serialization/string.hpp>
+#include <boost/serialization/binary_object.hpp>
+#include <boost/serialization/vector.hpp>
+
+/**
+ * marshaling & demarshaling : msg converting : typed info <-> untyped stream
+ * here we use Boost.Serialization text_archive for conversion.
+ * other choices: binary archive or xml archives
+ *
+ * 2 steps to enable marshaling for a message type:
+ * 1> define a free serialize function for it (non-intrusive)
+ * 2> register the type with marshaler_registry:
+ * marshaler_registry.register<msg_type>(id);
+ *
+ * for msg types using PODS: struct without virtual methods, dont
+ * need define any serialization methods or register marshalers, the
+ * default marshaler<void_type> does byte-copy and will be enough
+ */
+
+namespace boost {
+ namespace channel {
+
+ ///interface of all message marshalers
+ class msg_marshaler {
+ public:
+ virtual void marshal(boost::shared_ptr<void> &msg, std::string &buf) = 0;
+ virtual void demarshal(std::string &buf, boost::shared_ptr<void> &msg) = 0;
+ virtual ~msg_marshaler() {
+ }
+ };
+
+ ///interface of all id marshalers
+ template<typename id_type>
+ class id_marshaler {
+ public:
+ virtual void marshal(const id_type &id, std::string &buf) = 0;
+ virtual void demarshal(std::string &buf, id_type &id) = 0;
+ virtual ~id_marshaler() {
+ }
+ };
+
+ ///grouping of archives
+ enum marshaling_archive_type {
+ text_archive, binary_archive, xml_archive
+ };
+
+ template<int> class marshaling_archives;
+
+ template<>
+ struct marshaling_archives<text_archive> {
+ typedef boost::archive::text_oarchive oarchive;
+ typedef boost::archive::text_iarchive iarchive;
+ };
+
+ template<>
+ struct marshaling_archives<binary_archive> {
+ typedef boost::archive::binary_oarchive oarchive;
+ typedef boost::archive::binary_iarchive iarchive;
+ };
+
+ template<>
+ struct marshaling_archives<xml_archive> {
+ typedef boost::archive::xml_oarchive oarchive;
+ typedef boost::archive::xml_iarchive iarchive;
+ };
+
+ /**
+ * --------- id marshaler types --------------
+ */
+ template<typename id_type, int archive_type>
+ class id_marshaler_impl: public id_marshaler<id_type> {
+ void marshal(const id_type &id, std::string &buf) {
+ std::ostringstream archive_stream;
+ typename marshaling_archives<archive_type>::oarchive archive(archive_stream);
+ archive << id;
+ buf = archive_stream.str();
+ }
+ void demarshal(std::string &buf, id_type &id) {
+ std::istringstream archive_stream(buf);
+ typename marshaling_archives<archive_type>::iarchive archive(archive_stream);
+ archive >> id;
+ }
+ };
+
+ /**
+ * --------- message marshaler types --------------
+ */
+ //struct void_type {};
+
+ ///---- text_marshaler: marshal typed message using text_archive ----
+ template<typename msg_type, int archive_type>
+ class msg_marshaler_impl: public msg_marshaler {
+ public:
+ void marshal(boost::shared_ptr<void> &msg, std::string &buf) {
+ /// must be const pointer, otherwise marshaling will fail
+ msg_type * const data = (msg_type *) msg.get();
+ std::ostringstream archive_stream;
+ typename marshaling_archives<archive_type>::oarchive archive(archive_stream);
+ archive << data;
+ buf = archive_stream.str();
+ }
+ void demarshal(std::string &buf, boost::shared_ptr<void> &msg) {
+ msg_type * data; ///to support marshaling, msg_type need support default constructor
+ std::istringstream archive_stream(buf);
+ typename marshaling_archives<archive_type>::iarchive archive(archive_stream);
+ archive >> data;
+ msg.reset(data);
+ }
+ };
+
+ /*
+ /// binary copy text_marshaler, used as default
+ template <int archive_type>
+ struct msg_marshaler_impl<void_type, archive_type> : public msg_marshaler {
+ void marshal(boost::shared_ptr<void> &msg, int sz, std::string &buf)
+ {
+ std::ostringstream archive_stream;
+ typename marshaling_archives<archive_type>::oarchive archive(archive_stream);
+ archive << boost::serialization::make_binary_object(msg.get(), sz);
+ buf = archive_stream.str();
+ }
+ void demarshal(std::string &buf, boost::shared_ptr<void> &msg, int &sz)
+ {
+ sz = buf.size();
+ char *data = new char[sz]; //for binary obj, we have to alloc space
+ std::istringstream archive_stream(buf);
+ typename marshaling_archives<archive_type>::iarchive archive(archive_stream);
+ archive >> boost::serialization::make_binary_object(data, sz);
+ msg.reset(data);
+ }
+ };
+ */
+
+ /**
+ * -------------- xml_marshaler -----------
+ */
+
+ /**
+ * marshaler registration map:
+ * for simple application, all remote connections can share a marshaler_registry
+ * for applications involving diff marshaling strategies for diff remote
+ * connections, several marshaler_registries can be used; each stream object
+ * will use its own marshaler_registry
+ */
+
+ template<typename id_type, typename id_trait, typename synch_policy, int archive_type = text_archive>
+ class marshaler_registry {
+ private:
+ //marshaler registration
+ std::map<id_type, boost::shared_ptr<msg_marshaler> > mar_tbl_;
+ //msg_marshaler_impl<void_type, archive_type> bin_mar_;
+ id_marshaler_impl<id_type, archive_type> id_mar_;
+ msg_marshaler *default_mar_;
+ typename synch_policy::mutex mar_tbl_lock_;
+ public:
+ typedef boost::channel::id_marshaler<id_type> id_marshaler;
+ marshaler_registry() :
+ default_mar_(NULL) {
+ //register marshaler for system internal msgs
+ std::vector<id_type> ids;
+ ids.push_back(id_trait::channel_conn_msg);
+ ids.push_back(id_trait::channel_disconn_msg);
+ ids.push_back(id_trait::connection_ready_msg);
+ register_msg_marshaler<channel_info_msg_t> (ids);
+
+ ids.clear();
+ ids.push_back(id_trait::init_subscription_info_msg);
+ ids.push_back(id_trait::subscription_info_msg);
+ ids.push_back(id_trait::unsubscription_info_msg);
+ ids.push_back(id_trait::publication_info_msg);
+ ids.push_back(id_trait::unpublication_info_msg);
+ register_msg_marshaler<pubsub_info_msg_t<id_type> > (ids);
+ }
+
+ ~marshaler_registry() {
+ if (default_mar_ != NULL)
+ delete default_mar_;
+ }
+
+ template<typename msg_type>
+ void register_default_msg_marshaler(void) {
+ typename synch_policy::scoped_lock lock(mar_tbl_lock_);
+ if (default_mar_ != NULL)
+ delete default_mar_;
+ default_mar_ = new msg_marshaler_impl<msg_type, archive_type> ();
+ }
+
+ template<typename msg_type>
+ void register_msg_marshaler(id_type id) {
+ typename synch_policy::scoped_lock lock(mar_tbl_lock_);
+ boost::shared_ptr<msg_marshaler> mar(new msg_marshaler_impl<msg_type, archive_type> ());
+ mar_tbl_[id] = mar;
+ }
+
+ template<typename msg_type>
+ void register_msg_marshaler(std::vector<id_type> &ids) {
+ typename synch_policy::scoped_lock lock(mar_tbl_lock_);
+ boost::shared_ptr<msg_marshaler> mar(new msg_marshaler_impl<msg_type, archive_type> ());
+ for (typename std::vector<id_type>::iterator iter = ids.begin(); iter != ids.end(); iter++) {
+ mar_tbl_[*iter] = mar;
+ }
+ }
+
+ msg_marshaler * get_msg_marshaler(id_type id) {
+ typename synch_policy::scoped_lock lock(mar_tbl_lock_);
+ if (mar_tbl_.find(id) != mar_tbl_.end())
+ return mar_tbl_[id].get();
+ else
+ //if(default_mar_ != NULL)
+ return default_mar_;
+ /*
+ else
+ return &bin_mar_; //default byte-copy
+ */
+ }
+
+ //return default marshaler
+ msg_marshaler * get_msg_marshaler(void) {
+ //if(default_mar_ != NULL)
+ return default_mar_;
+ //return &bin_mar_;
+ }
+
+ id_marshaler * get_id_marshaler(void) {
+ return &id_mar_;
+ }
+ };
+
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/message.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/message.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,135 @@
+//
+// message.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef MESSAGE_HPP
+#define MESSAGE_HPP
+
+#include <string>
+#include <vector>
+#include <boost/shared_ptr.hpp>
+#include <boost/shared_array.hpp>
+#include <boost/serialization/string.hpp>
+#include <boost/serialization/vector.hpp>
+#include <boost/serialization/split_member.hpp>
+#include <boost/serialization/binary_object.hpp>
+#include <boost/serialization/array.hpp>
+
+namespace boost {
+ namespace channel {
+
+ template<typename id_type>
+ struct message {
+ id_type id_;
+ boost::shared_ptr<void> data_;
+ message(id_type id, boost::shared_ptr<void> d) :
+ id_(id), data_(d) {
+ }
+ message() {
+ }
+ };
+
+ /**
+ * block messages: for passing a continuous memory blocks as messages, such as
+ * data classes marshaled as bindary objects (void *) and arrays
+ */
+ template<typename T>
+ struct binary_message {
+ size_t size_;
+ boost::shared_ptr<void> data_;
+ binary_message() :
+ size_(0), data_() {
+ }
+ binary_message(T *d, size_t s) :
+ size_(s), data_(d) {
+ }
+ binary_message(boost::shared_ptr<void> d, size_t s) :
+ size_(s), data_(d) {
+ }
+ ~binary_message() {
+ } //shared_ptr should clean up data_
+ template<class Archive>
+ void save(Archive & ar, const unsigned int version) const {
+ ar & size_;
+ ar & boost::serialization::make_binary_object(data_.get(), size_);
+ }
+ template<class Archive>
+ void load(Archive & ar, const unsigned int version) {
+ ar & size_;
+ data_ = new char[size_];
+ ar & boost::serialization::make_binary_object(data_.get(), size_);
+ }
+ };
+
+ template<typename T>
+ struct array_message {
+ size_t size_;
+ boost::shared_array<T> data_;
+ array_message() :
+ size_(0), data_() {
+ }
+ array_message(T *d, size_t s) :
+ size_(s), data_(d) {
+ }
+ array_message(boost::shared_array<T> d, size_t s) :
+ size_(s), data_(d) {
+ }
+ ~array_message() {
+ } //shared_ptr should clean up data_
+ template<class Archive>
+ void save(Archive & ar, const unsigned int version) const {
+ ar & size_;
+ ar & boost::serialization::make_array<T>(data_.get(), size_);
+ }
+ template<class Archive>
+ void load(Archive & ar, const unsigned int version) {
+ ar & size_;
+ data_ = new T[size_];
+ ar & boost::serialization::make_array<T>(data_.get(), size_);
+ }
+ };
+
+ /**
+ * Channel Management Msg types
+ */
+ ///when 2 channels connects, channel_info_msg is sent to tell
+ ///peers about the channel info
+ struct channel_info_msg_t {
+ std::string host_addr;
+ void *intf; ///the interface connect to peer
+ bool is_local;
+ channel_info_msg_t() {
+ intf = NULL;
+ is_local = false;
+ }
+
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int version) {
+ ar & host_addr;
+ }
+
+ };
+
+ ///pubsub_info_msg is used to notify peer channels about
+ ///publish/subscribe events
+ template<class id_type>
+ struct pubsub_info_msg_t {
+ std::vector<id_type> msg_types;
+ pubsub_info_msg_t() {
+ }
+
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int version) {
+ ar & msg_types;
+ }
+
+ };
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/name.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/name.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,272 @@
+//
+// name.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef NAME_HPP
+#define NAME_HPP
+
+#include <list>
+#include <map>
+#include <algorithm>
+#include <boost/utility.hpp>
+#include <boost/bind.hpp>
+#include <boost/channel/platforms/synch_policy.hpp>
+
+namespace boost {
+ namespace channel {
+
+ namespace detail {
+
+ //name binding callback; should i use boost::function?
+ template<typename name>
+ class binding_callback_base {
+ public:
+ void invoke(name *n, typename name::binding_event e) {
+ invoke_func_(this, n, e);
+ }
+
+ void destroy() {
+ destroy_func_(this);
+ }
+
+ protected:
+ typedef void
+ (*invoke_func_type)(binding_callback_base*, name *n, typename name::binding_event e);
+ typedef void (*destroy_func_type)(binding_callback_base*);
+
+ binding_callback_base(invoke_func_type invoke_func, destroy_func_type destroy_func) :
+ invoke_func_(invoke_func), destroy_func_(destroy_func) {
+ }
+
+ ~binding_callback_base() {
+ }
+
+ private:
+ invoke_func_type invoke_func_;
+ destroy_func_type destroy_func_;
+ };
+
+ template<typename name, typename handler_type>
+ class binding_callback: public binding_callback_base<name> {
+ public:
+ binding_callback(handler_type handler) :
+ binding_callback_base<name> (&binding_callback<name, handler_type>::invoke_handler,
+ &binding_callback<name, handler_type>::destroy_handler), handler_(handler) {
+ }
+
+ static void invoke_handler(binding_callback_base<name>* base, name *n,
+ typename name::binding_event e) {
+ static_cast<binding_callback<name, handler_type>*> (base)->handler_(n, e);
+ }
+
+ static void destroy_handler(binding_callback_base<name>* base) {
+ delete static_cast<binding_callback<name, handler_type>*> (base);
+ }
+
+ private:
+ handler_type handler_;
+ };
+
+ }
+
+ class name_base {
+ public:
+ enum scope_type {
+ scope_local = 0, scope_remote, scope_global, scope_number
+ };
+
+ enum member_type {
+ member_all = -1, member_local = 0,//local queues and callbacks
+ member_remote, //interfaces to remote/local name_spaces
+ member_number
+ };
+
+ enum binding_event {
+ bind_out_ev = 0, unbind_out_ev, bind_in_ev, unbind_in_ev, bind_ev, unbind_ev
+ };
+
+ ///binding scope checking table:
+ ///row: publish_member_type * scope_number + publish_scope
+ ///col: subscribe_member_type * scope_number + subscribe_scope
+ ///since "remote" members can only send_to/recv_from "local"
+ ///members, only the upper-left 4x4 sub-matrix have value
+ ///value "1" marks a valid combo of publisher(row) sending to subscriber(col)
+ ///value "0" marks invalid
+ static short scope_checking_tbl_[][name_base::scope_number * name_base::member_number];
+ };
+
+ /// "name" should be noncopyable; otherwise the connection between
+ /// named_in and named_out will be messed up
+ template<typename id_type, typename executor, typename synch_policy>
+ class name: public name_base, private boost::noncopyable {
+ public:
+
+ typedef std::list<name *> binding_set_type;
+
+ id_type id_;
+ typename name_base::scope_type scope_;
+ typename name_base::member_type type_;
+ executor *exec_;
+
+ typename synch_policy::mutex bind_lock_;
+ std::list<name *> bindings_;
+ detail::binding_callback_base<name> *binding_cb_;
+
+ /*
+ template <typename id_type, typename synch_policy>
+ friend bool operator< (const name<id_type,synch_policy> &left,
+ const name<id_type,synch_policy> &right);
+ */
+ protected:
+ //make constructor protected, so only children can be created
+ template<typename binding_cb_type>
+ name(id_type id, scope_type scope, member_type type, binding_cb_type cb, executor *e) :
+ id_(id), scope_(scope), type_(type), exec_(e), binding_cb_(new detail::binding_callback<name,
+ binding_cb_type>(cb)) {
+ }
+
+ name(id_type id, scope_type scope, member_type type) :
+ id_(id), scope_(scope), type_(type), exec_(NULL), binding_cb_(NULL) {
+ }
+
+ name() :
+ id_(), scope_(scope_local), type_(member_local), exec_(NULL), binding_cb_(NULL) {
+ }
+
+ ~name() {
+ unbind_all(); //detach all peers
+ if (binding_cb_ != NULL)
+ binding_cb_->destroy();
+ }
+
+ template<typename binding_cb_type>
+ void set_name(id_type id, scope_type scope, member_type type, binding_cb_type cb, executor *e) {
+ id_ = id;
+ scope_ = scope;
+ type_ = type;
+ exec_ = e;
+ binding_cb_ = new detail::binding_callback<name, binding_cb_type>(cb);
+ }
+
+ void set_name(id_type id, scope_type scope, member_type type) {
+ id_ = id;
+ scope_ = scope;
+ type_ = type;
+ }
+
+ void binding_callback(name *n, binding_event e) {
+ if (binding_cb_ != NULL) {
+ if (exec_ != NULL) //execute binding callback in executor
+ exec_->execute(boost::bind(&detail::binding_callback_base<name>::invoke, binding_cb_,
+ n, e));
+ else
+ //execute in place
+ binding_cb_->invoke(n, e);
+ }
+ }
+
+ public:
+ int num_bindings(void) {
+ return bindings_.size();
+ }
+ std::list<name *> & bindings(void) {
+ return bindings_;
+ }
+
+ //validate the src and dest scope matches
+ static bool scope_checking(name *src, name *dst) {
+ short src_row = src->type_ * name_base::scope_number + src->scope_;
+ short dst_col = dst->type_ * name_base::scope_number + dst->scope_;
+ return name_base::scope_checking_tbl_[src_row][dst_col] == 1;
+ }
+
+ //the following 2 callbacks invoked by name_space to notify binding changes
+ void bind(name *n) {
+ typename synch_policy::scoped_lock lock(bind_lock_);
+ //add n to bindings_
+ if (std::find(bindings_.begin(), bindings_.end(), n) == bindings_.end()) {
+ bindings_.push_front(n);
+ //callback
+ binding_callback(n, bind_ev);
+ }
+ }
+ void unbind(name *n) {
+ typename std::list<name *>::iterator iter;
+ typename synch_policy::scoped_lock lock(bind_lock_);
+ if ((iter = std::find(bindings_.begin(), bindings_.end(), n)) != bindings_.end()) {
+ //remove n from bindings_
+ //bindings_.remove(n);
+ bindings_.erase(iter);
+ //callback
+ binding_callback(n, unbind_ev);
+ }
+ }
+
+ //during name-destruction, disconn all
+ void unbind_all(void) {
+ typename synch_policy::scoped_lock lock(bind_lock_);
+ //unbind_all
+ for (typename std::list<name *>::iterator iter = bindings_.begin(); iter != bindings_.end();) {
+ //remove n from bindings_
+ typename std::list<name *>::iterator cur = iter;
+ name *n = *cur;
+ n->unbind(this); //remove reference to me at remote
+ iter++;
+ bindings_.erase(cur);
+ }
+ }
+
+ //unbind all external bindings; this must be a member_local
+ void unbind_all_external(void) {
+ typename synch_policy::scoped_lock lock(bind_lock_);
+ //unbind_all_external
+ for (typename std::list<name *>::iterator iter = bindings_.begin(); iter != bindings_.end();)
+ if ((*iter)->type_ == member_remote) {
+ //remove n from bindings_
+ typename std::list<name *>::iterator cur = iter;
+ name *n = *cur;
+ n->unbind(this); //remove reference to me at remote
+ iter++;
+ bindings_.erase(cur);
+ }
+ }
+
+ //predicates used for name space queries
+ ///names from internal and visible at interfaces to external channels
+ static bool exported_name(name *n) {
+ if (n->type_ == member_local && (n->scope_ == scope_remote || n->scope_ == scope_global))
+ return true;
+ return false;
+ }
+
+ ///names from internal and visible to internal peers
+ static bool internal_name(name *n) {
+ if (n->type_ == member_local && (n->scope_ == scope_local || n->scope_ == scope_global))
+ return true;
+ return false;
+ }
+
+ ///all/any names in name_space
+ static bool any_name(name *n) {
+ return true;
+ }
+
+ };
+
+ /*
+ template <typename id_type, typename synch_policy>
+ friend bool operator< (const name<id_type,synch_policy> &left,
+ const name<id_type,synch_policy> &right) {
+ return left.id_ < right.id_;
+ }
+ */
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/name_spaces/assoc_id_trait.def
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/name_spaces/assoc_id_trait.def 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,37 @@
+//
+// assoc_id_trait.def
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include "name.def"
+
+/// definitions of system messages for regex_id ids
+#define DEFINE_REGEX_SYS_IDS \
+ DEFINE_SCOPE_TABLE \
+ regex_id id_trait<regex_id>::channel_conn_msg = "_channel_conn_msg_"; \
+ regex_id id_trait<regex_id>::channel_disconn_msg = "_channel_disconn_msg_"; \
+ regex_id id_trait<regex_id>::init_subscription_info_msg = "_init_subscription_info_msg_"; \
+ regex_id id_trait<regex_id>::connection_ready_msg = "_connection_ready_msg_"; \
+ regex_id id_trait<regex_id>::subscription_info_msg = "_subscription_info_msg_"; \
+ regex_id id_trait<regex_id>::unsubscription_info_msg = "_unsubscription_info_msg_"; \
+ regex_id id_trait<regex_id>::publication_info_msg = "_publication_info_msg_"; \
+ regex_id id_trait<regex_id>::unpublication_info_msg = "_unpublication_info_msg_";
+
+/* definitions of system messages for tuple_id ids */
+#define DEFINE_TUPLE_SYS_IDS( tuple_type ) \
+ DEFINE_SCOPE_TABLE \
+ template <> boost::channel::tuple_id<tuple_type> boost::channel::id_trait<boost::channel::tuple_id<tuple_type> >::channel_conn_msg(boost::channel::tuple_id<tuple_type>::channel_conn_type); \
+ template <> boost::channel::tuple_id<tuple_type> boost::channel::id_trait<boost::channel::tuple_id<tuple_type> >::channel_disconn_msg(boost::channel::tuple_id<tuple_type>::channel_disconn_type); \
+ template <> boost::channel::tuple_id<tuple_type> boost::channel::id_trait<boost::channel::tuple_id<tuple_type> >::init_subscription_info_msg(boost::channel::tuple_id<tuple_type>::init_subscription_info_type); \
+ template <> boost::channel::tuple_id<tuple_type> boost::channel::id_trait<boost::channel::tuple_id<tuple_type> >::connection_ready_msg(boost::channel::tuple_id<tuple_type>::connection_ready_type); \
+ template <> boost::channel::tuple_id<tuple_type> boost::channel::id_trait<boost::channel::tuple_id<tuple_type> >::subscription_info_msg(boost::channel::tuple_id<tuple_type>::subscription_info_type); \
+ template <> boost::channel::tuple_id<tuple_type> boost::channel::id_trait<boost::channel::tuple_id<tuple_type> >::unsubscription_info_msg(boost::channel::tuple_id<tuple_type>::unsubscription_info_type); \
+ template <> boost::channel::tuple_id<tuple_type> boost::channel::id_trait<boost::channel::tuple_id<tuple_type> >::publication_info_msg(boost::channel::tuple_id<tuple_type>::publication_info_type); \
+ template <> boost::channel::tuple_id<tuple_type> boost::channel::id_trait<boost::channel::tuple_id<tuple_type> >::unpublication_info_msg(boost::channel::tuple_id<tuple_type>::unpublication_info_type); \
+ int field_trait<int>::wildcard = -1010101; /* should choose a better value */ \
+ float field_trait<float>::wildcard = -1010101.0101; /* should choose a better value */ \
+ const char * field_trait<std::string>::wildcard = "-1010101"; //should choose a better value

Added: sandbox/channel/boost/channel/name_spaces/assoc_id_trait.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/name_spaces/assoc_id_trait.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,361 @@
+//
+// assoc_id_trait.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASSOC_ID_TRAIT_HPP
+#define ASSOC_ID_TRAIT_HPP
+
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <boost/regex.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/serialization/string.hpp>
+#include <boost/serialization/split_member.hpp>
+#include <boost/tuple/tuple_comparison.hpp>
+#include <boost/tuple/tuple_io.hpp>
+
+namespace boost {
+ namespace channel {
+
+ /**
+ * regex_id type class
+ * using strings/regex as id and use regex-matching for id matching
+ */
+ struct regex_id {
+ bool is_regex_;
+ std::string text_;
+ boost::shared_ptr<boost::regex> re_;
+ regex_id() :
+ is_regex_(false), text_(""), re_() {
+ }
+ regex_id(const char * id_text) :
+ is_regex_(false), text_(id_text), re_() {
+ }
+ regex_id(boost::regex *reg) :
+ is_regex_(true), text_(""), re_(reg) {
+ }
+ bool operator<(const regex_id &id) const {
+ if (!is_regex_ && id.is_regex_)
+ return true;
+ else if (!is_regex_ && !id.is_regex_ && text_ < id.text_)
+ return true;
+ else if (is_regex_ && id.is_regex_ && (*re_) < (*id.re_))
+ return true;
+ return false;
+ }
+ bool operator==(const regex_id &id) const {
+ if (!is_regex_ && !id.is_regex_ && text_ == id.text_)
+ return true;
+ else if (is_regex_ && id.is_regex_ && (*re_) == (*id.re_))
+ return true;
+ return false;
+ }
+ bool operator!=(const regex_id &id) const {
+ return !operator==(id);
+ }
+ template<class Archive>
+ void save(Archive & ar, const unsigned int version) const {
+ ar & is_regex_;
+ if (!is_regex_) {
+ ar & text_;
+ //std::cout << "save id: " << text_ << std::endl;
+ } else {
+ typename boost::regex::flag_type f = re_->flags();
+ std::string str = re_->str();
+ ar & f;
+ ar & str;
+ //std::cout << "save id: " << *re_ << std::endl;
+ }
+ }
+ template<class Archive>
+ void load(Archive & ar, const unsigned int version) {
+ ar & is_regex_;
+ if (!is_regex_) {
+ ar & text_;
+ //std::cout << "load id: " << text_ << std::endl;
+ } else {
+ typename boost::regex::flag_type f;
+ std::string str;
+ ar & f;
+ ar & str;
+ re_.reset(new boost::regex(str, f));
+ //std::cout << "load id: " <<* re_ << std::endl;
+ }
+ }
+ BOOST_SERIALIZATION_SPLIT_MEMBER()
+ };
+
+ /**
+ * regex_id_trait class
+ */
+ template<class id_type> class id_trait;
+
+ template <>
+ class id_trait<regex_id> {
+ public:
+ ///define system msgs
+ static regex_id channel_conn_msg;
+ static regex_id channel_disconn_msg;
+ static regex_id init_subscription_info_msg;
+ static regex_id connection_ready_msg;
+ static regex_id subscription_info_msg;
+ static regex_id unsubscription_info_msg;
+ static regex_id publication_info_msg;
+ static regex_id unpublication_info_msg;
+
+ typedef regex_id id_type;
+
+ static bool match(regex_id id1, regex_id id2)
+ {
+ //std::cout << "try to match : " << id_to_string(id1) << "; " << id_to_string(id2) << std::endl;
+ if (!id1.is_regex_ && !id2.is_regex_)
+ return id1.text_ == id2.text_;
+ else if (id1.is_regex_ && !id2.is_regex_)
+ return boost::regex_match(id2.text_, *(id1.re_));
+ else if (id2.is_regex_ && !id1.is_regex_)
+ return boost::regex_match(id1.text_, *(id2.re_));
+ else if (id1.is_regex_ && id2.is_regex_)
+ return (*id1.re_) == (*id2.re_);
+ return false;
+ }
+
+ //are we using assoc/fuzzy matching here
+ static bool wildcard_name(const regex_id &id) {
+ return id.is_regex_;
+ }
+
+ static std::string id_to_string(const regex_id &id) {
+ std::ostringstream os;
+ if (id.is_regex_)
+ os << "regex_id " << "[regex_pattern]: " << *(id.re_);
+ else
+ os << "regex_id " << "[plain_text]: " << id.text_;
+ return os.str();
+ }
+ };
+
+ /**
+ * tuple_id : use linda style tuple as id and associative lookup for matching
+ * a tuple_id consist of multiple fields
+ * we should just define field_trait for primitive types here
+ * user should define field_traits for user-defined types
+ */
+ /**
+ * basic field_trait
+ */
+ template<typename field_type> class field_trait;
+
+ template <>
+ class field_trait<int> {
+ public:
+ typedef int field_type;
+ static int wildcard;
+ static bool wildcard_field(int f) {
+ if (f == wildcard)
+ return true;
+ return false;
+ }
+ static bool match(int f1, int f2) {
+ if (f1 == wildcard || f2 == wildcard)
+ return true;
+ return f1 == f2;
+ }
+ };
+
+ template <>
+ class field_trait<float> {
+ public:
+ typedef float field_type;
+ static float wildcard;
+ static bool wildcard_field(float f) {
+ if (f == wildcard)
+ return true;
+ return false;
+ }
+ static bool match(float f1, float f2) {
+ if (f1 == wildcard || f2 == wildcard)
+ return true;
+ return f1 == f2;
+ }
+ };
+
+ template <>
+ class field_trait<std::string> {
+ public:
+ typedef std::string field_type;
+ static const char * wildcard;
+ static bool wildcard_field(std::string f) {
+ if (f == wildcard)
+ return true;
+ return false;
+ }
+ static bool match(std::string f1, std::string f2) {
+ if (f1 == wildcard || f2 == wildcard)
+ return true;
+ return f1 == f2;
+ }
+ };
+
+ /* --- we should add field_trait for other primitive types here --- */
+
+ /**
+ * use boost::tuple as tuple_id
+ */
+ template<typename Tuple_Type>
+ class tuple_id {
+ public:
+ typedef Tuple_Type tuple_type;
+ enum sys_ids {
+ app_type = 0,
+ channel_conn_type,
+ channel_disconn_type,
+ init_subscription_info_type,
+ connection_ready_type,
+ subscription_info_type,
+ unsubscription_info_type,
+ publication_info_type,
+ unpublication_info_type
+ };
+ int type_;
+ tuple_type tuple_;
+ tuple_id() :
+ type_(app_type), tuple_() {
+ }
+ tuple_id(int type) :
+ type_(type), tuple_() {
+ }
+ tuple_id(tuple_type tt) :
+ type_(app_type), tuple_(tt) {
+ }
+ tuple_id(const tuple_id &id) :
+ type_(id.type_), tuple_(id.tuple_) {
+ }
+ bool operator<(const tuple_id &id) const {
+ if (type_ < id.type_)
+ return true;
+ else if (type_ == id.type_ && type_ == app_type && tuple_ < id.tuple_)
+ return true;
+ return false;
+ }
+ bool operator==(const tuple_id &id) const {
+ if (type_ == id.type_) {
+ if (type_ != app_type)
+ return true;
+ else
+ return tuple_ == id.tuple_;
+ }
+ return false;
+ }
+ bool operator!=(const tuple_id &id) const {
+ return !operator==(id);
+ }
+ template<class Archive>
+ inline void serialize_priv(Archive & ar, const boost::tuples::null_type&,
+ const unsigned int version) {
+ }
+ template<class Archive, typename H, typename T>
+ inline void serialize_priv(Archive & ar, boost::tuples::cons<H, T> &t,
+ const unsigned int version) {
+ ar & t.get_head();
+ serialize_priv(ar, t.get_tail(), version);
+ }
+
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int version) {
+ ar & type_;
+ if (type_ == app_type) {
+ ar & tuple_.get_head();
+ serialize_priv(ar, tuple_.get_tail(), version);
+ }
+ //std::cout << "serialize tuple_id : type[" << type_ << "] tuple[" << tuple_ << "]" << std::endl;
+ }
+ };
+
+ /**
+ * tuple id trait
+ */
+ template<typename Tuple_Type>
+ class id_trait<tuple_id<Tuple_Type> > {
+ public:
+
+ typedef Tuple_Type tuple_type;
+ typedef tuple_id<tuple_type> id_type;
+
+ ///define system msgs
+ static id_type channel_conn_msg;
+ static id_type channel_disconn_msg;
+ static id_type init_subscription_info_msg;
+ static id_type connection_ready_msg;
+ static id_type subscription_info_msg;
+ static id_type unsubscription_info_msg;
+ static id_type publication_info_msg;
+ static id_type unpublication_info_msg;
+
+ static bool match_tuple(const boost::tuples::null_type&, const boost::tuples::null_type&)
+ {
+ //std::cout << "match_tuple(const boost::tuples::null_type matched tuple \n";
+ return true;
+ }
+
+ template <typename H, typename T>
+ static bool match_tuple(const boost::tuples::cons<H,T> &t1, const boost::tuples::cons<H,T> &t2)
+ {
+ if(!field_trait<H>::match(t1.get_head(), t2.get_head()))
+ return false;
+ return match_tuple(t1.get_tail(), t2.get_tail());
+ }
+
+ static bool match(id_type id1, id_type id2)
+ {
+ if (id1.type_ != id2.type_)
+ return false;
+ if (id1.type_ == id_type::app_type) {
+ if (wildcard_tuple(id1.tuple_) && wildcard_tuple(id2.tuple_) && (id1.tuple_ != id2.tuple_))
+ return false;
+ if (id1.tuple_ == id2.tuple_)
+ return true;
+ return match_tuple(id1.tuple_, id2.tuple_);
+ }
+ return true;
+ }
+
+ //are we using assoc/fuzzy matching here
+ static bool wildcard_tuple(const boost::tuples::null_type&)
+ {
+ return false;
+ }
+
+ template <typename H, typename T>
+ static bool wildcard_tuple(const boost::tuples::cons<H,T> &t1)
+ {
+ if(field_trait<H>::wildcard_field(t1.get_head()))
+ return true;
+ return wildcard_tuple(t1.get_tail());
+ }
+
+ static bool wildcard_name(const id_type &id) {
+ if (id.type_ != id_type::app_type)
+ return false;
+ return wildcard_tuple(id.tuple_);
+ }
+
+ static std::string id_to_string(const id_type &id) {
+ std::ostringstream os;
+ os << "tuple_id : type[" << id.type_ << "] tuple[" << id.tuple_ << "]";
+ return os.str();
+ }
+ };
+
+ }
+}
+
+#include "assoc_id_trait.def"
+
+#endif
+

Added: sandbox/channel/boost/channel/name_spaces/hierarchical_id_trait.def
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/name_spaces/hierarchical_id_trait.def 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,55 @@
+//
+// hierarchical_id_trait.def
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include "name.def"
+
+/// definitions of system messages for str_path_id<'/'> ids
+#define DEFINE_SLASH_PATH_SYS_IDS \
+ DEFINE_SCOPE_TABLE \
+ template <> str_path_id<'/'> id_trait<str_path_id<'/'> >::channel_conn_msg = "/sys/channel_conn_msg"; \
+ template <> str_path_id<'/'> id_trait<str_path_id<'/'> >::channel_disconn_msg = "/sys/channel_disconn_msg"; \
+ template <> str_path_id<'/'> id_trait<str_path_id<'/'> >::init_subscription_info_msg = "/sys/init_subscription_info_msg"; \
+ template <> str_path_id<'/'> id_trait<str_path_id<'/'> >::connection_ready_msg = "/sys/connection_ready_msg"; \
+ template <> str_path_id<'/'> id_trait<str_path_id<'/'> >::subscription_info_msg = "/sys/subscription_info_msg"; \
+ template <> str_path_id<'/'> id_trait<str_path_id<'/'> >::unsubscription_info_msg = "/sys/unsubscription_info_msg"; \
+ template <> str_path_id<'/'> id_trait<str_path_id<'/'> >::publication_info_msg = "/sys/publication_info_msg"; \
+ template <> str_path_id<'/'> id_trait<str_path_id<'/'> >::unpublication_info_msg = "/sys/unpublication_info_msg"; \
+ template <> str_path_id<'/'>::value_type id_trait<str_path_id<'/'> >::root_token = "//"; \
+ template <> str_path_id<'/'>::value_type id_trait<str_path_id<'/'> >::wildcard_token = "*";
+
+/// definitions of system messages for str_path_id<'|'> ids
+#define DEFINE_BAR_PATH_SYS_IDS \
+ DEFINE_SCOPE_TABLE \
+ template <> str_path_id<'|'> id_trait<str_path_id<'|'> >::channel_conn_msg = "|sys|channel_conn_msg"; \
+ template <> str_path_id<'|'> id_trait<str_path_id<'|'> >::channel_disconn_msg = "|sys|channel_disconn_msg"; \
+ template <> str_path_id<'|'> id_trait<str_path_id<'|'> >::init_subscription_info_msg = "|sys|init_subscription_info_msg"; \
+ template <> str_path_id<'|'> id_trait<str_path_id<'|'> >::connection_ready_msg = "|sys|connection_ready_msg"; \
+ template <> str_path_id<'|'> id_trait<str_path_id<'|'> >::subscription_info_msg = "|sys|subscription_info_msg"; \
+ template <> str_path_id<'|'> id_trait<str_path_id<'|'> >::unsubscription_info_msg = "|sys|unsubscription_info_msg"; \
+ template <> str_path_id<'|'> id_trait<str_path_id<'|'> >::publication_info_msg = "|sys|publication_info_msg"; \
+ template <> str_path_id<'|'> id_trait<str_path_id<'|'> >::unpublication_info_msg = "|sys|unpublication_info_msg"; \
+ template <> str_path_id<'|'>::value_type id_trait<str_path_id<'|'> >::root_token = "||"; \
+ template <> str_path_id<'|'>::value_type id_trait<str_path_id<'|'> >::wildcard_token = "*";
+
+/// definitions of system messages for str_path_id<'\'> ids
+#define DEFINE_BACKSLASH_PATH_SYS_IDS \
+ DEFINE_SCOPE_TABLE \
+ template <> str_path_id<'\\'> id_trait<str_path_id<'\\'> >::channel_conn_msg = "\\sys\\channel_conn_msg"; \
+ template <> str_path_id<'\\'> id_trait<str_path_id<'\\'> >::channel_disconn_msg = "\\sys\\channel_disconn_msg"; \
+ template <> str_path_id<'\\'> id_trait<str_path_id<'\\'> >::init_subscription_info_msg = "\\sys\\init_subscription_info_msg"; \
+ template <> str_path_id<'\\'> id_trait<str_path_id<'\\'> >::connection_ready_msg = "\\sys\\connection_ready_msg"; \
+ template <> str_path_id<'\\'> id_trait<str_path_id<'\\'> >::subscription_info_msg = "\\sys\\subscription_info_msg"; \
+ template <> str_path_id<'\\'> id_trait<str_path_id<'\\'> >::unsubscription_info_msg = "\\sys\\unsubscription_info_msg"; \
+ template <> str_path_id<'\\'> id_trait<str_path_id<'\\'> >::publication_info_msg = "\\sys\\publication_info_msg"; \
+ template <> str_path_id<'\\'> id_trait<str_path_id<'\\'> >::unpublication_info_msg = "\\sys\\unpublication_info_msg"; \
+ template <> str_path_id<'\\'>::value_type id_trait<str_path_id<'\\'> >::root_token = "\\\\"; \
+ template <> str_path_id<'\\'>::value_type id_trait<str_path_id<'\\'> >::wildcard_token = "*";
+
+
+

Added: sandbox/channel/boost/channel/name_spaces/hierarchical_id_trait.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/name_spaces/hierarchical_id_trait.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,198 @@
+//
+// hierarchical_id_trait.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef HIERARCHICAL_ID_TRAIT_HPP
+#define HIERARCHICAL_ID_TRAIT_HPP
+
+#include <vector>
+#include <string>
+#include <sstream>
+#include <boost/serialization/string.hpp>
+#include <boost/serialization/vector.hpp>
+#include <boost/serialization/base_object.hpp>
+
+namespace boost {
+ namespace channel {
+ /**
+ * hierarchical id types:
+ * each id/name in hierarchical name_space is a "path name" of sub-ids/tokens
+ * denoting the "branches" of tree you traverse thru before reaching
+ * the tree-node which represents the id; these sub-ids called tokens
+ * 1. if token_type is "char", HierarchicalId will be strings
+ * 2. if token_type is "string", HierarichalId is unix style pathnames
+ *
+ * vector<token_type> is used as the base class for all hierarchical id
+ * to store the elements of hierarchical ids
+ * real applications' hierarchial ids should inherit vector class and
+ * add :
+ * 1. convenience constructors
+ * 2. marshal/demarshal methods
+ * 3. other convenience methods
+ */
+
+ template<class id_type> class id_trait;
+
+ /**
+ * str_path_id - a hierarchical id type using unix path names
+ * element_type = string
+ * in channel, only absolute pathnames are used: ie. must start with "/"
+ * add convenience constructors and methods for decoding the names
+ */
+ template<char sep = '/'>
+ struct str_path_id: public std::vector<std::string> {
+ enum {
+ separator = sep
+ };
+ bool valid_;
+ str_path_id() {
+ valid_ = true;
+ }
+ str_path_id(const char * pathname) {
+ std::string name(pathname);
+ valid_ = true;
+ size_type pos1 = std::string::npos, pos2 = std::string::npos;
+ pos1 = name.find(separator);
+ if (pos1 == std::string::npos) {
+ valid_ = false;
+ } else {
+ while (true) {
+ pos2 = name.find(separator, pos1 + 1);
+ if (pos2 != std::string::npos)
+ push_back(name.substr(pos1 + 1, pos2 - pos1 - 1));
+ else {
+ std::string s = name.substr(pos1 + 1);
+ pos2 = s.find_last_not_of(' ');
+ if (pos2 != std::string::npos)
+ push_back(s.substr(0, pos2 + 1));
+ break;
+ }
+ pos1 = pos2;
+ }
+ }
+ }
+ std::string get_str_name(void) {
+ std::string name;
+ for (size_t i = 0; i < size(); i++) {
+ name.push_back(sep);
+ name.append(operator[](i));
+ }
+ return name;
+ }
+
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int version) {
+ ar
+ & boost::serialization::base_object<std::vector<std::string> >(
+ *this);
+ }
+ };
+
+ ///trait class for string pathname id type
+ template<char sep>
+ class id_trait<str_path_id<sep> > {
+ public:
+
+ typedef str_path_id<sep> id_type;
+ enum {separator = id_type::separator};
+
+ typedef typename id_type::value_type token_type;
+
+ ///define system msgs
+ static id_type channel_conn_msg;
+ static id_type channel_disconn_msg;
+ static id_type init_subscription_info_msg;
+ static id_type connection_ready_msg;
+ static id_type subscription_info_msg;
+ static id_type unsubscription_info_msg;
+ static id_type publication_info_msg;
+ static id_type unpublication_info_msg;
+
+ static token_type root_token; //just a name for root trie node, not in name_space
+ static token_type wildcard_token;
+
+ ///need the comparisons for msg matching and map
+ static bool eq(const id_type &id1, const id_type &id2)
+ { return id1 == id2;}
+ static bool lt(const id_type &id1, const id_type &id2)
+ { return id1 < id2;}
+
+ static std::string id_to_string(const id_type &id) {
+ std::ostringstream os;
+ for(size_t i=0; i<id.size(); i++)
+ os << (char)separator << id[i];
+ return os.str();
+ }
+
+ static bool wildcard_name(const id_type &id) {
+ return (*id.rbegin()) == wildcard_token;
+ }
+
+ static bool valid(const id_type &id) {
+ if (!id.valid_) return false;
+ size_t sz = id.size();
+ for (size_t i=0; i<sz; i++)
+ if (id[i] == id_trait::wildcard_token && i != (sz-1))
+ return false;
+ return true;
+ }
+
+ enum id_compare_result {
+ id_match,
+ id_1_contains_2,
+ id_2_contains_1,
+ id_mismatch
+ };
+
+ static id_compare_result compare(id_type &id1, id_type &id2)
+ {
+ int sz1 = id1.size();
+ int sz2 = id2.size();
+ int sz = (sz1 < sz2)?sz1:sz2;
+ for(int i=0; i<sz; i++) {
+ if (id1[i] != id2[i]) {
+ if (id1[i] == id_trait::wildcard_token)
+ return id_1_contains_2;
+ else if (id2[i] == id_trait::wildcard_token)
+ return id_2_contains_1;
+ else return id_mismatch;
+ }
+ }
+ if (sz1 == sz2)
+ return id_match;
+ else if(sz1 < sz2 && (sz1+1) == sz2 && id2[sz1] == id_trait::wildcard_token)
+ return id_2_contains_1;
+ else if(sz2 < sz1 && (sz2+1) == sz1 && id1[sz2] == id_trait::wildcard_token)
+ return id_1_contains_2;
+ return id_mismatch;
+ }
+
+ //compiler doesnt allow references here
+ //static bool match(const id_type &id1, const id_type &id2)
+ static bool match(id_type id1, id_type id2)
+ {
+ return compare(id1,id2) != id_mismatch;
+ }
+
+ //compiler doesnt allow references here
+ //static bool id1contains2(const id_type &id1, const id_type &id2)
+ static bool id1contains2(id_type id1, id_type id2)
+ {
+ id_compare_result res = compare(id1,id2);
+ return res == id_match || res == id_1_contains_2;
+ }
+
+ };
+
+ }
+}
+
+#include "hierarchical_id_trait.def"
+
+#endif
+

Added: sandbox/channel/boost/channel/name_spaces/hierarchical_name_space.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/name_spaces/hierarchical_name_space.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,824 @@
+//
+// hierarchical_name_space.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef HIERARCHICAL_NAME_SPACE_HPP
+#define HIERARCHICAL_NAME_SPACE_HPP
+
+#include <map>
+#include <list>
+#include <algorithm>
+#include <boost/shared_ptr.hpp>
+#include <boost/channel/name_spaces/hierarchical_id_trait.hpp>
+#include <boost/channel/platforms/synch_policy.hpp>
+#include <boost/channel/name.hpp>
+#include <boost/channel/name_spaces/name_space_change_notify.hpp>
+
+namespace boost {
+ namespace channel {
+ /**
+ * hierarchical_name_space:
+ * using trie as routing data structure
+ * using pathname matching
+ */
+ template<class idtype, class executor_type, class synchpolicy>
+ class hierarchical_name_space {
+ public:
+ typedef idtype id_type;
+ typedef boost::channel::id_trait<id_type> id_trait;
+ typedef synchpolicy synch_policy;
+ typedef executor_type executor;
+ typedef typename id_trait::token_type token_type;
+ typedef typename synch_policy::platform platform;
+ //we dont care about In/Out operations here, just names and bindings
+ typedef boost::channel::name<id_type,executor_type,synch_policy> name;
+
+ private:
+ typedef hierarchical_name_space<idtype,executor_type,synchpolicy> ns_type;
+
+ struct trie_node {
+ token_type token; //name of this node
+ /// -- trie data structure --
+ trie_node *parent;
+ std::map<token_type, trie_node *> children;
+ typename synch_policy::mutex trie_lock_; //to protect trie structure
+ /// -- bindings --
+ // normal name binding
+ std::list<name *> outs_;
+ std::list<name *> ins_;
+ // wildcard name binding
+ std::list<name *> outs_w_;
+ std::list<name *> ins_w_;
+ typename synch_policy::mutex bind_lock_; //to protect binding structure
+ trie_node(token_type e, trie_node *p) : token(e), parent(p) {
+ }
+ ~trie_node() {
+ typename synch_policy::scoped_lock lock(trie_lock_);
+ for(typename std::map<token_type, trie_node *>::iterator iter = children.begin();
+ iter != children.end(); iter++) {
+ if (iter->second != NULL)
+ delete iter->second;
+ }
+ }
+ };
+
+ //name_space
+ boost::shared_ptr<trie_node> ns_root_; //root of name_space tree
+ //no need for a global name_space lock, since each node has its own lock
+ //may be too much protection, in future we can swtch back to a global lock
+
+ executor_type *exec_; //default executor_type for all async_opers/callbacks in channel
+ //for sending out local name_space change events
+ detail::name_space_change_notify<ns_type> ns_notifier_;
+
+ public:
+
+ hierarchical_name_space(executor_type *e) :
+ ns_root_(new trie_node(id_trait::root_token, NULL)),
+ exec_(e),
+ ns_notifier_(*this) {
+ }
+
+ ~hierarchical_name_space() {
+ //shared_ptr make sure delete notifier (so its named_in/outs are deleted)
+ //before deleting name space
+ }
+
+ executor_type * get_exec(void) {
+ return exec_;
+ }
+
+ /**
+ * Local operations on name_space:
+ * bind/unbind named_in/out
+ * for each bind/unbind, 3 kinds of changes made:
+ * 1. binding to the trie data structure
+ * 2. binding between named_out and named_in
+ * 3. exported ids/names exposed to external channels
+ *
+ * specialty with hierarchical name_space because of wildcard in names/ids:
+ * 1> bindings (out<->in):
+ * . bind with all "opposite" names/wildcards in trie at the node with this id
+ * . bind with all upper level "opposite" wildcards, no matter this is wildcard or not
+ * . if this is wildcard, bind with all lower level "opposite" names
+ * 2> external ids (exposed): wildcard names do hide/unhide :
+ * . a wildcard name will hide/unhide all "same-side" names in trie at lower levels
+ * . any names can be hiden by a "same-side" wildcard at upper level
+ *
+ * normal algorithms:
+ * 1. traverse the trie to the destination node:
+ * . if some path or node do not exist, create them
+ * . check if it is hidden by a upper level wildcard at the same side
+ * . check if it can bind to upper level wildcards at opposite, add bindings
+ * 2. at the destination node:
+ * . check if it can bind to opposite names and wildcards at this node, add bindings
+ * . if it is not a wildcard, and not hidden, simply check if it should be "notify"ed
+ * . if this is a wildcard:
+ * . check if it can bind to all lower level "opposite" names, add bindings
+ * . check if it is not hidden, it hide/unhide all "same-side" names at lower level;
+ * call notify_external to hide hidden names.
+ * . if is not hidden call notify on it; if hidden, call notify_internal
+ */
+ ///
+ void bind_named_out(name *n)
+ {
+ bool wildcard = id_trait::wildcard_name(n->id_);
+ bool hidden = false;
+
+ /**
+ * traverse from root to node designated by n->id_
+ */
+ trie_node *node = ns_root_.get();
+ for (size_t i=0; i<n->id_.size(); i++) {
+ if (n->id_[i] == id_trait::wildcard_token && i == (n->id_.size()-1))
+ break;
+ ///check if it is hidden by a upper level wildcard at the same side
+ if (!hidden && name::exported_name(n)) {
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ if (!node->outs_w_.empty()) {
+ for(typename std::list<name *>::iterator iter = node->outs_w_.begin();
+ iter != node->outs_w_.end() && !hidden; iter++) {
+ name *m = (*iter);
+ if (name::exported_name(m))
+ hidden = true;
+ }
+ }
+ }
+ ///check if it can bind to upper level wildcards at opposite, add bindings
+ {
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ if (!node->ins_w_.empty()) {
+ for(typename std::list<name *>::iterator iter = node->ins_w_.begin();
+ iter != node->ins_w_.end(); iter++) {
+ name *m = (*iter);
+ ///setup bindings
+ if (name::scope_checking(n,m)) {
+ n->bind(m);
+ m->bind(n);
+ platform::log("bind_named_out/bind : "+id_trait::id_to_string(n->id_)+"->"+id_trait::id_to_string(m->id_));
+ }
+ }
+ }
+ }
+ ///if some path or node do not exist, create them
+ {
+ typename synch_policy::scoped_lock lock(node->trie_lock_);
+ typename std::map<token_type, trie_node *>::iterator iter = node->children.find(n->id_[i]);
+ if (iter == node->children.end()) {
+ trie_node *cnd = new trie_node (n->id_[i], node);
+ node->children[n->id_[i]] = cnd;
+ node = cnd;
+ }
+ else
+ node = iter->second;
+ }
+ }
+
+ /// now we have reached the node for this n->id_ (without trailing wildcard)
+ //
+ ///check if it can bind to opposite names , add bindings
+ ///binding to opposite wildcard at this node already handled during traverse
+ {
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ if (!node->ins_.empty()) {
+ for(typename std::list<name *>::iterator iter = node->ins_.begin();
+ iter != node->ins_.end(); iter++) {
+ name *m = (*iter);
+ ///setup bindings
+ if (name::scope_checking(n,m)) {
+ n->bind(m);
+ m->bind(n);
+ platform::log("bind_named_out/bind : "+id_trait::id_to_string(n->id_)+"->"+
+ id_trait::id_to_string(m->id_));
+ }
+ }
+ }
+
+ if (!node->ins_w_.empty()) {
+ for(typename std::list<name *>::iterator iter = node->ins_w_.begin();
+ iter != node->ins_w_.end(); iter++) {
+ name *m = (*iter);
+ ///setup bindings
+ if (name::scope_checking(n,m)) {
+ n->bind(m);
+ m->bind(n);
+ platform::log("bind_named_out/bind : "+id_trait::id_to_string(n->id_)+"->"+
+ id_trait::id_to_string(m->id_));
+ }
+ }
+ }
+ }
+
+ if (!wildcard) {
+ /// for normal names
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ ///store in name_space
+ node->outs_.push_front(n);
+ lock.unlock();
+
+ ///notify
+ if(name::exported_name(n) && hidden)
+ ///if hidden, just notify internal peers
+ ns_notifier_.notify_internal(name::bind_out_ev, n);
+ else if(n->type_ == name::member_local)
+ ///notify all
+ ns_notifier_.notify(name::bind_out_ev, n);
+ }
+ else {
+ ///for wildcards
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ ///store in name_space
+ node->outs_w_.push_front(n);
+ lock.unlock();
+
+ /// bind to lower level opposite names
+ {
+ typename synch_policy::scoped_lock lock(node->trie_lock_);
+ for(typename std::map<token_type, trie_node *>::iterator iter = node->children.begin();
+ iter != node->children.end(); iter++)
+ bind_out_to_lower_ins(n, iter->second);
+ }
+
+ /// notify, and possibly hide lower level names
+ if (name::exported_name(n)) {
+ if(hidden)
+ ns_notifier_.notify_internal(name::bind_out_ev, n);
+ else {
+ ///at external interface, hide all "same-side" names at lower level,
+ ///starting from this node
+ update_children_out_exports (node, name::unbind_out_ev, false);
+ ns_notifier_.notify(name::bind_out_ev, n);
+ }
+ }
+ else if(n->type_ == name::member_local) {
+ ns_notifier_.notify(name::bind_out_ev, n);
+ }
+ }
+ }
+
+ ///
+ void unbind_named_out(name *n)
+ {
+ bool wildcard = id_trait::wildcard_name(n->id_);
+ bool hidden = false;
+
+ /**
+ * traverse from root to node designated by n->id_
+ */
+ trie_node *node = ns_root_.get();
+ for (size_t i=0; i<n->id_.size(); i++) {
+ if (n->id_[i] == id_trait::wildcard_token && i == (n->id_.size()-1))
+ break;
+ ///check if it is hidden by a upper level wildcard at the same side
+ if (!hidden && name::exported_name(n)) {
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ if (!node->outs_w_.empty()) {
+ for(typename std::list<name *>::iterator iter = node->outs_w_.begin();
+ iter != node->outs_w_.end() && !hidden; iter++) {
+ name *m = (*iter);
+ if (name::exported_name(m) && n != m)
+ hidden = true;
+ }
+ }
+ }
+ {
+ typename synch_policy::scoped_lock lock(node->trie_lock_);
+ typename std::map<token_type, trie_node *>::iterator iter = node->children.find(n->id_[i]);
+ if (iter == node->children.end()) {
+ platform::log("unbind_named_in: branch disappeared");
+ return;
+ }
+ node = iter->second;
+ }
+ }
+
+ /// now we have reached the node for this n->id_ (without trailing wildcard)
+
+ ///unbind all Out->In
+ //n->unbind_all();
+
+ ///del binding from name_space
+ if (!wildcard) {
+ /// for normal names
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ ///store in name_space
+ node->outs_.remove(n);
+ lock.unlock();
+
+ ///notify
+ if(name::exported_name(n) && hidden)
+ ///if hidden, just notify internal peers
+ ns_notifier_.notify_internal(name::unbind_out_ev, n);
+ else if(n->type_ == name::member_local)
+ ///notify all
+ ns_notifier_.notify(name::unbind_out_ev, n);
+ }
+ else {
+ ///for wildcards
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ ///store in name_space
+ node->outs_w_.remove(n);
+ lock.unlock();
+
+ /// notify, and possibly hide lower level names
+ if (name::exported_name(n)) {
+ if(hidden)
+ ns_notifier_.notify_internal(name::unbind_out_ev, n);
+ else {
+ ///at external interface, unhide all "same-side" names at lower level,
+ ///starting from this node
+ update_children_in_exports (node, name::bind_out_ev, false);
+ ns_notifier_.notify(name::unbind_out_ev, n);
+ }
+ }
+ else if(n->type_ == name::member_local) {
+ ns_notifier_.notify(name::unbind_out_ev, n);
+ }
+ }
+ }
+
+ ///
+ void bind_named_in(name *n)
+ {
+ bool wildcard = id_trait::wildcard_name(n->id_);
+ bool hidden = false;
+
+ /**
+ * traverse from root to node designated by n->id_
+ */
+ trie_node *node = ns_root_.get();
+ for (size_t i=0; i<n->id_.size(); i++) {
+ if (n->id_[i] == id_trait::wildcard_token && i == (n->id_.size()-1))
+ break;
+ ///check if it is hidden by a upper level wildcard at the same side
+ if (!hidden && name::exported_name(n)) {
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ if (!node->ins_w_.empty()) {
+ for(typename std::list<name *>::iterator iter = node->ins_w_.begin();
+ iter != node->ins_w_.end() && !hidden; iter++) {
+ name *m = (*iter);
+ if (name::exported_name(m))
+ hidden = true;
+ }
+ }
+ }
+ ///check if it can bind to upper level wildcards at opposite, add bindings
+ {
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ if (!node->outs_w_.empty()) {
+ for(typename std::list<name *>::iterator iter = node->outs_w_.begin();
+ iter != node->outs_w_.end(); iter++) {
+ name *m = (*iter);
+ ///setup bindings
+ if (name::scope_checking(m,n)) {
+ m->bind(n);
+ n->bind(m);
+ platform::log("bind_named_in/bind : "+id_trait::id_to_string(n->id_)+"->"+
+ id_trait::id_to_string(m->id_));
+ }
+ }
+ }
+ }
+ ///if some path or node do not exist, create them
+ {
+ typename synch_policy::scoped_lock lock(node->trie_lock_);
+ typename std::map<token_type, trie_node *>::iterator iter = node->children.find(n->id_[i]);
+ if (iter == node->children.end()) {
+ trie_node *cnd = new trie_node (n->id_[i], node);
+ node->children[n->id_[i]] = cnd;
+ node = cnd;
+ }
+ else
+ node = iter->second;
+ }
+ }
+
+ /// now we have reached the node for this n->id_ (without trailing wildcard)
+ //
+ ///check if it can bind to opposite names , add bindings
+ ///binding to opposite wildcards at this node already done during traverse
+ {
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ if (!node->outs_.empty()) {
+ for(typename std::list<name *>::iterator iter = node->outs_.begin();
+ iter != node->outs_.end(); iter++) {
+ name *m = (*iter);
+ ///setup bindings
+ if (name::scope_checking(m,n)) {
+ m->bind(n);
+ n->bind(m);
+ platform::log("bind_named_in/bind : "+id_trait::id_to_string(n->id_)+"->"+
+ id_trait::id_to_string(m->id_));
+ }
+ }
+ }
+ if (!node->outs_w_.empty()) { //if this is wildcard, this step alrady done during traverse
+ for(typename std::list<name *>::iterator iter = node->outs_w_.begin();
+ iter != node->outs_w_.end(); iter++) {
+ name *m = (*iter);
+ ///setup bindings
+ if (name::scope_checking(m,n)) {
+ m->bind(n);
+ n->bind(m);
+ platform::log("bind_named_in/bind : "+id_trait::id_to_string(n->id_)+"->"+
+ id_trait::id_to_string(m->id_));
+ }
+ }
+ }
+ }
+
+ if (!wildcard) {
+ /// for normal names
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ ///store in name_space
+ node->ins_.push_front(n);
+ lock.unlock();
+
+ ///notify
+ if(name::exported_name(n) && hidden)
+ ///if hidden, just notify internal peers
+ ns_notifier_.notify_internal(name::bind_in_ev, n);
+ else if(n->type_ == name::member_local)
+ ///notify all
+ ns_notifier_.notify(name::bind_in_ev, n);
+ }
+ else {
+ ///for wildcards
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ ///store in name_space
+ node->ins_w_.push_front(n);
+ lock.unlock();
+
+ /// bind to lower level opposite names
+ {
+ typename synch_policy::scoped_lock lock(node->trie_lock_);
+ for(typename std::map<token_type, trie_node *>::iterator iter = node->children.begin();
+ iter != node->children.end(); iter++)
+ bind_in_to_lower_outs(n, iter->second);
+ }
+
+ /// notify, and possibly hide lower level names
+ if (name::exported_name(n)) {
+ if(hidden)
+ ns_notifier_.notify_internal(name::bind_in_ev, n);
+ else {
+ ///at external interface, hide all "same-side" names at lower level,
+ ///starting from this node
+ update_children_in_exports (node, name::unbind_in_ev, false);
+ ns_notifier_.notify(name::bind_in_ev, n);
+ }
+ }
+ else if(n->type_ == name::member_local) {
+ ns_notifier_.notify(name::bind_in_ev, n);
+ }
+ }
+ }
+
+ ///
+ void unbind_named_in(name *n)
+ {
+ bool wildcard = id_trait::wildcard_name(n->id_);
+ bool hidden = false;
+
+ /**
+ * traverse from root to node designated by n->id_
+ */
+ trie_node *node = ns_root_.get();
+ for (size_t i=0; i<n->id_.size(); i++) {
+ if (n->id_[i] == id_trait::wildcard_token && i == (n->id_.size()-1))
+ break;
+ ///check if it is hidden by a upper level wildcard at the same side
+ if (!hidden && name::exported_name(n)) {
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ if (!node->ins_w_.empty()) {
+ for(typename std::list<name *>::iterator iter = node->ins_w_.begin();
+ iter != node->ins_w_.end() && !hidden; iter++) {
+ name *m = (*iter);
+ if (name::exported_name(m) && n != m)
+ hidden = true;
+ }
+ }
+ }
+ {
+ typename synch_policy::scoped_lock lock(node->trie_lock_);
+ typename std::map<token_type, trie_node *>::iterator iter = node->children.find(n->id_[i]);
+ if (iter == node->children.end()) {
+ platform::log("unbind_named_in: branch disappeared");
+ return;
+ }
+ node = iter->second;
+ }
+ }
+
+ /// now we have reached the node for this n->id_ (without trailing wildcard)
+
+ ///unbind all Out->In
+ //n->unbind_all();
+
+ ///del binding from name_space
+ if (!wildcard) {
+ /// for normal names
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ ///store in name_space
+ node->ins_.remove(n);
+ lock.unlock();
+
+ ///notify
+ if(name::exported_name(n) && hidden)
+ ///if hidden, just notify internal peers
+ ns_notifier_.notify_internal(name::unbind_in_ev, n);
+ else if(n->type_ == name::member_local)
+ ///notify all
+ ns_notifier_.notify(name::unbind_in_ev, n);
+ }
+ else {
+ ///for wildcards
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ ///store in name_space
+ node->ins_w_.remove(n);
+ lock.unlock();
+
+ /// notify, and possibly hide lower level names
+ if (name::exported_name(n)) {
+ if(hidden)
+ ns_notifier_.notify_internal(name::unbind_in_ev, n);
+ else {
+ ///at external interface, unhide all "same-side" names at lower level,
+ ///starting from this node
+ id_type id = n->id_;
+ update_children_in_exports (node, name::bind_in_ev, false);
+ ns_notifier_.notify(name::unbind_in_ev, n);
+ }
+ }
+ else if(n->type_ == name::member_local) {
+ ns_notifier_.notify(name::unbind_in_ev, n);
+ }
+ }
+ }
+
+ void bind_in_to_lower_outs(name *n, trie_node *node) {
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ if (!node->outs_.empty()) {
+ for(typename std::list<name *>::iterator iter = node->outs_.begin();
+ iter != node->outs_.end(); iter++) {
+ name *m = (*iter);
+ ///setup bindings
+ if (name::scope_checking(m,n)) {
+ m->bind(n);
+ n->bind(m);
+ platform::log("bind_in_to_lower_outs/bind : "+id_trait::id_to_string(n->id_)+"->"+
+ id_trait::id_to_string(m->id_));
+ }
+ }
+ }
+ if (!node->outs_w_.empty()) {
+ for(typename std::list<name *>::iterator iter = node->outs_w_.begin();
+ iter != node->outs_w_.end(); iter++) {
+ name *m = (*iter);
+ ///setup bindings
+ if (name::scope_checking(m,n)) {
+ m->bind(n);
+ n->bind(m);
+ platform::log("bind_in_to_lower_outs/bind : "+id_trait::id_to_string(n->id_)+"->"+
+ id_trait::id_to_string(m->id_));
+ }
+ }
+ }
+ lock.unlock();
+ //recursively update children
+ typename synch_policy::scoped_lock lock2(node->trie_lock_);
+ for(typename std::map<token_type, trie_node*>::iterator iter = node->children.begin();
+ iter != node->children.end(); iter++) {
+ bind_in_to_lower_outs (n, iter->second);
+ }
+ }
+
+ void bind_out_to_lower_ins(name *m, trie_node *node) {
+ typename synch_policy::scoped_lock lock(node->bind_lock_);
+ if (!node->ins_.empty()) {
+ for(typename std::list<name *>::iterator iter = node->ins_.begin();
+ iter != node->ins_.end(); iter++) {
+ name *n = (*iter);
+ ///setup bindings
+ if (name::scope_checking(m,n)) {
+ m->bind(n);
+ n->bind(m);
+ platform::log("bind_out_to_lower_ins/bind : "+id_trait::id_to_string(n->id_)+"->"+
+ id_trait::id_to_string(m->id_));
+ }
+ }
+ }
+ if (!node->ins_w_.empty()) {
+ for(typename std::list<name *>::iterator iter = node->ins_w_.begin();
+ iter != node->ins_w_.end(); iter++) {
+ name *n = (*iter);
+ ///setup bindings
+ if (name::scope_checking(m,n)) {
+ m->bind(n);
+ n->bind(m);
+ platform::log("bind_out_to_lower_ins/bind : "+id_trait::id_to_string(n->id_)+"->"+
+ id_trait::id_to_string(m->id_));
+ }
+ }
+ }
+ lock.unlock();
+ //recursively update children
+ typename synch_policy::scoped_lock lock2(node->trie_lock_);
+ for(typename std::map<token_type, trie_node*>::iterator iter = node->children.begin();
+ iter != node->children.end(); iter++) {
+ bind_out_to_lower_ins (m, iter->second);
+ }
+ }
+
+ void update_children_out_exports (trie_node *node,
+ typename name::binding_event oper, bool update_wildcard) {
+ bool send2remote = false;
+
+ typename synch_policy::scoped_lock lock1(node->bind_lock_);
+ ///if encounter wildcard, stop going deeper
+ if (update_wildcard && !node->outs_w_.empty()) {
+ name *m;
+ for(typename std::list<name *>::iterator iter = node->outs_w_.begin();
+ iter != node->outs_w_.end(); iter++) {
+ m = *iter;
+ if (name::exported_name(m)) {
+ send2remote = true;
+ if (oper == name::unbind_out_ev)
+ m->unbind_all_external();
+ }
+ }
+ if (send2remote) {
+ ns_notifier_.notify_external(oper, m);
+ return;
+ }
+ }
+ if (!node->outs_.empty()) {
+ name *m;
+ for(typename std::list<name *>::iterator iter = node->outs_.begin();
+ iter != node->outs_.end(); iter++) {
+ m = *iter;
+ if (name::exported_name(m)) {
+ send2remote = true;
+ if (oper == name::unbind_out_ev)
+ m->unbind_all_external();
+ }
+ }
+ if (send2remote) {
+ ns_notifier_.notify_external(oper, m);
+ }
+ }
+ lock1.unlock();
+
+ //recursively update children
+ typename synch_policy::scoped_lock lock2(node->trie_lock_);
+ for(typename std::map<token_type, trie_node*>::iterator iter = node->children.begin();
+ iter != node->children.end(); iter++) {
+ update_children_out_exports (iter->second, oper, true);
+ }
+ }
+
+ void update_children_in_exports (trie_node *node,
+ typename name::binding_event oper, bool update_wildcard) {
+ bool send2remote = false;
+
+ typename synch_policy::scoped_lock lock1(node->bind_lock_);
+ ///if encounter wildcard, stop going deeper
+ if (update_wildcard && !node->ins_w_.empty()) {
+ name *m;
+ for(typename std::list<name *>::iterator iter = node->ins_w_.begin();
+ iter != node->ins_w_.end(); iter++) {
+ m = *iter;
+ if (name::exported_name(m)) {
+ send2remote = true;
+ if (oper == name::unbind_in_ev)
+ m->unbind_all_external();
+ }
+ }
+ if (send2remote) {
+ ns_notifier_.notify_external(oper, m);
+ return;
+ }
+ }
+ if (!node->ins_.empty()) {
+ name *m;
+ for(typename std::list<name *>::iterator iter = node->ins_.begin();
+ iter != node->ins_.end(); iter++) {
+ m = *iter;
+ if (name::exported_name(m)) {
+ send2remote = true;
+ if (oper == name::unbind_in_ev)
+ m->unbind_all_external();
+ }
+ }
+ if (send2remote) {
+ ns_notifier_.notify_external(oper, m);
+ }
+ }
+ lock1.unlock();
+
+ //recursively update children
+ typename synch_policy::scoped_lock lock2(node->trie_lock_);
+ for(typename std::map<token_type, trie_node*>::iterator iter = node->children.begin();
+ iter != node->children.end(); iter++) {
+ update_children_in_exports (iter->second, oper, true);
+ }
+ }
+
+ /**
+ * 3. name_space queries
+ */
+
+ template <typename Predicate>
+ void bound_ids_for_in(Predicate p, std::vector<id_type> &ids)
+ {
+ bound_ids_for_in_recursive(p, ids, ns_root_.get());
+ }
+
+ template <typename Predicate>
+ void bound_ids_for_in_recursive(Predicate p, std::vector<id_type> &ids, trie_node *node)
+ {
+ name *m;
+ typename synch_policy::scoped_lock lock1(node->bind_lock_);
+ ///if encounter wildcard, stop going deeper
+ if (!node->ins_w_.empty()) {
+ for(typename std::list<name *>::iterator iter = node->ins_w_.begin();
+ iter != node->ins_w_.end(); iter++) {
+ m = *iter;
+ if (p(m)) {
+ ids.push_back(m->id_);
+ return;
+ }
+ }
+ }
+ if (!node->ins_.empty()) {
+ for(typename std::list<name *>::iterator iter = node->ins_.begin();
+ iter != node->ins_.end(); iter++) {
+ m = *iter;
+ if (p(m)) {
+ ids.push_back(m->id_);
+ break;
+ }
+ }
+ }
+ lock1.unlock();
+
+ //recursively update children
+ typename synch_policy::scoped_lock lock2(node->trie_lock_);
+ for(typename std::map<token_type, trie_node*>::iterator iter = node->children.begin();
+ iter != node->children.end(); iter++) {
+ bound_ids_for_in_recursive(p, ids, iter->second);
+ }
+ }
+
+ template <typename Predicate>
+ void bound_ids_for_out(Predicate p, std::vector<id_type> &ids)
+ {
+ bound_ids_for_out_recursive(p, ids, ns_root_.get());
+ }
+
+ template <typename Predicate>
+ void bound_ids_for_out_recursive(Predicate p, std::vector<id_type> &ids, trie_node *node)
+ {
+ name *m;
+ typename synch_policy::scoped_lock lock1(node->bind_lock_);
+ ///if encounter wildcard, stop going deeper
+ if (!node->outs_w_.empty()) {
+ for(typename std::list<name *>::iterator iter = node->outs_w_.begin();
+ iter != node->outs_w_.end(); iter++) {
+ m = *iter;
+ if (p(m)) {
+ ids.push_back(m->id_);
+ return;
+ }
+ }
+ }
+ if (!node->outs_.empty()) {
+ for(typename std::list<name *>::iterator iter = node->outs_.begin();
+ iter != node->outs_.end(); iter++) {
+ m = *iter;
+ if (p(m)) {
+ ids.push_back(m->id_);
+ break;
+ }
+ }
+ }
+ lock1.unlock();
+
+ //recursively update children
+ typename synch_policy::scoped_lock lock2(node->trie_lock_);
+ for(typename std::map<token_type, trie_node*>::iterator iter = node->children.begin();
+ iter != node->children.end(); iter++) {
+ bound_ids_for_out_recursive(p, ids, iter->second);
+ }
+ }
+ };
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/name_spaces/linear_id_trait.def
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/name_spaces/linear_id_trait.def 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,60 @@
+//
+// linear_id_trait.def
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include "name.def"
+
+#define DEFINE_NULL_SYS_IDS \
+ DEFINE_SCOPE_TABLE \
+ null_id id_trait<null_id>::channel_conn_msg = null_id(); \
+ null_id id_trait<null_id>::channel_disconn_msg = null_id(); \
+ null_id id_trait<null_id>::init_subscription_info_msg = null_id(); \
+ null_id id_trait<null_id>::connection_ready_msg = null_id(); \
+ null_id id_trait<null_id>::subscription_info_msg = null_id(); \
+ null_id id_trait<null_id>::unsubscription_info_msg = null_id(); \
+ null_id id_trait<null_id>::publication_info_msg = null_id(); \
+ null_id id_trait<null_id>::unpublication_info_msg = null_id(); \
+ null_id id_trait<null_id>::app_msg_begin = null_id();
+
+ ///--- sys msg starts at 1000 ---
+ ///--- app msg starts at 2000 ---
+#define DEFINE_INT_SYS_IDS \
+ DEFINE_SCOPE_TABLE \
+ int id_trait<int>::channel_conn_msg=1000; \
+ int id_trait<int>::channel_disconn_msg=1001; \
+ int id_trait<int>::init_subscription_info_msg=1002; \
+ int id_trait<int>::connection_ready_msg=1003; \
+ int id_trait<int>::subscription_info_msg=1004; \
+ int id_trait<int>::unsubscription_info_msg=1005; \
+ int id_trait<int>::publication_info_msg=1006; \
+ int id_trait<int>::unpublication_info_msg=1007; \
+ int id_trait<int>::app_msg_begin=2000;
+
+/// definitions of system messages for string ids
+#define DEFINE_STRING_SYS_IDS \
+ DEFINE_SCOPE_TABLE \
+ string id_trait<string>::channel_conn_msg = "_channel_conn_msg_"; \
+ string id_trait<string>::channel_disconn_msg = "_channel_disconn_msg_"; \
+ string id_trait<string>::init_subscription_info_msg = "_init_subscription_info_msg_"; \
+ string id_trait<string>::connection_ready_msg = "_connection_ready_msg_"; \
+ string id_trait<string>::subscription_info_msg = "_subscription_info_msg_"; \
+ string id_trait<string>::unsubscription_info_msg = "_unsubscription_info_msg_"; \
+ string id_trait<string>::publication_info_msg = "_publication_info_msg_"; \
+ string id_trait<string>::unpublication_info_msg = "_unpublication_info_msg_";
+
+/// definitions of system messages for struct ids
+#define DEFINE_STRUCT_SYS_IDS \
+ DEFINE_SCOPE_TABLE \
+ struct_id id_trait<struct_id>::channel_conn_msg = {system_message, 1}; \
+ struct_id id_trait<struct_id>::channel_disconn_msg = {system_message, 2}; \
+ struct_id id_trait<struct_id>::init_subscription_info_msg = {system_message, 3}; \
+ struct_id id_trait<struct_id>::connection_ready_msg = {system_message, 4}; \
+ struct_id id_trait<struct_id>::subscription_info_msg = {system_message, 5}; \
+ struct_id id_trait<struct_id>::unsubscription_info_msg = {system_message, 6}; \
+ struct_id id_trait<struct_id>::publication_info_msg = {system_message, 7}; \
+ struct_id id_trait<struct_id>::unpublication_info_msg = {system_message, 8};

Added: sandbox/channel/boost/channel/name_spaces/linear_id_trait.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/name_spaces/linear_id_trait.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,259 @@
+//
+// linear_id_trait.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+
+#ifndef LINEAR_ID_TRAIT_HPP
+#define LINEAR_ID_TRAIT_HPP
+
+#include <sstream>
+#include <string>
+
+/**
+ * Here are the definitions related to linear name_space ids:
+ * 1> trait class for primitive id types: int, string,...
+ * 2> definitions of non-primitive id types: struct id,... and their traits
+ */
+
+namespace boost {
+ namespace channel {
+
+ ///no default definition for id trait; must explicitly define it for each id type
+ template<class id_type> class id_trait;
+
+ /**
+ * define null_id to avoid overhead for local port and signal
+ */
+ class null_id {
+ public:
+ bool operator==(const null_id &) const {
+ return false;
+ }
+ bool operator<(const null_id &) const {
+ return false;
+ }
+ bool operator!=(const null_id &) const {
+ return false;
+ }
+ };
+
+ /// trait class for null ids
+ template <>
+ class id_trait<null_id> {
+ public:
+ ///define system msgs
+ static null_id channel_conn_msg;
+ static null_id channel_disconn_msg;
+ static null_id init_subscription_info_msg;
+ static null_id connection_ready_msg;
+ static null_id subscription_info_msg;
+ static null_id unsubscription_info_msg;
+ static null_id publication_info_msg;
+ static null_id unpublication_info_msg;
+ static null_id app_msg_begin;
+
+ typedef null_id id_type;
+
+ ///need the comparisons for msg matching and map
+ static bool eq(const id_type &id1, const id_type &id2)
+ { return false;}
+ static bool lt(const id_type &id1, const id_type &id2)
+ { return false;}
+
+ //compiler doesnt allow references here
+ //static bool match(const id_type &id1, const id_type &id2)
+ static bool match(id_type id1, id_type id2)
+ { return false;}
+
+ //linear name_space dont support wildcard yet
+ static bool wildcard_name(const id_type &id) {
+ return false;
+ }
+
+ ///string representation of ids, for debugging
+ static std::string id_to_string(const id_type &id) {
+ return "null_id";
+ }
+
+ };
+
+ /// trait class for integer ids
+ template <>
+ class id_trait<int> {
+ public:
+ ///define system msgs
+ /*
+ enum sys_ids {
+ ///--- sys msg starts at 1000 ---
+ channel_conn_msg=1000,
+ channel_disconn_msg,
+ init_subscription_info_msg,
+ connection_ready_msg,
+ subscription_info_msg,
+ unsubscription_info_msg,
+ publication_info_msg,
+ unpublication_info_msg,
+ ///--- app msg starts at 2000 ---
+ app_msg_begin=2000
+ };
+ */
+ static int channel_conn_msg;
+ static int channel_disconn_msg;
+ static int init_subscription_info_msg;
+ static int connection_ready_msg;
+ static int subscription_info_msg;
+ static int unsubscription_info_msg;
+ static int publication_info_msg;
+ static int unpublication_info_msg;
+ static int app_msg_begin;
+
+ typedef int id_type;
+
+ ///need the comparisons for msg matching and map
+ static bool eq(const id_type &id1, const id_type &id2)
+ { return id1 == id2;}
+ static bool lt(const id_type &id1, const id_type &id2)
+ { return id1 < id2;}
+
+ //compiler doesnt allow references here
+ //static bool match(const id_type &id1, const id_type &id2)
+ static bool match(id_type id1, id_type id2)
+ { return id1 == id2;}
+
+ //linear name_space dont support wildcard yet
+ static bool wildcard_name(const id_type &id) {
+ return false;
+ }
+
+ ///string representation of ids, for debugging
+ static std::string id_to_string(const id_type &id) {
+ std::ostringstream os;
+ os << id;
+ return os.str();
+ }
+
+ };
+
+ /// trait class for string ids
+ template <>
+ class id_trait<std::string> {
+ public:
+ ///define system msgs
+
+ static std::string channel_conn_msg;
+ static std::string channel_disconn_msg;
+ static std::string init_subscription_info_msg;
+ static std::string connection_ready_msg;
+ static std::string subscription_info_msg;
+ static std::string unsubscription_info_msg;
+ static std::string publication_info_msg;
+ static std::string unpublication_info_msg;
+
+ typedef std::string id_type;
+
+ ///need the comparisons for msg matching and map
+ static bool eq(const std::string &id1, const std::string &id2)
+ { return id1 == id2;}
+ static bool lt(const std::string &id1, const std::string &id2)
+ { return id1 < id2;}
+
+ //compiler doesnt allow references here
+ //static bool match(const std::string &id1, const std::string &id2)
+ static bool match(std::string id1, std::string id2)
+ { return id1 == id2;}
+
+ //linear name_space dont support wildcard yet
+ static bool wildcard_name(const id_type &id) {
+ return false;
+ }
+
+ static std::string id_to_string(const std::string &id) {
+ return id;
+ }
+
+ };
+
+ /**
+ * definition of sample POD struct ids
+ */
+ ///ids have 2 fields: family and type
+ enum message_family {
+ system_message, application_message
+ };
+
+ struct struct_id {
+ message_family family;
+ int type;
+ bool operator<(const struct_id &id) const {
+ if (family < id.family || (family == id.family && type < id.type))
+ return true;
+ return false;
+ }
+ bool operator==(const struct_id &id) const {
+ if (family == id.family && type == id.type)
+ return true;
+ return false;
+ }
+ bool operator!=(const struct_id &id) const {
+ if (family != id.family || type != id.type)
+ return true;
+ return false;
+ }
+ ///serializer for struct_id as id_type
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int version) {
+ ar & family & type;
+ }
+
+ };
+
+ /// trait class for sample POD struct ids
+ template<>
+ class id_trait<struct_id> {
+ public:
+ ///define system msgs
+
+ static struct_id channel_conn_msg;
+ static struct_id channel_disconn_msg;
+ static struct_id init_subscription_info_msg;
+ static struct_id connection_ready_msg;
+ static struct_id subscription_info_msg;
+ static struct_id unsubscription_info_msg;
+ static struct_id publication_info_msg;
+ static struct_id unpublication_info_msg;
+
+ typedef struct_id id_type;
+
+ ///need the comparisons for msg matching and map
+ static bool eq(const struct_id &id1, const struct_id &id2)
+ { return id1 == id2;}
+ static bool lt(const struct_id &id1, const struct_id &id2)
+ { return id1 < id2;}
+
+ //compiler doesnt allow references here
+ //static bool match(const struct_id &id1, const struct_id &id2)
+ static bool match(struct_id id1, struct_id id2)
+ { return id1 == id2;}
+
+ //linear name_space dont support wildcard yet
+ static bool wildcard_name(const id_type &id) {
+ return false;
+ }
+
+ static std::string id_to_string(const struct_id &id) {
+ std::ostringstream os;
+ os << "[Family:" << id.family << ", Type:" << id.type <<"]";
+ return os.str();
+ }
+ };
+ }
+}
+
+#include "linear_id_trait.def"
+
+#endif

Added: sandbox/channel/boost/channel/name_spaces/linear_name_space.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/name_spaces/linear_name_space.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,284 @@
+//
+// linear_name_space.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+
+#ifndef LINEAR_NAME_SPACE_HPP
+#define LINEAR_NAME_SPACE_HPP
+
+#include <map>
+#include <list>
+#include <algorithm>
+#include <boost/channel/name_spaces/linear_id_trait.hpp>
+#include <boost/channel/platforms/synch_policy.hpp>
+#include <boost/channel/name.hpp>
+#include <boost/channel/name_spaces/name_space_change_notify.hpp>
+
+namespace boost {
+ namespace channel {
+ /**
+ * linear_name_space: combo of simple linear space and associative space
+ * . simple linear space: name_matching = exact_match
+ * . assoc name space: name_matching = assoc/fuzzy/regex-based matching
+ * using stl map for linear name_space
+ */
+ template<typename idtype, typename executor_type, typename synchpolicy,
+ bool exact_match = true>
+ class linear_name_space {
+ public:
+ typedef idtype id_type;
+ typedef boost::channel::id_trait<id_type> id_trait;
+ typedef synchpolicy synch_policy;
+ typedef executor_type executor;
+ typedef typename synch_policy::platform platform;
+ //we dont care about In/Out operations here, just names and bindings
+ typedef boost::channel::name<id_type,executor_type,synch_policy> name;
+
+ private:
+ typedef linear_name_space<idtype,executor_type,synchpolicy,exact_match> ns_type;
+
+ struct ns_entry {
+ std::list<name *> outs_;
+ std::list<name *> ins_;
+ };
+
+ //name_space - pubsub table
+ std::map<id_type, ns_entry> ns_;
+ typename synch_policy::mutex ns_lock_;
+
+ executor_type *exec_; //default executor_type for all async_opers/callbacks in channel
+ //for sending out local name_space change events
+ detail::name_space_change_notify<ns_type> ns_notifier_;
+
+ public:
+
+ linear_name_space(executor_type *e) : exec_(e), ns_notifier_(*this) {
+ }
+
+ ~linear_name_space() {
+ typename synch_policy::scoped_lock lock(ns_lock_);
+ //clean up name_space structures
+ ns_.clear();
+ }
+
+ executor_type * get_exec(void) {
+ return exec_;
+ }
+
+ /**
+ * Local operations on Channel/Router name_space:
+ * bind/unbind named_in/out
+ * for each bind/unbind, 3 kinds of changes made:
+ * 1. binding to the name_space data structure
+ * 2. binding between named_out and named_in
+ * 3. exported ids exposed to external channels
+ */
+ ///
+ void bind_named_out(name *n)
+ {
+ typename synch_policy::scoped_lock lock(ns_lock_);
+
+ //add new binding to name_space
+ ns_entry &entry = ns_[n->id_]; //if first time, the entry will be added
+ if (std::find(entry.outs_.begin(), entry.outs_.end(), n) != entry.outs_.end())
+ return;
+
+ entry.outs_.push_front(n);
+
+ //platform::log("ns::bind_named_out name: "+id_trait::id_to_string(n->id_));
+
+ //bind Out->In
+ //using reverse_iterator, so that later-added names will be pushed to
+ //the front of bindings
+ if (exact_match) {
+ for(typename std::list<name *>::reverse_iterator iter=entry.ins_.rbegin();
+ iter != entry.ins_.rend(); iter++) {
+ name *m = (*iter);
+ if (name::scope_checking(n,m)) {
+ n->bind(m);
+ m->bind(n);
+ }
+ }
+ }
+ else { //assoc match
+ typename std::map<id_type, ns_entry>::iterator it = ns_.begin();
+ for (; it != ns_.end(); it++) {
+ //platform::log("ns::bind_named_in compare: "+id_trait::id_to_string(it->first));
+ if (id_trait::match(it->first, n->id_)) {
+ ns_entry &ent = it->second;
+ //bind Out->In
+ //using reverse_iterator, so that later-added names will be pushed to
+ //the front of bindings
+ for(typename std::list<name *>::reverse_iterator iter=ent.ins_.rbegin();
+ iter != ent.ins_.rend(); iter++) {
+ name *m = (*iter);
+ if (name::scope_checking(n,m)) {
+ n->bind(m);
+ m->bind(n);
+ }
+ }
+ }
+ }
+ }
+
+ //propagate name_space changes
+ lock.unlock();
+ if(n->type_ == name_base::member_local)
+ ns_notifier_.notify(name_base::bind_out_ev, n);
+ }
+
+ ///
+ void unbind_named_out(name *n)
+ {
+ typename synch_policy::scoped_lock lock(ns_lock_);
+
+ //del binding from name_space
+ ns_entry &entry = ns_[n->id_];
+ entry.outs_.remove(n);
+ //clean up
+ if (entry.outs_.empty() && entry.ins_.empty())
+ ns_.erase(n->id_);
+
+ //unbind all Out->In
+ //n->unbind_all();
+
+ //propagate name_space changes
+ lock.unlock();
+ if(n->type_ == name_base::member_local)
+ ns_notifier_.notify(name_base::unbind_out_ev, n);
+ }
+
+ ///
+ void bind_named_in(name *n)
+ {
+ typename synch_policy::scoped_lock lock(ns_lock_);
+
+ //add new binding to name_space
+ ns_entry &entry = ns_[n->id_]; //if first time, the entry will be added
+ if (std::find(entry.ins_.begin(), entry.ins_.end(), n) != entry.ins_.end())
+ return;
+
+ entry.ins_.push_front(n);
+
+ //platform::log("ns::bind_named_in name: "+id_trait::id_to_string(n->id_));
+
+ //bind Out->In
+ //using reverse_iterator, so that later-added names will be pushed to
+ //the front of bindings
+ if (exact_match) {
+ for(typename std::list<name *>::reverse_iterator iter=entry.outs_.rbegin();
+ iter != entry.outs_.rend(); iter++) {
+ name *m = (*iter);
+ if (name::scope_checking(m,n)) {
+ m->bind(n);
+ n->bind(m);
+ }
+ }
+ }
+ else {
+ typename std::map<id_type, ns_entry>::iterator it = ns_.begin();
+ for (; it != ns_.end(); it++) {
+ //platform::log("ns::bind_named_in compare: "+id_trait::id_to_string(it->first));
+ if (id_trait::match(it->first, n->id_)) {
+ ns_entry &ent = it->second;
+ //bind Out->In
+ //using reverse_iterator, so that later-added names will be pushed to
+ //the front of bindings
+ for(typename std::list<name *>::reverse_iterator iter=ent.outs_.rbegin();
+ iter != ent.outs_.rend(); iter++) {
+ name *m = (*iter);
+ if (name::scope_checking(m,n)) {
+ m->bind(n);
+ n->bind(m);
+ }
+ }
+ }
+ }
+ }
+
+ //propagate name_space changes
+ lock.unlock();
+ if(n->type_ == name_base::member_local)
+ ns_notifier_.notify(name_base::bind_in_ev, n);
+ }
+
+ ///
+ void unbind_named_in(name *n)
+ {
+ typename synch_policy::scoped_lock lock(ns_lock_);
+
+ //del binding from name_space
+ ns_entry &entry = ns_[n->id_];
+ entry.ins_.remove(n);
+ //clean up
+ if (entry.outs_.empty() && entry.ins_.empty())
+ ns_.erase(n->id_);
+
+ //unbind all Out->In
+ //n->unbind_all();
+
+ //propagate name_space changes
+ lock.unlock();
+ if(n->type_ == name_base::member_local)
+ ns_notifier_.notify(name_base::unbind_in_ev, n);
+ }
+
+ /**
+ * 3. name_space queries
+ */
+ template <typename Predicate>
+ void bound_ids_for_in(Predicate p, std::vector<id_type> &ids)
+ {
+ typename synch_policy::scoped_lock lock(ns_lock_);
+ for(typename std::map<id_type, ns_entry>::iterator iter = ns_.begin();
+ iter != ns_.end(); iter++) {
+ ns_entry &entry = iter->second;
+ if (entry.ins_.empty())
+ continue;
+
+ bool found = false;
+ for(typename std::list<name*>::iterator iter2 = entry.ins_.begin();
+ iter2 != entry.ins_.end() && !found; iter2++) {
+ name *n = (*iter2);
+ if (p(n)) {
+ found = true;
+ }
+ }
+ if (found)
+ ids.push_back(iter->first);
+ }
+ }
+
+ template <typename Predicate>
+ void bound_ids_for_out(Predicate p, std::vector<id_type> &ids)
+ {
+ typename synch_policy::scoped_lock lock(ns_lock_);
+ for(typename std::map<id_type, ns_entry>::iterator iter = ns_.begin();
+ iter != ns_.end(); iter++) {
+ ns_entry &entry = iter->second;
+ if (entry.outs_.empty())
+ continue;
+
+ bool found = false;
+ for(typename std::list<name*>::iterator iter2 = entry.outs_.begin();
+ iter2 != entry.outs_.end() && !found; iter2++) {
+ name *n = (*iter2);
+ if (p(n)) {
+ found = true;
+ }
+ }
+ if (found)
+ ids.push_back(iter->first);
+ }
+ }
+
+ };
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/name_spaces/name.def
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/name_spaces/name.def 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,18 @@
+//
+// name.def
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#define DEFINE_SCOPE_TABLE \
+short boost::channel::name_base::scope_checking_tbl_[][name_base::scope_number * name_base::member_number] = { \
+ {1, 0, 1, 0, 0, 0}, \
+ {0, 0, 0, 1, 0, 0}, \
+ {1, 0, 1, 1, 0, 0}, \
+ {0, 1, 1, 0, 0, 0}, \
+ {0, 0, 0, 0, 0, 0}, \
+ {0, 0, 0, 0, 0, 0} \
+};

Added: sandbox/channel/boost/channel/name_spaces/name_space_change_notify.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/name_spaces/name_space_change_notify.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,161 @@
+//
+// name_space_change_notify.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef NAME_SPACE_CHANGE_NOTIFY_HPP
+#define NAME_SPACE_CHANGE_NOTIFY_HPP
+
+#include <boost/shared_ptr.hpp>
+#include <boost/channel/named_in_out.hpp>
+#include <boost/channel/dispatchers/broadcast_dispatcher.hpp>
+#include <boost/channel/message.hpp>
+
+namespace boost {
+ namespace channel {
+ namespace detail {
+
+ template<typename name_space_type>
+ class name_space_change_notify {
+ typedef typename name_space_type::id_type id_type;
+ typedef typename name_space_type::id_trait id_trait;
+ typedef typename name_space_type::name name;
+ typedef boost::channel::named_out<name_space_type,
+ typename broadcast_dispatcher<name_space_type,
+ typename name_space_type::platform>::sender> named_out;
+ struct binding_notify {
+ named_out *bind_out, *unbind_out, *bind_in, *unbind_in;
+ };
+ binding_notify notify_[name_base::scope_number];
+ bool silent;
+ public:
+ name_space_change_notify(name_space_type & ns) {
+ silent = true;
+ for(int i=0;i<name_base::scope_number;i++) {
+ notify_[i].bind_out = new named_out(ns, (id_type)id_trait::publication_info_msg,(typename name::scope_type)i);
+ notify_[i].unbind_out = new named_out(ns, (id_type)id_trait::unpublication_info_msg,(typename name::scope_type)i);
+ notify_[i].bind_in = new named_out(ns, (id_type)id_trait::subscription_info_msg,(typename name::scope_type)i);
+ notify_[i].unbind_in = new named_out(ns, (id_type)id_trait::unsubscription_info_msg,(typename name::scope_type)i);
+ }
+ silent = false;
+ }
+
+ ~name_space_change_notify() {
+ silent = true;
+ for(int i=0;i<name::scope_number;i++) {
+ delete notify_[i].bind_out;
+ delete notify_[i].unbind_out;
+ delete notify_[i].bind_in;
+ delete notify_[i].unbind_in;
+ }
+ silent = false;
+ }
+
+ ///notify all related (local/remote/global) named_ins/outs about changes
+ void notify(typename name::binding_event op, name *n)
+ {
+ typename name_base::scope_type scope = n->scope_;
+ if(n->id_ == id_trait::publication_info_msg ||
+ n->id_ == id_trait::unpublication_info_msg ||
+ n->id_ == id_trait::subscription_info_msg ||
+ n->id_ == id_trait::unsubscription_info_msg) {
+ if(silent)
+ return;
+ scope = name::scope_local;
+ }
+ boost::shared_ptr<pubsub_info_msg_t<id_type> > sub(new pubsub_info_msg_t<id_type>());
+ sub->msg_types.push_back(n->id_);
+ named_out *no;
+ switch(op) {
+ case name::bind_out_ev:
+ no = notify_[scope].bind_out;
+ break;
+ case name::unbind_out_ev:
+ no = notify_[scope].unbind_out;
+ break;
+ case name::bind_in_ev:
+ no = notify_[scope].bind_in;
+ break;
+ case name::unbind_in_ev:
+ no = notify_[scope].unbind_in;
+ break;
+ default:
+ break;
+ }
+ no->send(sub);
+ }
+
+ ///just notify external (remote) named_ins/outs (at interface) about changes
+ void notify_external(typename name::binding_event op, name *n)
+ {
+ if (n->scope_ == name::scope_local) return;
+ //dont need to send sys_msgs pub/subs, interface has done all
+ if(n->id_ == id_trait::publication_info_msg ||
+ n->id_ == id_trait::unpublication_info_msg ||
+ n->id_ == id_trait::subscription_info_msg ||
+ n->id_ == id_trait::unsubscription_info_msg)
+ return;
+ boost::shared_ptr<pubsub_info_msg_t<id_type> > sub(new pubsub_info_msg_t<id_type>());
+ sub->msg_types.push_back(n->id_);
+ named_out *no;
+ switch(op) {
+ case name::bind_out_ev:
+ no = notify_[name::scope_remote].bind_out;
+ break;
+ case name::unbind_out_ev:
+ no = notify_[name::scope_remote].unbind_out;
+ break;
+ case name::bind_in_ev:
+ no = notify_[name::scope_remote].bind_in;
+ break;
+ case name::unbind_in_ev:
+ no = notify_[name::scope_remote].unbind_in;
+ break;
+ default:
+ break;
+ }
+ no->send(sub);
+ }
+
+ ///just notify internal (local) named_ins/outs about changes
+ void notify_internal(typename name::binding_event op, name *n)
+ {
+ if (n->scope_ == name::scope_remote) return;
+ if(silent) {
+ if(n->id_ == id_trait::publication_info_msg ||
+ n->id_ == id_trait::unpublication_info_msg ||
+ n->id_ == id_trait::subscription_info_msg ||
+ n->id_ == id_trait::unsubscription_info_msg)
+ return;
+ }
+ boost::shared_ptr<pubsub_info_msg_t<id_type> > sub(new pubsub_info_msg_t<id_type>());
+ sub->msg_types.push_back(n->id_);
+ named_out *no;
+ switch(op) {
+ case name::bind_out_ev:
+ no = notify_[name::scope_local].bind_out;
+ break;
+ case name::unbind_out_ev:
+ no = notify_[name::scope_local].unbind_out;
+ break;
+ case name::bind_in_ev:
+ no = notify_[name::scope_local].bind_in;
+ break;
+ case name::unbind_in_ev:
+ no = notify_[name::scope_local].unbind_in;
+ break;
+ default:
+ break;
+ }
+ no->send(sub);
+ }
+ };
+ }
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/name_spaces/null_name_space.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/name_spaces/null_name_space.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,41 @@
+//
+// null_name_space.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+
+#ifndef NULL_NAME_SPACE_HPP
+#define NULL_NAME_SPACE_HPP
+
+#include <boost/channel/name.hpp>
+
+namespace boost {
+ namespace channel {
+ /**
+ * null_name_space:
+ * convenience class for "unnamed" entities;
+ * no real functionalities; just for transferring type info
+ */
+ template<typename idtype, typename executor_type, typename synchpolicy,
+ bool exact_match = true>
+ class null_name_space {
+ public:
+ typedef idtype id_type;
+ typedef boost::channel::id_trait<id_type> id_trait;
+ typedef synchpolicy synch_policy;
+ typedef executor_type executor;
+ typedef typename synch_policy::platform platform;
+ //we dont care about In/Out operations here, just names and bindings
+ typedef boost::channel::name<id_type,executor_type,synch_policy> name;
+
+ void unbind_named_out(name *) {}
+ void unbind_named_in(name *) {}
+ };
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/named_in_out.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/named_in_out.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,374 @@
+//
+// named_in_out.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef NAMED_IN_OUT_HPP
+#define NAMED_IN_OUT_HPP
+
+#include <vector>
+#include <map>
+#include <iostream>
+
+namespace boost {
+ namespace channel {
+ /**
+ * named_out/named_in provides the basic functionality of out/in
+ * for use inside name_space, always use broadcast_dispatcher
+ */
+ template <
+ typename name_space,
+ typename dispatcher_sender_type
+ >
+ class named_out: public name_space::name,
+ public dispatcher_sender_type {
+ public:
+ typedef typename name_space::executor executor_type;
+ typedef typename name_space::id_type id_type;
+ typedef typename name_space::name name_type;
+ name_space * ch_;
+ executor_type *exe_;
+ named_out (name_space & ch,
+ id_type id,
+ typename name_type::scope_type scope = name_type::scope_global,
+ typename name_type::member_type type = name_type::member_local,
+ executor_type *e = NULL
+ ) :
+ name_space::name (id,scope,type),
+ dispatcher_sender_type(this,e!=NULL?e:ch.get_exec()),
+ ch_(&ch), exe_(e!=NULL?e:ch.get_exec()) {
+ ch_->bind_named_out(this);
+ }
+ template <typename binding_cb_type>
+ named_out (name_space & ch,
+ id_type id,
+ binding_cb_type cb,
+ typename name_type::scope_type scope = name_type::scope_global,
+ typename name_type::member_type type = name_type::member_local,
+ executor_type *e = NULL
+ ) :
+ name_space::name (id, scope, type, cb, e!=NULL?e:ch.get_exec()),
+ dispatcher_sender_type(this,e!=NULL?e:ch.get_exec()),
+ ch_(&ch), exe_(e!=NULL?e:ch.get_exec()) {
+ ch_->bind_named_out(this);
+ }
+ //unnamed named_out
+ named_out (executor_type *e = NULL) :
+ name_space::name (),
+ dispatcher_sender_type(this,e),
+ ch_(NULL), exe_(e) {
+ }
+ ~named_out () {
+ if (ch_ != NULL)
+ ch_->unbind_named_out(this);
+ }
+
+ //attach unnamed named_out to name space
+ void attach_name_space (name_space & ch,
+ id_type id,
+ typename name_type::scope_type scope = name_type::scope_global,
+ typename name_type::member_type type = name_type::member_local) {
+ this->set_name (id,scope,type);
+ ch_ = &ch;
+ ch_->bind_named_out(this);
+ }
+ template <typename binding_cb_type>
+ void attach_name_space (name_space & ch,
+ id_type id,
+ binding_cb_type cb,
+ typename name_type::scope_type scope = name_type::scope_global,
+ typename name_type::member_type type = name_type::member_local) {
+ this->set_name (id, scope, type, cb, exe_!=NULL?exe_:ch.get_exec()),
+ ch_ = &ch;
+ ch_->bind_named_out(this);
+ }
+ };
+
+ template <
+ typename name_space,
+ typename dispatcher_recver_type
+ >
+ class named_in : public name_space::name,
+ public dispatcher_recver_type {
+ public:
+ typedef typename name_space::executor executor_type;
+ typedef typename name_space::id_type id_type;
+ typedef typename name_space::name name_type;
+ name_space * ch_;
+ executor_type *exe_;
+ //asynch recvers constructor
+ template <typename recver_type,typename binding_cb_type>
+ named_in (name_space & ch,
+ id_type id,
+ recver_type rc,
+ binding_cb_type bc,
+ typename name_type::scope_type scope = name_type::scope_global,
+ typename name_type::member_type type = name_type::member_local,
+ executor_type *e = NULL
+ ) :
+ name_space::name (id,scope,type,bc, e!=NULL?e:ch.get_exec()),
+ dispatcher_recver_type(this, rc, e!=NULL?e:ch.get_exec()), ch_(&ch),
+ exe_(e!=NULL?e:ch.get_exec()) {
+ ch_->bind_named_in(this);
+ }
+ //asynch recvers constructor
+ template <typename recver_type>
+ named_in (name_space & ch,
+ id_type id,
+ recver_type rc,
+ typename name_type::scope_type scope = name_type::scope_global,
+ typename name_type::member_type type = name_type::member_local,
+ executor_type *e = NULL
+ ) :
+ name_space::name (id,scope,type),
+ dispatcher_recver_type(this, rc, e!=NULL?e:ch.get_exec()), ch_(&ch),
+ exe_(e!=NULL?e:ch.get_exec()) {
+ ch_->bind_named_in(this);
+ }
+ //synch/active recvers constructor
+ named_in (name_space & ch,
+ id_type id,
+ typename name_type::scope_type scope = name_type::scope_global,
+ typename name_type::member_type type = name_type::member_local,
+ executor_type *e = NULL
+ ) :
+ name_space::name (id,scope,type),
+ dispatcher_recver_type(this), ch_(&ch), exe_(e!=NULL?e:ch.get_exec()) {
+ ch_->bind_named_in(this);
+ }
+ //unnamed named_in
+ template <typename recver_type>
+ named_in (recver_type rc,
+ executor_type *e = NULL
+ ) :
+ name_space::name (),
+ dispatcher_recver_type(this, rc, e),
+ ch_(NULL), exe_(e) {
+ }
+ ~named_in () {
+ if (ch_ != NULL)
+ ch_->unbind_named_in(this);
+ }
+ //
+ template <typename binding_cb_type>
+ void attach_name_space (name_space & ch,
+ id_type id,
+ binding_cb_type bc,
+ typename name_type::scope_type scope = name_type::scope_global,
+ typename name_type::member_type type = name_type::member_local
+ ) {
+ if (exe_ == NULL) exe_ = ch.get_exec();
+ this->set_name (id,scope,type,bc, exe_),
+ ch_ = &ch;
+ ch_->bind_named_in(this);
+ (dispatcher_recver_type*) this->set_exe(exe_);
+ }
+ //
+ void attach_name_space (name_space & ch,
+ id_type id,
+ typename name_type::scope_type scope = name_type::scope_global,
+ typename name_type::member_type type = name_type::member_local
+ ) {
+ if (exe_ == NULL) exe_ = ch.get_exec();
+ this->set_name (id,scope,type);
+ ch_ = &ch;
+ ch_->bind_named_in(this);
+ (dispatcher_recver_type*) this->set_exe(exe_);
+ }
+ };
+
+ /**
+ * named_out_bundle/named_in_bundle or named_pub/named_sub
+ * no binding callbacks installed
+ */
+ template <
+ typename name_space,
+ typename dispatcher_sender_type
+ >
+ class named_out_bundle {
+ public:
+ typedef typename name_space::id_type id_type;
+ typedef typename name_space::id_trait id_trait;
+ typedef typename name_space::executor executor_type;
+ typedef typename name_space::synch_policy synch_policy;
+ typedef boost::channel::named_out<name_space,dispatcher_sender_type> named_out;
+ public:
+ named_out_bundle(name_space & ch,
+ typename named_out::member_type type = named_out::member_local,
+ executor_type *e = NULL) :
+ ch_(ch), type_(type), exec_(e!=NULL?e:ch.get_exec()) {
+ }
+ ~named_out_bundle() {
+ for(typename std::map<id_type, named_out*>::iterator iter=named_outs_.begin();
+ iter != named_outs_.end(); iter++)
+ delete iter->second;
+ }
+ int get_ids(std::vector<id_type> &ids) {
+ for(typename std::map<id_type, named_out*>::iterator iter=named_outs_.begin();
+ iter != named_outs_.end(); iter++)
+ ids.push_back(iter->first);
+ return ids.size();
+ }
+ bool bound(id_type & id) {
+ typename std::map<id_type, named_out*>::iterator iter = named_outs_.find(id);
+ if (iter != named_outs_.end()) {
+ return iter->second->num_bindings() > 0;
+ }
+ return false;
+ }
+ named_out * find(id_type & id) {
+ typename std::map<id_type, named_out*>::iterator iter = named_outs_.find(id);
+ if (iter != named_outs_.end()) {
+ return iter->second;
+ }
+ return NULL;
+ }
+ named_out * find_match(id_type & id) {
+ for(typename std::map<id_type, named_out*>::iterator iter = named_outs_.begin();
+ iter != named_outs_.end(); iter++)
+ if(id_trait::match(iter->first, id)) {
+ return iter->second;
+ }
+ return NULL;
+ }
+ void bind(std::vector<std::pair<id_type,typename named_out::scope_type> > & ids) {
+ for(typename std::vector<id_type>::iterator iter=ids.begin();iter != ids.end(); iter++) {
+ bind(iter->first, iter->second);
+ }
+ }
+ bool bind(id_type & id, typename named_out::scope_type scope = named_out::scope_global) {
+ if (named_outs_.find(id) == named_outs_.end()) {
+ named_outs_[id] = new named_out(ch_, id, scope, type_, exec_);
+ return true;
+ }
+ return false;
+ }
+ bool unbind(id_type & id) {
+ typename std::map<id_type, named_out*>::iterator iter = named_outs_.find(id);
+ if (iter != named_outs_.end()) {
+ delete iter->second;
+ named_outs_.erase(iter);
+ return true;
+ }
+ return false;
+ }
+ void unbind_all(void) {
+ for(typename std::map<id_type, named_out*>::iterator iter=named_outs_.begin();
+ iter != named_outs_.end(); iter++)
+ delete iter->second;
+ named_outs_.clear();
+ }
+ private:
+ name_space & ch_;
+ typename named_out::member_type type_;
+ executor_type *exec_;
+ std::map<id_type, named_out*> named_outs_;
+ };
+
+ template <
+ typename name_space,
+ typename dispatcher_recver_type
+ >
+ class named_in_bundle {
+ public:
+ typedef typename name_space::synch_policy synch_policy;
+ typedef typename name_space::id_type id_type;
+ typedef typename name_space::id_trait id_trait;
+ typedef typename name_space::executor executor_type;
+ typedef boost::channel::named_in<name_space,dispatcher_recver_type> named_in;
+ private:
+ struct named_in_creator_base {
+ virtual named_in* create(name_space & ch, id_type &id,
+ typename named_in::scope_type scope,
+ typename named_in::member_type t,
+ executor_type *e) = 0;
+ virtual ~named_in_creator_base() {}
+ };
+ template <typename recver_type>
+ struct named_in_creator: public named_in_creator_base {
+ recver_type recver_;
+ named_in_creator(recver_type rc): recver_(rc) {}
+ named_in* create(name_space & ch, id_type &id,
+ typename named_in::scope_type scope,
+ typename named_in::member_type t,
+ executor_type *e) {
+ return new named_in(ch,id,recver_,scope,t,e);
+ }
+ };
+ name_space & ch_;
+ typename named_in::member_type type_;
+ executor_type *exec_;
+ std::map<id_type, named_in*> named_ins_;
+ named_in_creator_base *creator_;
+ public:
+ template <typename recver_type>
+ named_in_bundle(name_space & ch, recver_type rc,
+ typename named_in::member_type type = named_in::member_local,
+ executor_type *e = NULL) :
+ ch_(ch), type_(type), exec_(e!=NULL?e:ch.get_exec()), creator_(new named_in_creator<recver_type>(rc)) {
+ }
+ ~named_in_bundle() {
+ for(typename std::map<id_type, named_in*>::iterator iter=named_ins_.begin();
+ iter != named_ins_.end(); iter++)
+ delete iter->second;
+ delete creator_;
+ }
+ int get_ids(std::vector<id_type> &ids) {
+ for(typename std::map<id_type, named_in*>::iterator iter=named_ins_.begin();
+ iter != named_ins_.end(); iter++)
+ ids.push_back(iter->first);
+ return ids.size();
+ }
+ named_in * find(id_type & id) {
+ typename std::map<id_type, named_in*>::iterator iter = named_ins_.find(id);
+ if (iter != named_ins_.end()) {
+ return iter->second;
+ }
+ return NULL;
+ }
+ named_in * find_match(id_type & id) {
+ for(typename std::map<id_type, named_in*>::iterator iter = named_ins_.begin();
+ iter != named_ins_.end(); iter++)
+ if(id_trait::match(iter->first, id)) {
+ return iter->second;
+ }
+ return NULL;
+ }
+ void bind(std::vector<std::pair<id_type,typename named_in::scope_type> > & ids) {
+ for(typename std::vector<std::pair<id_type,typename named_in::scope_type> >::iterator iter=ids.begin();
+ iter != ids.end(); iter++) {
+ bind(iter->first, iter->second);
+ }
+ }
+ bool bind(id_type & id, typename named_in::scope_type scope = named_in::scope_global) {
+ if (named_ins_.find(id) == named_ins_.end()) {
+ named_ins_[id] = creator_->create(ch_, id, scope, type_, exec_);
+ return true;
+ }
+ return false;
+ }
+ bool unbind(id_type & id) {
+ typename std::map<id_type, named_in*>::iterator iter = named_ins_.find(id);
+ if (iter != named_ins_.end()) {
+ delete iter->second;
+ named_ins_.erase(iter);
+ return true;
+ }
+ return false;
+ }
+ void unbind_all(void) {
+ for(typename std::map<id_type, named_in*>::iterator iter=named_ins_.begin();
+ iter != named_ins_.end(); iter++)
+ delete iter->second;
+ named_ins_.clear();
+ }
+ };
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/peer.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/peer.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,82 @@
+//
+// peer.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef PEER_HPP
+#define PEER_HPP
+
+#include <string>
+#include <boost/shared_ptr.hpp>
+
+namespace boost {
+ namespace channel {
+
+ template<typename> class connection;
+
+ template<typename id_type>
+ class peer_type {
+ public:
+ typedef boost::channel::connection<id_type> connection;
+ enum type {
+ local_peer = 0, remote_peer
+ };
+ enum role {
+ undefined_role, active_role, //i start connection setup process
+ passive_role,
+ //i wait for others to connect
+ };
+
+ void bind_peer(peer_type *p, role r, connection *c) {
+ peer_ = p;
+ role_ = r;
+ conn_ = c;
+ }
+ virtual void unbind() {
+ peer_ = 0;
+ role_ = undefined_role;
+ conn_ = 0;
+ }
+ //channel or stream should call release to disconn and cleanup
+ void release(void) {
+ if (conn_ != NULL)
+ delete conn_; //connection destructor responsible for deleting all
+ }
+
+ peer_type() :
+ peer_(0), role_(undefined_role), conn_(0) {
+ }
+ virtual ~peer_type() {
+ }
+
+ std::pair<type, std::string> peer_get_info(void) {
+ return peer_->get_info();
+ }
+ void peer_send(id_type id, shared_ptr<void> msg) {
+ peer_->send(id, msg);
+ }
+
+ //stream should override get_info to provide transport info (e.g. host/port..)
+ virtual std::pair<type, std::string> get_info(void) {
+ std::pair<type, std::string> info;
+ info.first = local_peer;
+ info.second = "";
+ return info;
+ }
+
+ //concrete peer types (streams, interface) should override this
+ virtual void send(id_type id, shared_ptr<void> msg) = 0;
+
+ peer_type *peer_;
+ role role_;
+ connection *conn_;
+ };
+
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/platforms/boost_platform.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/platforms/boost_platform.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,43 @@
+//
+// boost_platform.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_PLATFORM_HPP
+#define BOOST_PLATFORM_HPP
+
+#include <iostream>
+#include <string>
+#include <boost/thread.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/channel/platforms/null_mutex.hpp>
+#include <boost/channel/platforms/null_condition.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+namespace boost {
+ namespace channel {
+
+ class boost_platform {
+ public:
+ //synch primitive
+ typedef detail::null_mutex null_mutex;
+ typedef detail::null_condition null_condition;
+ //typedef boost::mutex mutex;
+ typedef boost::recursive_mutex mutex;
+ typedef boost::condition condition;
+ //timeout
+ typedef boost::posix_time::time_duration timeout_type;
+ //log
+ static void log(std::string info) {
+ std::cout << "log << " << info << " >>" << std::endl;
+ }
+ };
+
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/platforms/null_condition.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/platforms/null_condition.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,59 @@
+//
+// null_condition.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_CHANNEL_NULL_CONDITION_HPP
+#define BOOST_CHANNEL_NULL_CONDITION_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+#include <boost/thread.hpp>
+#include <boost/utility.hpp>
+
+namespace boost {
+ namespace channel {
+ namespace detail {
+
+ class null_condition: private boost::noncopyable {
+ public:
+ null_condition() {
+ }
+ ~null_condition() {
+ }
+
+ void notify_one() {
+ }
+ void notify_all() {
+ }
+
+ template<typename L>
+ void wait(L& lock) {
+ }
+
+ template<typename L, typename Pr>
+ void wait(L& lock, Pr pred) {
+ }
+
+ template<typename L>
+ bool timed_wait(L& lock, const xtime& xt) {
+ return false;
+ }
+
+ template<typename L, typename Pr>
+ bool timed_wait(L& lock, const xtime& xt, Pr pred) {
+ return false;
+ }
+
+ };
+
+ } // namespace detail
+ } // namespace channel
+} // namespace boost
+
+#endif

Added: sandbox/channel/boost/channel/platforms/null_mutex.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/platforms/null_mutex.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,71 @@
+//
+// null_mutex.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_CHANNEL_NULL_MUTEX_HPP
+#define BOOST_CHANNEL_NULL_MUTEX_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/utility.hpp>
+
+namespace boost {
+ namespace channel {
+ namespace detail {
+
+ template <typename Mutex>
+ class null_scoped_lock : private noncopyable
+ {
+ public:
+ typedef Mutex mutex_type;
+
+ explicit null_scoped_lock(Mutex& mx, bool initially_locked=true)
+ {
+ }
+ ~null_scoped_lock()
+ {
+ }
+
+ void lock()
+ {
+ }
+ void unlock()
+ {
+ }
+
+ bool locked() const { return false; }
+ operator const void*() const { return 0; }
+
+ private:
+ };
+
+ class null_mutex
+ : private boost::noncopyable
+ {
+ public:
+ typedef null_scoped_lock<null_mutex> scoped_lock;
+
+ // Constructor.
+ null_mutex()
+ {
+ }
+
+ // Destructor.
+ ~null_mutex()
+ {
+ }
+
+ };
+
+ } // namespace detail
+ } // namespace channel
+} // namespace boost
+
+#endif

Added: sandbox/channel/boost/channel/platforms/synch_policy.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/platforms/synch_policy.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,40 @@
+//
+// synch_policy.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SYNCH_POLICY_HPP
+#define SYNCH_POLICY_HPP
+
+#include <boost/channel/platforms/boost_platform.hpp>
+
+namespace boost {
+ namespace channel {
+
+ template<typename platform_t>
+ class null_synch {
+ public:
+ typedef platform_t platform;
+ typedef typename platform_t::null_mutex mutex;
+ typedef typename platform_t::null_condition condition;
+ typedef typename mutex::scoped_lock scoped_lock;
+ };
+
+ template <typename platform_t>
+ class mt_synch {
+ public:
+ typedef platform_t platform;
+ typedef typename platform_t::mutex mutex;
+ typedef typename platform_t::condition condition;
+ typedef typename mutex::scoped_lock scoped_lock;
+ };
+
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/pub_sub.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/pub_sub.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,92 @@
+//
+// pub_sub.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef PUB_SUB_HPP
+#define PUB_SUB_HPP
+
+#include <vector>
+//#include <boost/channel/named_in_out.hpp>
+
+namespace boost {
+ namespace channel {
+
+ /**
+ * the following 2 classes are convenience high level API classes
+ * for end uers to use; to support publish/subscribe model
+ */
+ template<typename name_space, typename dispatcher_sender_type>
+ class publisher: public named_out_bundle<name_space, dispatcher_sender_type> {
+ typedef boost::channel::named_out_bundle<name_space, dispatcher_sender_type> named_out_bundle;
+ typedef typename name_space::id_type id_type;
+ typedef typename named_out_bundle::named_out named_out;
+ public:
+ publisher(name_space & ch,
+ typename named_out::member_type type = named_out::member_local) :
+ named_out_bundle(ch, type) {
+ }
+ void publish(std::vector<std::pair<id_type,typename named_out::scope_type> > & ids) {
+ this->bind(ids);
+ }
+ bool publish(id_type & id, typename named_out::scope_type scope = named_out::scope_global) {
+ return this->bind(id, scope);
+ }
+ bool unpublish(id_type & id) {
+ return this->unbind(id);
+ }
+
+ //-- the following are API borrowed from dispatcher --
+ template <typename user_msg_type>
+ void send(id_type & id, user_msg_type *msg) {
+ named_out *no = find(id);
+ if (no != NULL)
+ no->send(msg);
+ }
+ template <typename user_msg_type, typename deleter>
+ void send(id_type & id, user_msg_type *msg, deleter deler) {
+ named_out *no = find(id);
+ if (no != NULL)
+ no->send(msg,deler);
+ }
+ template <typename user_msg_type>
+ void send(id_type & id, boost::shared_ptr<user_msg_type> msg) {
+ named_out *no = find(id);
+ if (no != NULL)
+ no->send(msg);
+ }
+ };
+
+ template <
+ typename name_space,
+ typename dispatcher_recver_type
+ >
+ class subscriber: public named_in_bundle<name_space,dispatcher_recver_type> {
+ typedef typename name_space::id_type id_type;
+ typedef boost::channel::named_in_bundle<name_space,dispatcher_recver_type> named_in_bundle;
+ typedef typename named_in_bundle::named_in named_in;
+ public:
+ template <typename recver_type>
+ subscriber(name_space & ch, recver_type rc,
+ typename named_in::member_type type = named_in::member_local) :
+ named_in_bundle(ch, rc, type) {
+ }
+ void subscribe(std::vector<std::pair<id_type,typename named_in::scope_type> > & ids) {
+ this->bind(ids);
+ }
+ bool subscribe(id_type & id, typename named_in::scope_type scope = named_in::scope_global) {
+ return this->bind(id,scope);
+ }
+ bool unsubscribe(id_type & id) {
+ return this->unbind(id);
+ }
+ };
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/queues/bounded_queue.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/queues/bounded_queue.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,88 @@
+//
+// bounded_queue.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOUNDED_QUEUE_HPP
+#define BOUNDED_QUEUE_HPP
+
+#include <deque>
+
+namespace boost {
+ namespace channel {
+
+ /**
+ * size bounded queue:
+ * . when queue is full, senders will be blocked
+ * . when queue is empty, retrievers will be blocked
+ */
+ template<typename elem_type, typename synch_policy, typename platform>
+ class bounded_que {
+ public:
+ typedef typename platform::timeout_type timeout_type;
+ typename synch_policy::mutex lock_;
+ typename synch_policy::condition not_full_;
+ typename synch_policy::condition not_empty_;
+ int num_blocked_putter;
+ int num_blocked_getter;
+ std::deque<elem_type> data_;
+ size_t max_sz_;
+ timeout_type put_timeout_;
+ timeout_type sett_timeout_;
+ enum def_sz_type {def_sz = 100};
+ bounded_que(int s = def_sz): max_sz_(s) {
+ num_blocked_putter = 0;
+ num_blocked_getter = 0;
+ }
+ void set_max_que_sz(size_t ms) {max_sz_ = ms;}
+ size_t get_max_que_sz(void) {return max_sz_;}
+ /*
+ void set_timeout(timeout_type to);
+ timeout_type get_timeout(void);
+ */
+ bool empty() {
+ typename synch_policy::scoped_lock lock(lock_);
+ return data_.empty();
+ }
+ bool full() {
+ typename synch_policy::scoped_lock lock(lock_);
+ return data_.size() >= max_sz_;
+ }
+ size_t size() {
+ typename synch_policy::scoped_lock lock(lock_);
+ return data_.size();
+ }
+ void put(elem_type & e) {
+ typename synch_policy::scoped_lock lock(lock_);
+ while (data_.size() >= max_sz_) {
+ num_blocked_putter++;
+ not_full_.wait(lock);
+ num_blocked_putter--;
+ }
+ data_.push_back(e);
+ if (num_blocked_getter > 0)
+ not_empty_.notify_one();
+ }
+ void get(elem_type & e) {
+ typename synch_policy::scoped_lock lock(lock_);
+ while (data_.empty()) {
+ num_blocked_getter++;
+ not_empty_.wait(lock);
+ num_blocked_getter--;
+ }
+ e = data_.front();
+ data_.pop_front();
+ if (num_blocked_putter > 0)
+ not_full_.notify_one();
+ }
+ };
+
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/queues/dropping_queue.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/queues/dropping_queue.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,67 @@
+//
+// dropping_queue.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef DROPPING_QUEUE_HPP
+#define DROPPING_QUEUE_HPP
+
+#include <deque>
+
+namespace boost {
+ namespace channel {
+
+ /**
+ * droppined queue: after reaching que size limit, old msgs will be dropped to give
+ * space to new msgs
+ */
+ template<typename elem_type, typename synch_policy, typename platform>
+ class dropping_que {
+ public:
+ typename synch_policy::mutex lock_;
+ std::deque<elem_type> data_;
+ size_t max_sz_;
+ enum def_sz_type {
+ def_sz = 100
+ };
+ dropping_que(int s = def_sz) :
+ max_sz_(s) {
+ }
+ bool empty() {
+ typename synch_policy::scoped_lock lock(lock_);
+ return data_.empty();
+ }
+ size_t size() {
+ typename synch_policy::scoped_lock lock(lock_);
+ return data_.size();
+ }
+ void set_max_que_sz(size_t ms) {
+ max_sz_ = ms;
+ }
+ size_t get_max_que_sz(void) {
+ return max_sz_;
+ }
+ void put(elem_type & e) {
+ typename synch_policy::scoped_lock lock(lock_);
+ if (data_.size() >= max_sz_)
+ data_.pop_front(); //remove old data
+ data_.push_back(e);
+ }
+ void get(elem_type & e) {
+ typename synch_policy::scoped_lock lock(lock_);
+ if (!data_.empty()) {
+ e = data_.front();
+ data_.pop_front();
+ }
+ }
+ };
+
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/queues/flow_controlled_queue.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/queues/flow_controlled_queue.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,31 @@
+//
+// flow_controlled_queue.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef FLOW_CONTROLLED_QUEUE_HPP
+#define FLOW_CONTROLLED_QUEUE_HPP
+
+#include <deque>
+
+namespace boost {
+ namespace channel {
+
+ /**
+ * flow controled queue: follow the design of ACE Message_Queue:
+ * 1. flow is controlled thru high/low water marks
+ * 2. support priorities of enque and deque
+ */
+ template<typename elem_type, typename synch_policy, typename timeout_type>
+ class flow_controlled_que {
+ public:
+ };
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/queues/queues.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/queues/queues.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,19 @@
+//
+// queues.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef QUEUES_HPP
+#define QUEUES_HPP
+
+#include <boost/channel/queues/unbounded_queue.hpp>
+#include <boost/channel/queues/bounded_queue.hpp>
+#include <boost/channel/queues/dropping_queue.hpp>
+//#include <boost/channel/queues/timed_queue.hpp>
+//#include <boost/channel/queues/flow_controlled_queue.hpp>
+
+#endif

Added: sandbox/channel/boost/channel/queues/timed_queue.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/queues/timed_queue.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,32 @@
+//
+// timed_queue.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef TIMED_QUEUE_HPP
+#define TIMED_QUEUE_HPP
+
+#include <deque>
+
+namespace boost {
+ namespace channel {
+
+ /**
+ * timed queue: msgs will be dropped after waiting in queue for some time
+ * following JavaSpace in its use of "Lease" on entries in space, when
+ * lease expires, the entry is removed
+ */
+ template<typename elem_type, typename synch_policy, typename timeout_type>
+ class timed_que {
+ public:
+ };
+
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/queues/unbounded_queue.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/queues/unbounded_queue.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,51 @@
+//
+// unbounded_queue.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef UNBOUNDED_QUEUE_HPP
+#define UNBOUNDED_QUEUE_HPP
+
+#include <deque>
+
+namespace boost {
+ namespace channel {
+
+ /**
+ * the simplest msg_que: unbounded size
+ */
+ template<typename elem_type, typename synch_policy, typename platform>
+ class unbounded_que {
+ public:
+ std::deque<elem_type> data_;
+ typename synch_policy::mutex lock_;
+ bool empty() {
+ typename synch_policy::scoped_lock lock(lock_);
+ return data_.empty();
+ }
+ size_t size() {
+ typename synch_policy::scoped_lock lock(lock_);
+ return data_.size();
+ }
+ void put(elem_type & e) {
+ typename synch_policy::scoped_lock lock(lock_);
+ data_.push_back(e);
+ }
+ void get(elem_type & e) {
+ typename synch_policy::scoped_lock lock(lock_);
+ if (!data_.empty()) {
+ e = data_.front();
+ data_.pop_front();
+ }
+ }
+ };
+
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/streams/asio_connector_async.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/streams/asio_connector_async.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,174 @@
+//
+// asio_connector_async.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_CONNECTOR_ASYNC_HPP
+#define ASIO_CONNECTOR_ASYNC_HPP
+
+#include <string>
+#include <list>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/asio.hpp>
+
+using boost::asio::ip::tcp;
+
+namespace boost {
+ namespace channel {
+ class asio_connector_async;
+
+ class conn_handler_base {
+ public:
+ virtual boost::shared_ptr<void> handle(asio_connector_async *conn,
+ boost::shared_ptr<tcp::socket> sock, bool active) = 0;
+ virtual ~conn_handler_base() {
+ }
+ };
+ template<typename conn_handler_type>
+ class conn_handler: public conn_handler_base {
+ public:
+ conn_handler(conn_handler_type h) :
+ handler_(h) {
+ }
+ boost::shared_ptr<void> handle(asio_connector_async *conn,
+ boost::shared_ptr<tcp::socket> sock_conn, bool active) {
+ return handler_(conn, sock_conn, active);
+ }
+ private:
+ conn_handler_type handler_;
+ };
+
+ class asio_connector_async {
+ public:
+ //need add locks to protect these, since they are touched by both
+ //io_service thread (main) and thread calling shutdown
+ std::list<boost::shared_ptr<void> > streams_;
+ std::list<boost::shared_ptr<tcp::acceptor> > acceptors_;
+
+ size_t num_streams(void) {
+ return streams_.size();
+ }
+
+ void close_stream(boost::shared_ptr<void> s) {
+ streams_.remove(s);
+ }
+
+ void shutdown(void) {
+ std::cout << "close acceptors..." << std::endl;
+ for (std::list<boost::shared_ptr<tcp::acceptor> >::iterator iter0 =
+ acceptors_.begin(); iter0 != acceptors_.end(); iter0++) {
+ (*iter0)->close(); //close acceptors
+ }
+ std::cout << "close streams..." << std::endl;
+ for (std::list<boost::shared_ptr<void> >::iterator iter =
+ streams_.begin(); iter != streams_.end(); iter++) {
+ iter->reset(); //delete streams and connections & interfaces
+ }
+ std::cout << "finish shutdown..." << std::endl;
+ }
+
+ asio_connector_async(boost::asio::io_service& io_service) :
+ io_service_(io_service) {
+ }
+ ~asio_connector_async() {
+ std::cout << "~asio_connector_async..." << std::endl;
+ }
+
+ //publish a local channel at specific port and accept remote conn
+ template<typename sock_conn_handler>
+ void async_accept(int port, sock_conn_handler hndl) {
+ boost::shared_ptr<conn_handler_base> handler(new conn_handler<
+ sock_conn_handler> (hndl));
+ tcp::endpoint endpoint(tcp::v4(), port);
+ boost::shared_ptr<tcp::acceptor> acceptor(new tcp::acceptor(
+ io_service_, endpoint));
+ acceptors_.push_back(acceptor);
+ boost::shared_ptr<tcp::socket> sock(new tcp::socket(io_service_));
+ acceptor->async_accept(*sock, boost::bind(
+ &asio_connector_async::handle_accept, this, acceptor, handler,
+ sock, boost::asio::placeholders::error));
+ }
+
+ void handle_accept(boost::shared_ptr<tcp::acceptor> acceptor,
+ boost::shared_ptr<conn_handler_base> handler, boost::shared_ptr<
+ tcp::socket> sock, const boost::system::error_code& error) {
+ if (!error) {
+ boost::shared_ptr<void> stream = handler->handle(this, sock, false);
+ streams_.push_back(stream);
+ boost::shared_ptr<tcp::socket> new_sock(
+ new tcp::socket(io_service_));
+ acceptor->async_accept(*new_sock, boost::bind(
+ &asio_connector_async::handle_accept, this, acceptor,
+ handler, new_sock, boost::asio::placeholders::error));
+ }
+ }
+
+ //asynchronously connect a local channel to a remote channel (at <host, port>)
+ template<typename sock_conn_handler>
+ void async_connect(std::string host, std::string port,
+ sock_conn_handler hndl) {
+ tcp::resolver resolver(io_service_);
+ tcp::resolver::query query(host, port);
+ tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
+ tcp::endpoint endpoint = *endpoint_iterator;
+
+ boost::shared_ptr<tcp::socket> sock(new tcp::socket(io_service_));
+ boost::shared_ptr<conn_handler_base> handler(new conn_handler<
+ sock_conn_handler> (hndl));
+ sock->async_connect(endpoint, boost::bind(
+ &asio_connector_async::handle_connect, this, sock, handler,
+ boost::asio::placeholders::error, ++endpoint_iterator));
+ }
+
+ void handle_connect(boost::shared_ptr<tcp::socket> sock, boost::shared_ptr<
+ conn_handler_base> handler, const boost::system::error_code& error,
+ tcp::resolver::iterator endpoint_iterator) {
+ if (!error) {
+ boost::shared_ptr<void> stream = handler->handle(this, sock, true);
+ streams_.push_back(stream);
+ } else if (endpoint_iterator != tcp::resolver::iterator()) {
+ sock->close();
+ tcp::endpoint endpoint = *endpoint_iterator;
+ sock->async_connect(endpoint, boost::bind(
+ &asio_connector_async::handle_connect, this, sock, handler,
+ boost::asio::placeholders::error, ++endpoint_iterator));
+ }
+ }
+
+ //synchronously connect a local channel to a remote channel (at <host, port>)
+ template<typename sock_conn_handler>
+ void sync_connect(std::string host, std::string port,
+ sock_conn_handler hndl) {
+ tcp::resolver resolver(io_service_);
+ tcp::resolver::query query(host, port);
+ tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
+ tcp::resolver::iterator end;
+
+ boost::shared_ptr<tcp::socket> sock(new tcp::socket(io_service_));
+ boost::system::error_code error = boost::asio::error::host_not_found;
+ while (error && endpoint_iterator != end) {
+ sock->close();
+ sock->connect(*endpoint_iterator++, error);
+ }
+ if (error)
+ throw error;
+
+ boost::shared_ptr<void> stream = hndl(this, sock, true);
+ streams_.push_back(stream);
+ }
+
+ private:
+ boost::asio::io_service& io_service_;
+ };
+
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/streams/asio_connector_sync.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/streams/asio_connector_sync.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,70 @@
+//
+// asio_connector_sync.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_CONNECTOR_SYNC_HPP
+#define ASIO_CONNECTOR_SYNC_HPP
+
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/asio.hpp>
+#include <boost/channel/streams/asio_stream_sync.hpp>
+
+using boost::asio::ip::tcp;
+
+namespace boost {
+ namespace channel {
+
+ class asio_connector_sync {
+ private:
+ boost::asio::io_service& io_service_;
+ public:
+ asio_connector_sync(boost::asio::io_service& io_service) :
+ io_service_(io_service) {
+ }
+
+ void shutdown(void) {
+ }
+
+ //synchronously connect a local channel to a remote channel (at <host, port>)
+ asio_stream_sync* connect(std::string host, std::string port) {
+ tcp::resolver resolver(io_service_);
+ tcp::resolver::query query(host, port);
+ tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
+ tcp::resolver::iterator end;
+
+ asio_stream_sync *stream = new asio_stream_sync(io_service_, reg);
+ boost::asio::error error = boost::asio::error::host_not_found;
+ while (error && endpoint_iterator != end) {
+ stream->socket().close();
+ stream->socket().connect(*endpoint_iterator++,
+ boost::asio::assign_error(error));
+ }
+ if (error)
+ throw error;
+ stream->start();
+ return stream;
+ }
+
+ //synchronously accept:
+ //? how to continuously wait
+ //? how to wait on multi ports for multi channels
+ asio_stream_sync* accept(int port) {
+ tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port));
+ asio_stream_sync *stream = new asio_stream_sync(io_service_, reg);
+ a.accept(stream->socket());
+ stream->start();
+ return stream;
+ }
+ };
+
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/streams/asio_stream_async.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/streams/asio_stream_async.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,377 @@
+//
+// asio_stream_async.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_STREAM_ASYNC_HPP
+#define ASIO_STREAM_ASYNC_HPP
+
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <deque>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/function.hpp>
+#include <boost/asio.hpp>
+#include <boost/channel/peer.hpp>
+#include <boost/channel/message.hpp>
+#include <boost/channel/marshaler.hpp>
+#include <boost/channel/streams/asio_connector_async.hpp>
+
+namespace boost {
+ namespace channel {
+
+ /**
+ * asio_stream_async: a wrapper of socket, implement peer_type interface to be
+ * connected to channels
+ * msg serialization/deserialization is also done here: there are 2 parts:
+ * 1. serialization of ids: in id_trait files, for each id_type,
+ * a serialization function is defined
+ * 2. serialization of msg data: inside channel and among local peers, messages
+ * are passed by pointers; only when writing into and reading from
+ * external connections (such as sockets), serialization/deserialization
+ * is necessary. So all serialization is localized in "streams":
+ * diff ids could have diff msgs data structures, use
+ * marshaler_registry (a map or hash table to map
+ * ids to marshalers (the serialization functions)
+ */
+
+ void asio_stream_async_do_close(boost::shared_ptr<tcp::socket> sock) {
+ //close socket; called from io_service main thread
+ std::cout << "asio_stream_async_do_close enter" << std::endl;
+ sock->close();
+ std::cout << "asio_stream_async_do_close exit" << std::endl;
+ }
+
+ template<typename id_type, typename marshaler_registry>
+ class asio_stream_async: public peer_type<id_type> {
+ typedef boost::channel::peer_type<id_type> peer_type;
+ typedef message<id_type> msg_type;
+ typedef std::deque<msg_type> msg_que_type;
+
+ enum stream_state {
+ connecting, connected, disconnected
+ };
+
+ public:
+ asio_stream_async(asio_connector_async *conn, boost::shared_ptr<
+ boost::asio::ip::tcp::socket> sock, marshaler_registry &reg) :
+ socket_(sock), io_service_(sock->io_service()), mar_reg_(reg), conn_(
+ conn), state_(connected) {
+ }
+
+ ~asio_stream_async() {
+ std::cout << "asio_stream_async destructor enter..." << std::endl;
+ if (state_ == connected) {
+ state_ = disconnected;
+ peer_type::release();
+ io_service_.post(boost::bind(&asio_stream_async_do_close, socket_));
+ }
+ std::cout << "asio_stream_async destructor exit..." << std::endl;
+ }
+
+ //start reading from socket
+ void start() {
+ async_read(read_msg_, boost::bind(&asio_stream_async::handle_read,
+ this, boost::asio::placeholders::error));
+ }
+
+ //send a msg to socket and to remote peer
+ void send(id_type id, shared_ptr<void> msg) {
+ msg_type mdata(id, msg);
+ io_service_.post(boost::bind(&asio_stream_async::do_write, this, mdata));
+ }
+
+ std::pair<typename peer_type::type, std::string> get_info(void) {
+ std::pair<typename peer_type::type, std::string> info;
+ info.first = peer_type::remote_peer;
+ info.second = ""; //should get address info from sock_
+ return info;
+ }
+
+ void close() {
+ if (state_ == connected) {
+ state_ = disconnected;
+ peer_type::release();
+ io_service_.post(boost::bind(&asio_stream_async_do_close, socket_));
+ }
+ }
+
+ private:
+
+ void do_write(msg_type msg) {
+ bool write_in_progress = !write_msgs_.empty();
+ write_msgs_.push_back(msg);
+ if (!write_in_progress) {
+ async_write(write_msgs_.front(), boost::bind(
+ &asio_stream_async::handle_write, this,
+ boost::asio::placeholders::error));
+ }
+ }
+
+ template<typename handler_type>
+ void async_write(msg_type &m, handler_type handler) {
+ //marshal id
+ id_marshaler<id_type> *id_m = mar_reg_.get_id_marshaler();
+ id_m->marshal(m.id_, id_data_);
+ //marshal msg payload
+ msg_marshaler *m_m = mar_reg_.get_msg_marshaler(m.id_);
+ m_m->marshal(m.data_, msg_data_);
+ // format id length.
+ std::ostringstream id_len_stream;
+ id_len_stream << std::setw(size_length) << std::hex << id_data_.size();
+ if (!id_len_stream || id_len_stream.str().size() != size_length) {
+ // Something went wrong, inform the caller.
+ boost::system::error_code error(
+ boost::asio::error::invalid_argument);
+ io_service_.post(boost::bind(handler, error));
+ return;
+ }
+ id_len_ = id_len_stream.str();
+ // format msg length.
+ std::ostringstream msg_len_stream;
+ msg_len_stream << std::setw(size_length) << std::hex
+ << msg_data_.size();
+ if (!msg_len_stream || msg_len_stream.str().size() != size_length) {
+ // Something went wrong, inform the caller.
+ boost::system::error_code error(
+ boost::asio::error::invalid_argument);
+ io_service_.post(boost::bind(handler, error));
+ return;
+ }
+ msg_len_ = msg_len_stream.str();
+
+ std::vector<boost::asio::const_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(id_len_));
+ buffers.push_back(boost::asio::buffer(id_data_));
+ buffers.push_back(boost::asio::buffer(msg_len_));
+ buffers.push_back(boost::asio::buffer(msg_data_));
+ boost::asio::async_write(*socket_, buffers, handler);
+ }
+
+ void handle_write(const boost::system::error_code& error) {
+ if (!error) {
+ write_msgs_.pop_front();
+ if (!write_msgs_.empty()) {
+ async_write(write_msgs_.front(), boost::bind(
+ &asio_stream_async::handle_write, this,
+ boost::asio::placeholders::error));
+ }
+ } else {
+ close();
+ //conn_->close_stream(boost::shared_ptr<void>(this));
+ }
+ }
+
+ template<typename handler_type>
+ void async_read(msg_type &read_msg, handler_type handler) {
+ // read id length header.
+ void (asio_stream_async::*f)(const boost::system::error_code&,
+ msg_type&, boost::tuple<handler_type>)
+ = &asio_stream_async::handle_read_id_len;
+ boost::asio::async_read(*socket_, boost::asio::buffer(inbound_header_),
+ boost::bind(f, this, boost::asio::placeholders::error,
+ boost::ref(read_msg), boost::make_tuple(handler)));
+ }
+
+ template<typename handler_type>
+ void handle_read_id_len(const boost::system::error_code& e, msg_type& t,
+ boost::tuple<handler_type> handler) {
+ if (e) {
+ boost::get<0>(handler)(e);
+ } else {
+ // Determine id length
+ std::istringstream is(std::string(inbound_header_, size_length));
+ std::size_t inbound_data_size = 0;
+ if (!(is >> std::hex >> inbound_data_size)) {
+ // Header doesn't seem to be valid. Inform the caller.
+ boost::system::error_code error(
+ boost::asio::error::invalid_argument);
+ boost::get<0>(handler)(error);
+ return;
+ }
+
+ // Start an asynchronous call to read id data.
+ inbound_data_.resize(inbound_data_size);
+ void (asio_stream_async::*f)(const boost::system::error_code&,
+ msg_type&, boost::tuple<handler_type>)
+ = &asio_stream_async::handle_read_id_data;
+ boost::asio::async_read(*socket_,
+ boost::asio::buffer(inbound_data_), boost::bind(f, this,
+ boost::asio::placeholders::error, boost::ref(t),
+ handler));
+ }
+ }
+
+ template<typename handler_type>
+ void handle_read_id_data(const boost::system::error_code& e, msg_type& t,
+ boost::tuple<handler_type> handler) {
+ if (e) {
+ boost::get<0>(handler)(e);
+ } else {
+ // Extract the data structure from the data just received.
+ try {
+ std::string archive_data(&inbound_data_[0],
+ inbound_data_.size());
+ id_marshaler<id_type> *id_m = mar_reg_.get_id_marshaler();
+ id_m->demarshal(archive_data, t.id_);
+ } catch (std::exception& e) {
+ // Unable to decode data.
+ boost::system::error_code error(
+ boost::asio::error::invalid_argument);
+ boost::get<0>(handler)(error);
+ return;
+ }
+
+ // read msg length header.
+ void (asio_stream_async::*f)(const boost::system::error_code&,
+ msg_type&, boost::tuple<handler_type>)
+ = &asio_stream_async::handle_read_msg_len;
+ boost::asio::async_read(*socket_, boost::asio::buffer(
+ inbound_header_), boost::bind(f, this,
+ boost::asio::placeholders::error, boost::ref(t), handler));
+
+ }
+ }
+
+ template<typename handler_type>
+ void handle_read_msg_len(const boost::system::error_code& e, msg_type& t,
+ boost::tuple<handler_type> handler) {
+ if (e) {
+ boost::get<0>(handler)(e);
+ } else {
+ // Determine id length
+ std::istringstream is(std::string(inbound_header_, size_length));
+ std::size_t inbound_data_size = 0;
+ if (!(is >> std::hex >> inbound_data_size)) {
+ // Header doesn't seem to be valid. Inform the caller.
+ boost::system::error_code error(
+ boost::asio::error::invalid_argument);
+ boost::get<0>(handler)(error);
+ return;
+ }
+
+ // Start an asynchronous call to read id data.
+ inbound_data_.resize(inbound_data_size);
+ void (asio_stream_async::*f)(const boost::system::error_code&,
+ msg_type&, boost::tuple<handler_type>)
+ = &asio_stream_async::handle_read_msg_data;
+ boost::asio::async_read(*socket_,
+ boost::asio::buffer(inbound_data_), boost::bind(f, this,
+ boost::asio::placeholders::error, boost::ref(t),
+ handler));
+ }
+ }
+
+ template<typename handler_type>
+ void handle_read_msg_data(const boost::system::error_code& e, msg_type& t,
+ boost::tuple<handler_type> handler) {
+ if (e) {
+ boost::get<0>(handler)(e);
+ } else {
+ // Extract the data structure from the data just received.
+ try {
+ std::string archive_data(&inbound_data_[0],
+ inbound_data_.size());
+ msg_marshaler *m_m = mar_reg_.get_msg_marshaler(t.id_);
+ m_m->demarshal(archive_data, t.data_);
+ } catch (std::exception& e) {
+ // Unable to decode data.
+ boost::system::error_code error(
+ boost::asio::error::invalid_argument);
+ boost::get<0>(handler)(error);
+ return;
+ }
+
+ // Inform caller that data has been received ok.
+ boost::get<0>(handler)(e);
+ }
+ }
+
+ //finish reading a complete msg, forward to peer and read next one
+ void handle_read(const boost::system::error_code& error) {
+ if (!error) {
+ peer_send(read_msg_.id_, read_msg_.data_);
+ async_read(read_msg_, boost::bind(&asio_stream_async::handle_read,
+ this, boost::asio::placeholders::error));
+ } else {
+ close();
+ //conn_->close_stream(boost::shared_ptr<void>(this));
+ }
+ }
+
+ /*
+ void do_close(boost::shared_ptr<tcp::socket> sock)
+ {
+ //close socket; called from io_service main thread
+ sock->close();
+ std::cout << "do_close called" << std::endl;
+ }
+ */
+
+ boost::shared_ptr<boost::asio::ip::tcp::socket> socket(void) {
+ return socket_;
+ }
+
+ private:
+ enum sz_len {
+ size_length = 8
+ };
+ boost::shared_ptr<boost::asio::ip::tcp::socket> socket_;
+ boost::asio::io_service& io_service_;
+ marshaler_registry &mar_reg_;
+ asio_connector_async *conn_;
+ stream_state state_;
+
+ //output data buffers
+ msg_que_type write_msgs_;
+ std::string id_len_;
+ std::string id_data_;
+ std::string msg_len_;
+ std::string msg_data_;
+
+ //input data buffers
+ char inbound_header_[size_length];
+ std::vector<char> inbound_data_;
+ msg_type read_msg_;
+ };
+
+ template<typename channel, typename marshaler_registry>
+ struct asio_bind_sock_chan {
+ typedef boost::shared_ptr<void> result_type;
+ typename channel::binder_type *binder_;
+ typedef boost::function1<typename channel::binder_type *,
+ boost::shared_ptr<tcp::socket> > call_back_t;
+ call_back_t binder_gen_;
+
+ asio_bind_sock_chan(call_back_t cb = 0) :
+ binder_(NULL), binder_gen_(cb) {
+ }
+ boost::shared_ptr<void> operator()(channel &chan, marshaler_registry &reg,
+ asio_connector_async *conn, boost::shared_ptr<tcp::socket> sock,
+ bool active) {
+ typedef typename channel::id_type id_type;
+ typedef asio_stream_async<id_type, marshaler_registry> asio_stream;
+ asio_stream *stream = new asio_stream(conn, sock, reg);
+ if (binder_gen_)
+ binder_ = binder_gen_(sock);
+ //should connect first, so that when stream starts(reading),
+ //peer channel is already connected and ready to forward msgs
+ connect(chan, stream, active,binder_);
+ stream->start(); //start reading from sock
+ return boost::shared_ptr<void>(stream);
+ }
+ };
+
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/streams/asio_stream_sync.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/streams/asio_stream_sync.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,213 @@
+//
+// asio_stream_sync.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_STREAM_SYNC_HPP
+#define ASIO_STREAM_SYNC_HPP
+
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <boost/asio.hpp>
+#include <boost/thread.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/channel/peer.hpp>
+#include <boost/channel/message.hpp>
+#include <boost/channel/marshaler.hpp>
+
+namespace boost {
+ namespace channel {
+
+ template<typename id_type, typename marshaler_registry>
+ class asio_stream_sync: public peer_type<id_type> {
+ typedef peer_type<id_type> peer_type;
+ typedef message<id_type> msg_type;
+
+ enum {
+ wait_time = 2
+ };
+
+ enum thr_state {
+ thr_running, thr_stopped
+ };
+
+ private:
+ enum sz_len {
+ size_length = 8
+ };
+ boost::asio::ip::tcp::socket socket_;
+ boost::asio::io_service& io_service_;
+ marshaler_registry &mar_reg_;
+ boost::thread *thr_;
+ thr_state thr_st_;
+
+ //output data buffers
+ std::string id_len_;
+ std::string id_data_;
+ std::string msg_len_;
+ std::string msg_data_;
+
+ //input data buffers
+ char inbound_header_[size_length];
+ std::vector<char> inbound_data_;
+ msg_type read_msg_;
+
+ public:
+ asio_stream_sync(boost::asio::io_service& io, marshaler_registry &reg) :
+ socket_(io), io_service_(io), mar_reg_(reg) {
+ }
+
+ boost::asio::ip::tcp::socket& socket() {
+ return socket_;
+ }
+
+ //start reading from socket
+ void start() {
+ //spawn a thread reading msgs from socket and forward them to local channel
+ thr_st_ = thr_running;
+ thr_ = new thread(boost::bind(&asio_stream_sync::recv, this));
+ }
+
+ //send a msg to socket and to remote peer
+ void send(id_type id, shared_ptr<void> msg) {
+ try {
+ //marshal id
+ id_marshaler<id_type> *id_m = mar_reg_.get_id_marshaler();
+ id_m->marshal(id, id_data_);
+ //marshal msg payload
+ msg_marshaler *m_m = mar_reg_.get_msg_marshaler(id);
+ m_m->marshal(msg, msg_data_);
+ // format id length.
+ std::ostringstream id_len_stream;
+ id_len_stream << std::setw(size_length) << std::hex
+ << id_data_.size();
+ if (!id_len_stream || id_len_stream.str().size() != size_length) {
+ // Something went wrong
+ boost::system::error_code err(
+ boost::asio::error::invalid_argument);
+ boost::system::system_error e(err);
+ boost::throw_exception(e);
+ }
+ id_len_ = id_len_stream.str();
+ // format msg length.
+ std::ostringstream msg_len_stream;
+ msg_len_stream << std::setw(size_length) << std::hex
+ << msg_data_.size();
+ if (!msg_len_stream || msg_len_stream.str().size() != size_length) {
+ // Something went wrong
+ boost::system::error_code err(
+ boost::asio::error::invalid_argument);
+ boost::system::system_error e(err);
+ boost::throw_exception(e);
+ }
+ msg_len_ = msg_len_stream.str();
+
+ std::vector<boost::asio::const_buffer> buffers;
+ buffers.push_back(boost::asio::buffer(id_len_));
+ buffers.push_back(boost::asio::buffer(id_data_));
+ buffers.push_back(boost::asio::buffer(msg_len_));
+ buffers.push_back(boost::asio::buffer(msg_data_));
+ boost::asio::write(socket_, buffers);
+ } catch (boost::system::error_code& e) {
+ std::cerr << e << "\n";
+ shutdown_wait();
+ } catch (std::exception& e) {
+ std::cerr << "Exception: " << e.what() << "\n";
+ shutdown_wait();
+ }
+ }
+
+ void recv(void) {
+ std::cerr << "recver thread active...\n";
+ try {
+ while (thr_st_ == thr_running) {
+ //--- read id ---
+ //1. read id len
+ boost::asio::read(socket_, boost::asio::buffer(inbound_header_));
+ std::istringstream
+ is(std::string(inbound_header_, size_length));
+ std::size_t inbound_data_size = 0;
+ if (!(is >> std::hex >> inbound_data_size)) {
+ // invalid id len
+ boost::system::error_code err(
+ boost::asio::error::invalid_argument);
+ boost::system::system_error e(err);
+ boost::throw_exception(e);
+ }
+ inbound_data_.resize(inbound_data_size);
+ //2. read id data
+ boost::asio::read(socket_, boost::asio::buffer(inbound_data_));
+ std::string archive_data(&inbound_data_[0],
+ inbound_data_.size());
+ id_marshaler<id_type> *id_m = mar_reg_.get_id_marshaler();
+ id_m->demarshal(archive_data, read_msg_.id_);
+ //--- read msg ---
+ //3. read msg len
+ boost::asio::read(socket_, boost::asio::buffer(inbound_header_));
+ std::istringstream
+ is(std::string(inbound_header_, size_length));
+ std::size_t inbound_data_size = 0;
+ if (!(is >> std::hex >> inbound_data_size)) {
+ // invalid msg len
+ boost::system::error_code err(
+ boost::asio::error::invalid_argument);
+ boost::system::system_error e(err);
+ boost::throw_exception(e);
+ }
+ inbound_data_.resize(inbound_data_size);
+ //4. read msg data
+ boost::asio::read(socket_, boost::asio::buffer(inbound_data_));
+ std::string archive_data(&inbound_data_[0],
+ inbound_data_.size());
+ msg_marshaler *m_m = mar_reg_.get_msg_marshaler(t.id_);
+ m_m->demarshal(archive_data, read_msg_.data_);
+
+ //5. forward to local channel
+ peer_send(read_msg_.id_, read_msg_.data_);
+ }
+ } catch (boost::system::error_code& e) {
+ std::cerr << e << "\n";
+ shutdown_wait();
+ } catch (std::exception& e) {
+ std::cerr << "Exception: " << e.what() << "\n";
+ shutdown_wait();
+ }
+
+ std::cerr << "recver thread exit...\n";
+ }
+
+ void shutdown_wait() {
+ if (thr_st_ == thr_running) {
+ //close socket
+ close();
+ }
+ thr_->join();
+ peer_type::release();
+ }
+
+ std::pair<typename peer_type::type, std::string> get_info(void) {
+ std::pair<typename peer_type::type, std::string> info;
+ info.first = peer_type::remote_peer;
+ info.second = ""; //should get address info from sock_
+ return info;
+ }
+
+ void close(void) {
+ //close socket
+ socket_->close();
+ }
+
+ };
+
+ }
+}
+
+#endif

Added: sandbox/channel/boost/channel/streams/shmem_stream.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/streams/shmem_stream.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,181 @@
+//
+// shmem_stream.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef SHMEM_STREAM_HPP
+#define SHMEM_STREAM_HPP
+
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <deque>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/interprocess/ipc/message_queue.hpp>
+#include <boost/channel/peer.hpp>
+#include <boost/channel/message.hpp>
+#include <boost/channel/marshaler.hpp>
+
+namespace boost {
+ namespace channel {
+
+ /**
+ * shmem_stream : a stream based on boost::interprocess shmem message queue
+ * contains a internal thread reading from shmem msg_que and forward to peer
+ */
+ template<typename id_type, typename marshaler_registry>
+ class shmem_stream: public peer_type<id_type> {
+ typedef boost::channel::peer_type<id_type> peer_type;
+ typedef message<id_type> msg_type;
+
+ enum {
+ wait_time = 2
+ };
+
+ enum q_f {
+ quit_flag = 0
+ };
+
+ enum thr_state {
+ thr_running, thr_stopped
+ };
+
+ public:
+ shmem_stream(bool active, const char *name, std::size_t max_num_msg,
+ std::size_t max_msg_size, marshaler_registry &reg) :
+ active_role_(active), q_name_(name), mar_reg_(reg) {
+ if (active) {
+ //active side create msg que in shared mem
+ send_q_name_ = q_name_ + "_a_2_p"; //active_to_passive
+ recv_q_name_ = q_name_ + "_p_2_a"; //passive_to_active
+ boost::interprocess::message_queue::remove(send_q_name_.c_str());
+ boost::interprocess::message_queue::remove(recv_q_name_.c_str());
+ std::cout << "Create mq: " << send_q_name_.c_str() << "\n";
+ std::cout << "Create mq: " << recv_q_name_.c_str() << "\n";
+ send_mq_ = new boost::interprocess::message_queue(
+ boost::interprocess::create_only, send_q_name_.c_str(),
+ max_num_msg, max_msg_size);
+ recv_mq_ = new boost::interprocess::message_queue(
+ boost::interprocess::create_only, recv_q_name_.c_str(),
+ max_num_msg, max_msg_size);
+ } else {
+ //passive side open only
+ send_q_name_ = q_name_ + "_p_2_a"; //active_to_passive
+ recv_q_name_ = q_name_ + "_a_2_p"; //passive_to_active
+ send_mq_ = new boost::interprocess::message_queue(
+ boost::interprocess::open_only, send_q_name_.c_str());
+ recv_mq_ = new boost::interprocess::message_queue(
+ boost::interprocess::open_only, recv_q_name_.c_str());
+ }
+ //spawn a thread reading msgs from msg_que and forward them to peer
+ thr_st_ = thr_running;
+ thr_ = new thread(boost::bind(&shmem_stream::recv, this));
+ }
+
+ ~shmem_stream() {
+ //shutdown thread properly
+ if (thr_st_ == thr_running)
+ shutdown_wait();
+ delete thr_;
+ delete send_mq_;
+ delete recv_mq_;
+ if (active_role_) {
+ boost::interprocess::message_queue::remove(send_q_name_.c_str());
+ boost::interprocess::message_queue::remove(recv_q_name_.c_str());
+ }
+ }
+
+ //send a msg to shmem msg_que and to remote peer
+ void send(id_type id, shared_ptr<void> msg) {
+ id_marshaler<id_type> *id_m = mar_reg_.get_id_marshaler();
+ id_m->marshal(id, id_data_);
+ msg_marshaler *m_m = mar_reg_.get_msg_marshaler(id);
+ m_m->marshal(msg, out_msg_data_);
+ int id_sz = id_data_.size();
+ int msg_sz = out_msg_data_.size();
+ //msg que internal already has lock protection
+ send_mq_->send(id_data_.c_str(), id_sz, 0);
+ send_mq_->send(out_msg_data_.c_str(), msg_sz, 0);
+ std::cerr << "send one msg...\n";
+ }
+
+ void recv(void) {
+ std::cerr << "shmem msg_que recver thread active...\n";
+ size_t recv_sz;
+ unsigned int pri;
+ //have to be max_msg_sz of msg_que; otherwise exception is thrown
+ size_t buf_sz = recv_mq_->get_max_msg_size();
+ boost::shared_ptr<char> buf(new char[buf_sz]);
+ while (thr_st_ == thr_running) {
+ recv_mq_->receive(buf.get(), buf_sz, recv_sz, pri);
+ if (recv_sz == sizeof(size_t) && *((size_t*) buf.get())
+ == quit_flag) {
+ thr_st_ = thr_stopped;
+ break;
+ }
+ std::string id_data(buf.get(), recv_sz);
+ id_marshaler<id_type> *id_m = mar_reg_.get_id_marshaler();
+ id_m->demarshal(id_data, read_msg_.id_);
+ recv_mq_->receive(buf.get(), buf_sz, recv_sz, pri);
+ if (recv_sz == sizeof(size_t) && *((size_t*) buf.get())
+ == quit_flag) {
+ thr_st_ = thr_stopped;
+ break;
+ }
+ std::string msg_data(buf.get(), recv_sz);
+ msg_marshaler *m_m = mar_reg_.get_msg_marshaler(read_msg_.id_);
+ m_m->demarshal(msg_data, read_msg_.data_);
+ peer_send(read_msg_.id_, read_msg_.data_);
+ }
+ std::cerr << "shmem msg_que recver thread exit...\n";
+ }
+
+ std::pair<typename peer_type::type, std::string> get_info(void) {
+ std::pair<typename peer_type::type, std::string> info;
+ info.first = peer_type::remote_peer;
+ info.second = q_name_; //should get address info from sock_
+ return info;
+ }
+
+ void shutdown_wait() {
+ size_t quit_msg = quit_flag;
+ if (thr_st_ == thr_running) {
+ //msg que internal already has lock protection
+ recv_mq_->send(&quit_msg, sizeof(quit_msg), 0);
+ }
+ thr_->join();
+ peer_type::release();
+ }
+
+ private:
+ bool active_role_;
+ std::string q_name_;
+ std::string send_q_name_;
+ std::string recv_q_name_;
+ boost::interprocess::message_queue *send_mq_;
+ boost::interprocess::message_queue *recv_mq_;
+ marshaler_registry &mar_reg_;
+ boost::thread *thr_;
+ thr_state thr_st_;
+
+ //output data buffers
+ std::string id_data_;
+ std::string out_msg_data_;
+
+ //input data buffers
+ std::vector<char> msg_data_;
+ msg_type read_msg_;
+ };
+
+ }
+}
+
+#endif
+

Added: sandbox/channel/boost/channel/unnamed_in_out.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/boost/channel/unnamed_in_out.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,106 @@
+//
+// unnamed_in_out.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef UNNAMED_IN_OUT_HPP
+#define UNNAMED_IN_OUT_HPP
+
+#include <list>
+#include <vector>
+#include <algorithm>
+#include <iostream>
+#include <boost/channel/name_spaces/null_name_space.hpp>
+#include <boost/channel/dispatchers/arbiters_async.hpp>
+#include <boost/channel/dispatchers/arbiters_sync.hpp>
+#include <boost/channel/dispatchers/broadcast_dispatcher.hpp>
+#include <boost/channel/dispatchers/round_robin_dispatcher.hpp>
+#include <boost/channel/dispatchers/always_latest_dispatcher.hpp>
+#include <boost/channel/dispatchers/pull_dispatcher.hpp>
+
+namespace boost {
+ namespace channel {
+
+ /**
+ * port class: "unnamed" named_out with pull_dispatcher
+ * same role as port in CCR and channel in C++CSP or JCSP
+ */
+ template<
+ typename executor_type = abstract_executor, //force in-line execution
+ typename idtype = null_id,
+ typename platform_type = boost_platform,
+ typename synchpolicy = mt_synch<platform_type> ,
+ typename name_space = null_name_space<idtype, executor_type, synchpolicy> ,
+ typename pulldispatcher = pull_dispatcher<name_space, platform_type>
+ >
+ class port: public named_out<name_space, typename pulldispatcher::sender> {
+ public:
+ typedef typename pulldispatcher::choice_async choice_async;
+ typedef typename pulldispatcher::join_async join_async;
+ typedef typename pulldispatcher::choice_sync choice_sync;
+ typedef typename pulldispatcher::join_sync join_sync;
+ typedef named_out<name_space, typename pulldispatcher::sender> named_out_type;
+ typedef named_in<name_space, typename pulldispatcher::recver> named_in_type;
+ port(executor_type *e=NULL) : named_out_type(e) {}
+ };
+
+ /**
+ * signal and slot: for synch event dispatching
+ * signal : "unnamed" named_out with push_dispatchers
+ * when signal(named_out) is destroyed, all its remaining slots(named_ins) are unbound;
+ * their num_bindings() should return 0
+ * when slots(named_in) are destroyed, they are unbound from named_in automatically
+ */
+ template <
+ typename executor_type = abstract_executor, //force in-line execution
+ typename idtype = null_id,
+ typename platform_type = boost_platform,
+ typename synchpolicy = mt_synch<platform_type>,
+ typename name_space = null_name_space<idtype,executor_type,synchpolicy>,
+ typename push_dispatcher = broadcast_dispatcher<name_space,platform_type>
+ >
+ class signal : public named_out<name_space, typename push_dispatcher::sender> {
+ public:
+ typedef named_in<name_space, typename push_dispatcher::recver> slot;
+ typedef named_out<name_space, typename push_dispatcher::sender> named_out_type;
+ typedef name<idtype, executor_type, synchpolicy> name_type;
+ typedef typename name_type::binding_set_type binding_set_type;
+
+ executor_type *exec_;
+ signal(executor_type *e=NULL) : named_out_type(e), exec_(e) {}
+ ~signal() {
+ //signal should be the last to kill after all slots cleanup. do some cleanup ?
+ binding_set_type & bindings0 = ((name_type*) this)->bindings_;
+ //here something wrong with list::iterator!? so copy to a vector
+ std::vector<name_type *> bindings(bindings0.begin(), bindings0.end());
+ typename std::vector<name_type *>::iterator iter;
+ for(iter = bindings.begin(); iter != bindings.end(); iter++) {
+ delete ((slot *) (*iter));
+ }
+ }
+
+ template <typename recver_type>
+ slot * bind(recver_type rc) {
+ slot * ss = new slot(boost::bind(rc, _2), exec_);
+ ((name_type *)this)->bind((name_type *)ss);
+ ((name_type *)ss)->bind((name_type *)this);
+ return ss;
+ }
+
+ //when slots are destroyed, they unbind from signals automatically
+ //here is for the case when we just want unbind, not destroy
+ void unbind(slot *ss) {
+ ((name_type *)this)->unbind((name_type *)ss);
+ ((name_type *)ss)->unbind((name_type *)this);
+ }
+
+ };
+}
+}
+
+#endif
+

Added: sandbox/channel/libs/channel/doc/assoc_id_text.html
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/doc/assoc_id_text.html 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,380 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+ <meta content="text/html; charset=ISO-8859-1"
+ http-equiv="content-type">
+ <title>assoc_id_text.html</title>
+</head>
+<body style="color: rgb(0, 0, 0);" alink="#ee0000" link="#0000ee"
+ vlink="#551a8b">
+<h2>Design of Associative Name Space, Id and Id_Trait</h2>
+<br>
+There are 2 stimulis for the design of associative name space:<br>
+<ul>
+ <li>Control flow branching based on pattern matching. <br>
+ </li>
+</ul>
+<div style="margin-left: 40px;">Many shells (e.g. rc, bash) support the
+following control flow structure:<br>
+</div>
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; case <span
+ style="font-style: italic; font-weight: bold;">expression</span> in<br>
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; <span
+ style="font-weight: bold; font-style: italic;">pattern1</span> )<br>
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
+&nbsp;&nbsp; &nbsp;&nbsp; statements ;;<br>
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; <span
+ style="font-weight: bold; font-style: italic;">pattern2</span> )<br>
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
+&nbsp;&nbsp; &nbsp;&nbsp; statements ;;<br>
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
+......<br>
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; esac<br>
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; In shells, patterns are
+created by using wildcard characters (*,?...). Ruby provides a stronger
+"case" structure using regex to define patterns.<br>
+<ul>
+ <li>Linda Tuple Space. <br>
+ </li>
+</ul>
+<div style="margin-left: 40px;">In a brief summary, in a Linda system,
+distributed processes communicate thru shared associative "address
+space" - tuple space which consist of tuples. Each tuple consists of
+fields. Tuples are written
+("out") to tuple space, read and taken ("in", "read") from tuple space.
+Tuples are identified thru associative
+lookup: two tuples match if all their corresponding fields match while
+two fields match if they are of the same type and either of the same
+value or one of them is wildcard.<br>
+<br>
+</div>
+<div style="text-align: left;">Channel supports message passing and
+name-matching based on regex pattern matching and Linda associative
+lookup. Regex name-matching is implemented using Boost.Regex and the
+code is relative straightforward. Please refer to <a
+ href="sample9_text.html">sample 9</a>
+for the usage of regex based name-matching. Here we focus on the <a
+ href="../../../boost/channel/name_spaces/assoc_id_trait.hpp">detailed
+implemenation</a> of names-matching
+using Linda lookup. Please refer to <a href="sample10_text.html">sample
+10</a> for the usage of associative lookup based name-matching.<br>
+<br>
+In Linda style associative name space, a message names/ids is "a
+tuple" consisting of a set of fields. We use Boost.Tuple&nbsp; for
+defining these ids and names. To support associative lookup, we define
+field_trait template classes for each data type of the tuple fields.
+Each field_trait class will define wildcard and match operation for its
+data type. The following is a sample:<br>
+<div style="margin-left: 40px; background-color: rgb(255, 255, 255);"><span
+ style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+template &lt;&gt;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+class
+BOOST_CHANNEL_DECL field_trait&lt;int&gt; {</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+public:</span><br style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+typedef int field_type;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+static int wildcard;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+static bool wildcard_field(int f) {</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; if (f == wildcard) </span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;
+&nbsp;&nbsp;&nbsp; return true;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; return false;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+}</span><br style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+static bool match(int f1, int f2) {</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; if (f1 == wildcard || f2 == wildcard)</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;
+&nbsp;&nbsp;&nbsp; return true;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; return f1 == f2;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+}</span><br style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+};</span><br>
+</div>
+In assoc_id_trait.hpp, we define the field_trait template classes for
+all the primitive data types. If user defined types (classes or
+structs) are to be used as tuple field type, user code should provide
+field_trait classes for these types.<br>
+<br>
+We define the following template class as associative name space id:<br>
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+template &lt;typename Tuple_Type&gt;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+class tuple_id {</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; ......<br>
+&nbsp;&nbsp;&nbsp; </span><span style="color: rgb(153, 0, 0);"><span
+ style="color: rgb(0, 0, 0);">We need define copy constructor and
+standard relational operators for tuple_id to work with std::map
+container.</span><br style="color: rgb(153, 0, 0);">
+</span><span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; tuple_id(const tuple_id &amp;id) : type_(id.type_),
+tuple_(id.tuple_) {}</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+&nbsp; bool operator&lt; (const tuple_id &amp;id) const {......}</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; bool operator== (const tuple_id &amp;id) const
+{......}</span><br style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; bool operator!= (const tuple_id &amp;id) const
+{......}</span><br style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; ......<br>
+&nbsp;&nbsp;&nbsp; </span><span style="color: rgb(153, 0, 0);"><span
+ style="color: rgb(0, 0, 0);">Then we define serialize() method to
+marshal/demarshal tuple_id using Boost.Serialization</span><br
+ style="color: rgb(153, 0, 0);">
+</span><span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; template&lt;class Archive&gt;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; void serialize(Archive &amp; ar, const unsigned int
+version) {......}</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+};<br>
+<br>
+</span><span style="color: rgb(153, 0, 0);"><span
+ style="color: rgb(0, 0, 0);">Next, we define id_trait class for
+tuple_id:<br>
+<br>
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+template&lt;typename Tuple_Type&gt;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+class BOOST_CHANNEL_DECL id_trait&lt;tuple_id&lt;Tuple_Type&gt; &gt; {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+public:</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+&nbsp;&nbsp;&nbsp; we define some associated types.<br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+typedef Tuple_Type tuple_type;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+typedef tuple_id&lt;tuple_type&gt; id_type;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+&nbsp;&nbsp;&nbsp; and define system internal messages<br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);"></span><span
+ style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+static id_type channel_conn_msg;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+static id_type channel_disconn_msg;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+static id_type init_subscription_info_msg;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+static id_type connection_ready_msg;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+static id_type subscription_info_msg;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+static id_type unsubscription_info_msg;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+static id_type publication_info_msg;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+static id_type unpublication_info_msg;<br>
+&nbsp;&nbsp;&nbsp; </span><span style="color: rgb(153, 0, 0);"><span
+ style="color: rgb(0, 0, 0);">Since internally Boost.Tuple is
+represented as recursive cons list, the following match operation is
+defined as recursive methods:</span></span><span
+ style="color: rgb(153, 0, 0); font-style: italic;"><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static bool match_tuple(const
+boost::tuples::null_type&amp;, const boost::tuples::null_type&amp;)</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+{</span><br style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;"></span><span
+ style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; return true;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+}</span><br style="color: rgb(153, 0, 0); font-style: italic;">
+<br style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+template &lt;typename H, typename T&gt;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+static bool match_tuple(const boost::tuples::cons&lt;H,T&gt; &amp;t1,
+const boost::tuples::cons&lt;H,T&gt; &amp;t2)</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+{</span><br style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; if(!field_trait&lt;H&gt;::match(t1.get_head(),
+t2.get_head()))</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; return match_tuple(t1.get_tail(), t2.get_tail());</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+}</span><br>
+<br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);"></span><span
+ style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+static bool match(id_type id1, id_type id2)</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+{ </span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; if (id1.type_ != id2.type_)</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; &nbsp;&nbsp;&nbsp; return false;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; if (id1.type_ == id_type::app_type) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; &nbsp;&nbsp;&nbsp; if (wildcard_tuple(id1.tuple_) &amp;&amp;
+wildcard_tuple(id2.tuple_) &amp;&amp; (id1.tuple_ != id2.tuple_))</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return false;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; &nbsp;&nbsp;&nbsp; if (id1.tuple_ == id2.tuple_)</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return true;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; &nbsp;&nbsp;&nbsp; return match_tuple(id1.tuple_, id2.tuple_);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; }</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; return true;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+}</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+Similarly, we define recursive methods to find if a tuple_id contains
+wildcard:<span style="font-style: italic; color: rgb(153, 0, 0);"></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+static bool wildcard_tuple(const boost::tuples::null_type&amp;)</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+{</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; return false;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+}</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+template &lt;typename H, typename T&gt;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+static bool wildcard_tuple(const boost::tuples::cons&lt;H,T&gt; &amp;t1)</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+{</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp;
+if(field_trait&lt;H&gt;::wildcard_field(t1.get_head()))</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; &nbsp;&nbsp;&nbsp; return true;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; return wildcard_tuple(t1.get_tail());</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+}</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+static bool wildcard_name(const id_type &amp;id) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; if (id.type_ != id_type::app_type)</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; &nbsp;&nbsp;&nbsp; return false;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; return wildcard_tuple(id.tuple_);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+}</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+Finally we define a method to display id content as string for
+debugging purpose:<br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+static std::string id_to_string(const id_type &amp;id) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; std::ostringstream os;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; os &lt;&lt; "tuple_id : type[" &lt;&lt; id.type_
+&lt;&lt; "] tuple[" &lt;&lt; id.tuple_ &lt;&lt; "]";</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; return os.str();</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+};</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<br>
+Since the type of tuple (how many fields and what fields types) are
+decided by application code of Channel and can be different for
+different applications, the pre-defined system internal messages can
+only be defined thru the following macro. Application code should
+include this macro somewhere so that its system internal messages are
+defined:<br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">#define
+DEFINE_ASSOC_SYS_IDS( tuple_type ) \</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">template
+&lt;&gt; boost::channel::tuple_id&lt;tuple_type&gt;
+boost::channel::id_trait&lt;boost::channel::tuple_id&lt;tuple_type&gt;
+&gt;::channel_conn_msg(boost::channel::tuple_id&lt;tuple_type&gt;::channel_conn_type);
+\<br>
+......<br style="font-style: italic; color: rgb(153, 0, 0);">
+</span><span style="font-style: italic; color: rgb(153, 0, 0);"></span><span
+ style="font-style: italic; color: rgb(153, 0, 0);"></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<br>
+</span></span><span style="color: rgb(153, 0, 0); font-style: italic;"></span></div>
+</body>
+</html>

Added: sandbox/channel/libs/channel/doc/design.html
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/doc/design.html 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,1864 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+</head>
+<body>
+<h2 style="text-align: center;">Channel - A Name Space Based C++
+Framework For Asynchronous Distributed Message Passing and Event
+Dispatching</h2>
+<h2 style="text-align: center;">Yigong Liu (9/24/2006)</h2>
+<hr style="width: 100%; height: 2px;">
+<ul id="mozToc">
+<!--mozToc h3 1 h4 2-->
+ <li>1. Introduction</li>
+ <li>2. Build</li>
+ <li>3. Tutorials
+ <ul>
+ <li>3.1 gui event handling</li>
+ <li><a href="#mozTocId147115">3.2 gui event handling with 2 local
+channels</a></li>
+ <li>3.3 distributed gui events</li>
+ <li>3.4 chat with direct connection</li>
+ <li><a href="#mozTocId680978">3.5 buffered channel with blocking
+active receiver (synchronous choice, join synchronization patterns)</a></li>
+ <li><a href="#mozTocId232384">3.6 buffered channel with async
+receivers (asynchronous choice, join synchronization patterns)</a></li>
+ <li><a href="#mozTocId836556">3.7 distributed chat thru a
+central server</a></li>
+ <li><a href="#mozTocId266315">3.8 channel
+connection thru shared memory</a></li>
+ <li><a href="#mozTocId300223">3.9 channel using regex name
+matching </a></li>
+ <li><a href="#mozTocId440147">3.10 channel using Linda-style
+associative lookup</a></li>
+ <li><a href="#mozTocId505601">3.11 channel name space management
+and security with filters
+and translators</a></li>
+ <li><a href="#sample_dispatcher">3.12 port and signal: unnamed
+point of tightly-coupled local interactions</a><br>
+ </li>
+ </ul>
+ </li>
+ <li>4. Design
+ <ul>
+ <li><a href="#mozTocId135917">4.0 Overall Design
+Idea</a></li>
+ <li>4.1 Name space</li>
+ <ul>
+ <li>4.1.1 What's in a name?</li>
+ </ul>
+ <ul>
+ <li><a href="#mozTocId582741">4.1.2 Types of
+name space</a></li>
+ </ul>
+ <ul>
+ <li><a href="#mozTocId182536">4.1.3 Name binding
+set and Name matching
+algorithm, binding rules </a></li>
+ </ul>
+ <ul>
+ <li><a href="#mozTocId891206">4.1.4 Name spaces
+merge and connections </a></li>
+ </ul>
+ <li>4.2 Dispatching</li>
+ <ul>
+ <li><a href="#mozTocId862080">4.2.1 How message
+data move: push/pull, buffering</a></li>
+ </ul>
+ <ul>
+ <li><a href="#mozTocId629360">4.2.2 How operations
+are performed: synchronous/asynchronous</a></li>
+ </ul>
+ <ul>
+ <li><a href="#mozTocId248159">4.2.3 Message passing
+coordination
+patterns </a></li>
+ </ul>
+ <ul>
+ <li><a href="#mozTocId995030">4.2.4 Messages
+handling</a></li>
+ </ul>
+ <li>4.3 Connection related</li>
+ <ul>
+ <li>4.3.1 Connections</li>
+ </ul>
+ <ul>
+ <li>4.3.2 Peer</li>
+ </ul>
+ <li><a href="#unnamed_design">4.4 "Unnamed" binding of
+output/input or points of tightly-coupled
+local
+interactions</a></li>
+ <li><a href="#mozTocId970853">4.5 Application
+architecture and integration</a></li>
+ </ul>
+ </li>
+ <li>5. Classes
+ <ul>
+ <li>5.1 name space related</li>
+ <ul>
+ <li>5.1.1 name spaces</li>
+ </ul>
+ <ul>
+ <li><a href="#mozTocId828224"> 5.1.2 id_type and
+id_trait </a></li>
+ </ul>
+ <ul>
+ <li><a href="#mozTocId856863">5.1.3 name and name
+binding callback</a></li>
+ </ul>
+ <ul>
+ <li><a href="#mozTocId915384">5.1.4 named_out and
+named_in; publisher and subscriber</a></li>
+ <li><a href="#unnamed_class">5.1.5 unnamed in/out: port and
+signal/slot</a></li>
+ </ul>
+ <ul>
+ <li><a href="#mozTocId750531">5.1.6
+binder, filter and translator</a></li>
+ </ul>
+ <li><a href="#mozTocId985604">5.2 dispatching
+related</a></li>
+ <ul>
+ <li>5.2.1 dispatchers</li>
+ </ul>
+ <ul>
+ <li>5.2.2 messages</li>
+ </ul>
+ <ul>
+ <li>5.2.3 queues</li>
+ </ul>
+ <ul>
+ <li>5.2.4 executors </li>
+ </ul>
+ <li>5.3 connection related</li>
+ <ul>
+ <li><a href="#mozTocId460401">5.3.1&nbsp; global
+functions for connecting channels </a></li>
+ </ul>
+ <ul>
+ <li>5.3.2 connection</li>
+ </ul>
+ <ul>
+ <li><a href="#mozTocId581357">5.3.3 peer and
+interface</a></li>
+ </ul>
+ <ul>
+ <li>5.3.4 streams</li>
+ </ul>
+ <ul>
+ <li><a href="#mozTocId711260">5.3.5 marshaling
+registry</a></li>
+ </ul>
+ <li><a href="#mozTocId128213">5.4 platform
+abstraction policy and synchronization policy </a></li>
+ <ul>
+ <li><a href="#mozTocId345412">5.4.1 platform
+abstraction</a></li>
+ </ul>
+ <ul>
+ <li><a href="#mozTocId405486">5.4.2 synchronization
+policy</a></li>
+ </ul>
+ </ul>
+ </li>
+ <li><a href="#mozTocId283551">6. Class Concepts and
+How to extend
+Channel framework</a>
+ <ul>
+ <li><a href="#mozTocId162285">6.1 id_type and
+id_trait</a></li>
+ <li>6.2 name space</li>
+ <li>6.3 dispatcher</li>
+ <li>6.4 executor</li>
+ <li>6.5 queue</li>
+ <li><a href="#mozTocId441870">6.6
+streams/connectors (or integrate into new architecture)</a></li>
+ </ul>
+ </li>
+ <li><a href="#mozTocId631535">7. Compare Channel to
+others (plan9, STL)</a>
+ <ul>
+ <li><a href="#mozTocId547030">7.1 Compare
+Unix/Plan9/Inferno file-system name space and Channel's name space</a></li>
+ <li><a href="#mozTocId82643">7.2 compare STL and
+Channel</a></li>
+ </ul>
+ </li>
+ <li>8. Reference Links</li>
+</ul>
+<hr style="width: 100%; height: 2px;">
+<h3><a class="mozTocH3" name="mozTocId347090"></a><small>1. Introduction</small></h3>
+In Unix and most OSes, file systems allow applications to identify,
+bind to and operate on system resources and entities (devices,
+files,...) using a "name" (path name) in a hierarchical name space
+(directory system) which is different&nbsp; from variables and pointers
+in flat address space. Many interprocess communication facilities (IPC)
+often depend on some kind of "names" to identify them too, such as the
+pathname of FIFO or named-pipe, pathname for unix domain socket,
+ip-address and port for tcp/udp socket , and keys for System V shared
+memory, message queue and semaphores. "The set of possible names for a
+given type of IPC is called its <span
+ style="font-style: italic; font-weight: bold;">name space</span>. The
+name space is important because for all forms of IPC other than plain
+pipes, the name is how the client and server&nbsp; "connect" to
+exchange messages." (quote from W. Richard Stevens "Unix Network
+Programming").<br>
+<br>
+Channel is a C++ template library to provide name spaces for
+asynchronous, distributed message passing and event dispatching.
+Message senders and receivers bind to names in name space; binding and
+matching rules decide which senders will bind to which receivers; then
+message passing and event dispatching could happen among bound senders
+and receivers.<br>
+Channel's signature:<br>
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; template &lt;</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+typename idtype,</span><br style="font-weight: bold;">
+<span style="font-weight: bold;"></span><span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+typename platform_type = boost_platform,</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+typename synchpolicy = mt_synch&lt;platform_type&gt;,</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;"></span><span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+typename executor_type = abstract_executor, </span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;"></span><span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+typename name_space =
+linear_name_space&lt;idtype,executor_type,synchpolicy&gt;,</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+typename dispatcher =
+broadcast_dispatcher&lt;name_space,platform_type&gt; </span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &gt;</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; class
+channel;&nbsp;&nbsp; </span><br>
+Various name spaces (linear/hierarchical/associative) can be used for
+different applications. For example, we can use integer ids as names to
+send messages in linear name space, we can use string path name ids <a
+ id="intro">(such as
+"/sports/basketball")</a> to send
+messages in hierarchical name space<a id="intro"> and we can use regex
+patterns or
+Linda tuple-space style tuples to send messages in associative name
+space</a>; User can configure name space
+easily
+by setting a channel template parameter.<br>
+<br>
+Channel's other major components are dispatchers; which dispatch
+messages/events from senders to bounded receivers. Dispatcher is also a
+channel template parameter. The design of dispatchers can vary in
+several dimensions:<br>
+<ul>
+ <li>how msgs move: push or pull; </li>
+ <li>how callbacks executed: synchronous or asynchronous. </li>
+</ul>
+Sample dispatchers includes : synchronous broadcast dispatcher,
+buffered asynchronous dispatchers,...<br>
+<br>
+Name space and dispatchers are orthogonal; they can mix and match
+together freely; just as STL algorithms can be used with any STL
+containers by means of the iterator range concept, name space and
+dispatchers can be used together because of the name binding set
+concept. <br>
+<br>
+By combining different name space and dispatching policies, we can
+achieve various models:<br>
+<ul>
+ <li>synchronous event dispatching&nbsp;&nbsp;&nbsp; </li>
+ <li>associative name space based on matching/look-up rules similar to
+Linda tuple space</li>
+ <li>asynchronous messaging model similar to Microsoft CCR
+(Concurrency Coordination Runtime)<br>
+ </li>
+</ul>
+Similar to distributed files systems, distributed channels can be
+connected or "mounted" to allow transparent distributed message
+passing. Filters and translators are used to control name space changes.<br>
+<br>
+For tightly coupled single-address-space applications/modules,
+Channel's "unnamed" in/out
+objects : ports and signal/slots support fine grained and local message
+passing model without
+the hassle of setting up a name space and assigning names.<br>
+<br>
+Channel is built on top of Boost facilities: <br>
+<ul>
+ <li>Boost::shared_ptr for message/event data life-time management</li>
+ <li>Boost.Bind, Boost.Function for callback</li>
+ <li>Boost.Thread for synchronization</li>
+ <li>Boost.Serialization for message marshaling/demarshaling</li>
+ <li>Boost.Regex and Boost.Tuple for associative name-matching<br>
+ </li>
+ <li><big><small>Boost.Asio and Boost.Shmem are used to build
+transports among remote channels.</small></big></li>
+</ul>
+<hr style="width: 100%; height: 2px;">
+<h3><a class="mozTocH3" name="mozTocId587884"></a>2. Build</h3>
+Channel is continuously being developed and tested in linux
+(ubuntu8.04/g++4.2.4 - ubuntu9.04/g++4.3.3) and Windows (Visual C++ 2005 -
+Visual C++ 2008). The
+implementation is solely based on standard boost facilities plus
+Boost.Asio and
+Boost.Interprocess. <br>
+Download: http://channel.sourceforge.net<br>
+<div style="text-align: left;">Build: Channel is a header only library.
+There is no need to build the
+library itself to use it. Please following these steps:
+<div style="margin-left: 40px;"><a
+ href="http://www.boost.org/more/getting_started.html">download or
+checkout boost distribution</a><br>
+download latest boost_channel_x_x.tar.gz<br>
+tar xvzf boost_channel_x_x.tar.gz<br>
+add boost's directory and Channel's directory to compilers' include
+path<br>
+cd to &lt;channel_top_directory&gt;/libs/channel/exmaple/&lt;specific
+samples such as ping_pong&gt;<br>
+bjam<br>
+</div>
+</div>
+<hr style="width: 100%; height: 2px;">
+<h3><a class="mozTocH3" name="mozTocId174795"></a>3. Tutorials</h3>
+<p>the following are a few samples showing how different name spaces
+and dispatchers can be used in various situations:</p>
+<h4><a name="mozTocId270435"></a>3.1 gui event handling</h4>
+<p>A simple sample shows that a gui window send (broadcast) simple
+events to callbacks (either free functions or object members).
+details...</p>
+<h4><a name="mozTocId147115"></a>3.2 gui event handling with 2 local
+channels</h4>
+<p>This sample shows how 2 channels can be connected to allow gui
+events propagate from one channel to another. Also we use a POD struct
+as message id/name.&nbsp; <a
+ href="../example/gui_evt/sample2_text.html">details...</a></p>
+<h4><a name="mozTocId280170"></a>3.3 distributed gui events</h4>
+<p>A sample shows how events can be sent (broadcast) to callbacks in
+remote process by connecting local channel to remote channels thru
+Boost.Asio. details...</p>
+<h4><a name="mozTocId886481"></a>3.4 chat with direct connection</h4>
+<p>This sample shows the usage of hierarchical name space by defining
+chat subjects as string path names. For demo, chat peers directly
+connect to each other, subscribing to the subjects they are
+interested and send messages with each other. Since it a hierarchical
+name space, peers can subscribe to wildcard ids such as "all
+sports related subjects". <a
+ href="../example/chat_direct/sample4_text.html">details...</a></p>
+<h4><a name="mozTocId680978"></a>3.5 buffered channel with blocking
+active receiver (synchronous choice, join synchronization patterns)</h4>
+<p>A sample shows the usage of buffered channels implemented thru a
+synchronous pull dispatcher. In this channel
+configuration, messages are buffered inside channel at sender side.
+The receiver is active, a thread blocking waiting for the arrival of
+messages at synchronous join/choice arbiters and then processing the
+messages. details...</p>
+<h4><a name="mozTocId232384"></a>3.6 buffered channel with async
+receivers (asynchronous choice, join synchronization patterns)</h4>
+<p>This sample shows a buffered channel support asynchronous
+receivers using asynchronous coordination patterns: choice and join.
+The callback actions are dispatched thru a thread pool executor.
+details...</p>
+<h4><a name="mozTocId836556"></a><b>3.7 distributed chat thru a
+central server</b></h4>
+<p>This sample shows simple chat client and server design. Clients
+connect to server to chat with each other in seperate chat groups
+identified by subject. The chat subject (a string) is the ids in name
+space. Clients can join/leave chat groups identified by subject ids
+and send messages to chat groups. If the chat group (subject) doesn't
+exist yet, the first member's "join" will make it created.
+details...</p>
+
+<span style="font-weight: bold;"></span><span style="font-weight: bold;"></span>
+<h4><a class="mozTocH4" name="mozTocId266315"></a>3.8 channel
+connection thru shared memory</h4>
+This sample shows that remote channels at 2 processes (chat1, chat2)
+can be connected thru shared memory message queues based on
+Boost.Interprocess. details...<br>
+<h4><a class="mozTocH4" name="mozTocId300223"></a>3.9 channel using
+regex name matching<br>
+</h4>
+This sample demos channels using regex pattern matching for
+name-matching and message dispatching. Peers can use regex patterns to
+bind/subscribe to names/ids. Boost.Regex is used for implementation. <a
+ href="../example/chat_regex/sample9_text.html">details...</a><br>
+<h4><a class="mozTocH4" name="mozTocId440147"></a>3.10 channel using
+Linda-style associative lookup<br>
+</h4>
+This sample demos channels using Linda-style associative name space.
+Tuples are used as names/ids and associative lookup is used for
+name-matching. Boost.Tuple is used for implementation. <a
+ href="../example/chat_assoc/sample10_text.html">details...</a><br>
+<h4><a class="mozTocH4" name="mozTocId505601"></a>3.11 channel name
+space management and security with filter and
+translator</h4>
+<h4></h4>
+This sample demos how we can use filters and translators to achieve
+name space management and security. <a
+ href="../example/filter_translator/sample11_text.html">details...</a><br>
+<h4><a name="sample_dispatcher"></a>3.12 port and signal: unnamed point
+of tightly-coupled local interactions
+</h4>
+This tutorial explains 3 samples based on port and signal. <a
+ href="../example/prime_sieve/sample12_text.html">details...</a><br>
+<hr style="width: 100%; height: 2px;">
+<h3><a class="mozTocH3" name="mozTocId750399"></a>4. Design</h3>
+<h4><a class="mozTocH4" name="mozTocId135917"></a>4.0 Overall Design
+Idea</h4>
+"Names" play important role in distributed computing:<br>
+<ul>
+ <li>Name space plays a central role in plan9/inferno distributed OS
+as
+described in [1][2]. </li>
+</ul>
+<div style="margin-left: 40px;">quote: <br>
+"... a new kind of system, organized around communication and naming
+..."<br>
+"A single paradigm (writing to named places) unifies all kinds of
+control and interprocess signaling."<br>
+It can be briefly summerized as following:<br>
+<ul>
+ <li>Every resource, either local or remote, is represented as a
+hierarchical file system (name space).</li>
+ <li>Each process can assemble a private view of the system by
+constructing a local/private name space that connect these resources
+thru mount, bind and umount on demand.</li>
+ <li>The interface to named resources are file-oriented; they are
+accessed thru open/close/read/write calls.</li>
+</ul>
+</div>
+<ul>
+ <li>Robin Milner[3][4] gives a detailed discussion about what we can
+do
+with a name in asynchronous message passing, or the interactions thru
+"name":</li>
+</ul>
+<div style="text-align: left; margin-left: 40px;">The following
+operations on names are identified:<br>
+<ul>
+ <li>use name: call, co-calling (response)<br>
+ </li>
+</ul>
+<div style="margin-left: 40px;"><span style="font-weight: bold;">call -
+vocative use of name by one agent</span><br style="font-weight: bold;">
+<span style="font-weight: bold;">co-call/response - reaction by other</span><br>
+Synchronized action is the coming together (binding) of calling and
+co-calling (thru name).<br>
+The reason to distinquish between "calling" and "response" is that, in
+describing any agents ( processes/ threads/ ...), we define its
+potential
+behaviour (or capabilities) by what calls and responses it can make -
+this is the basic idea underlying the active objects or communicating
+processes based design which will be detailed in later section.<br>
+</div>
+<ul>
+ <li>mention name: quote/co-quote, match<br>
+ </li>
+</ul>
+<div style="margin-left: 40px; font-weight: bold;">quote, co-quote:</div>
+</div>
+<div style="text-align: left;">
+<div style="margin-left: 80px;">quote/co-quote is refering to the way
+we can pass names as/inside message content. We can simulate function
+call (call-and-return) by packing a "return" name/id inside message and
+waiting on this name for result (from remote).<br>
+</div>
+</div>
+<div style="text-align: left; margin-left: 40px;">
+<div style="margin-left: 40px; font-weight: bold;">match:</div>
+</div>
+<div style="text-align: left;">
+<div style="margin-left: 80px;">test a name for equality with another
+name. Name matching algorithms are mostly dependent on name space
+structure. In following sections, we will expand "matching" to include
+wildcards and regex matching<br>
+</div>
+<div style="margin-left: 40px;"><br>
+The design of Channel is based on the following integration of
+Plan9/Inferno's
+name space idea and Robin Milner's interaction thru names:<br>
+<ul>
+ <li>Channel provides process local private name_space which is
+customizable thru connecting to other channels.</li>
+ <li>The semantics of names are changed; names do not refer to named
+resources (which are relatively static entities), but to named "points
+of interaction" (which are mostly dynamic); thus file-oriented api and
+semantics are dropped and Robin Milner's operations/interactions on
+names are adopted as the api: calling/co-calling/matching.</li>
+</ul>
+</div>
+</div>
+<div style="text-align: left; margin-left: 40px;">
+<div style="margin-left: 80px;"></div>
+</div>
+<h4><a class="mozTocH3" name="mozTocId540592"></a>4.1 Name space</h4>
+<h4><a class="mozTocH4" name="mozTocId84795"></a>4.1.1 What's in a name?</h4>
+In Channel, to facilitate name-matching/binding operations, a name has
+the
+following attributes:<br>
+<ul>
+ <li>id_type<br>
+ </li>
+</ul>
+<div style="margin-left: 40px;">Id is the main content of names.
+Various types of ids can be used for different applications: integer,
+strings, POD structs etc can be used for linear name space;
+string
+path names can be used for hierarchical name spaces and regex patterns
+and Linda style tuples can be used for associative name space.<br>
+</div>
+<ul>
+ <li>id_trait and id-matching algorithms<br>
+ </li>
+</ul>
+<div style="margin-left: 40px;">Id_trait defines the attributes of an
+id type. A major feature of id_trait is the
+id-matching algorithm,
+which partially decides name-matching and thus which senders will bind
+which receivers and be
+able to send messages to them. For example, exact matching can be used
+for linear name space ids; prefix matching can be used for path
+name ids; while in associative name spaces, regex pattern matching and
+Linda style associative lookup can be used for id-matching.<br>
+</div>
+<ul>
+ <li>membership</li>
+</ul>
+<div style="margin-left: 40px;">A channel is a process local name space
+which can be connected to other
+local or remote channels. So we have 2 types of communicating peers:<br>
+</div>
+<ul style="margin-left: 40px;">
+ <li>MEMBER_LOCAL (local peers): communication peers inside the same
+channel</li>
+ <li>MEMBER_REMOTE (remote peers): communication peers from different
+channels</li>
+</ul>
+<ul>
+ <li>sending and receiving scope</li>
+</ul>
+<div style="margin-left: 40px;">When sending/receiving messages, we can
+specify the scope of operations:<br>
+<ul>
+ <li>SCOPE_LOCAL: <br>
+ </li>
+ <ul>
+ <li>publish/send specified messages to local peers; <br>
+ </li>
+ <li>subscribe/receive specified messages from local peers</li>
+ </ul>
+ <li>SCOPE_REMOTE: <br>
+ </li>
+ <ul>
+ <li>publish/send specified messages to remote peers; <br>
+ </li>
+ <li>subscribe/receive specified messages from remote peers</li>
+ </ul>
+ <li>SCOPE_GLOBAL: <br>
+ </li>
+ <ul>
+ <li>publish/send specified messages to both local and
+remote peers; <br>
+ </li>
+ <li>subscribe/receive specified messages from both local and
+remote peers</li>
+ </ul>
+</ul>
+</div>
+<h4><a class="mozTocH4" name="mozTocId582741"></a>4.1.2 Types of
+name space</h4>
+There are 3 types of name spaces based on its id-matching algorithms
+and naming structures:<br>
+<ul>
+ <li>linear:</li>
+</ul>
+<div style="margin-left: 40px;">There are ordering relationship among
+ids, so they can be arranged in linear range. <span
+ style="font-weight: bold; font-style: italic;">Exact matching</span>
+is used
+for
+id-matching.<br>
+</div>
+<ul>
+ <li>hierarchical:</li>
+</ul>
+<div style="margin-left: 40px;">There are containment relationship
+among ids, so they can be arranged in tree/trie structures. <span
+ style="font-style: italic; font-weight: bold;">Prefix
+matching</span> is used for id-matching<br>
+</div>
+<ul>
+ <li>associative:</li>
+</ul>
+<div style="margin-left: 40px;">Id-matching is based on <span
+ style="font-style: italic; font-weight: bold;">associative
+lookup</span> similar to Linda's tuple space or regular expression
+matching
+algorithms<br>
+</div>
+<h4><a class="mozTocH4" name="mozTocId182536"></a>4.1.3 Name binding
+set and Name matching
+algorithm, binding rules<br>
+</h4>
+No pure name exist; Names are ONLY created into name space when bound
+for sending/receiving msgs:<br>
+<ul>
+ <li>Named_Out: output/send interface bound with name</li>
+ <li>Named_In: input/receiv interface bound with name</li>
+</ul>
+Name binding sets:<br>
+<ul>
+ <li>for Named_Out, its binding_set is the set of bound Named_Ins to
+which to send messages</li>
+ <li>for Named_In, its binding_set is the set of bound Named_Outs from
+which to receive messages</li>
+</ul>
+There are 2 aspects to the name matching algorithms and binding rules
+to decide binding_sets:<br>
+<ul>
+ <li>id matching: the id of Named_Out must "match" the id of Named_In
+based on matching operation defined in id_trait<br>
+ </li>
+ <li>scope &amp; membership matching: the membership and scope of both
+Named_Out and Named_In must match. This doesn't mean they must be the
+same. For example, a local sender&nbsp; (MEMBER_LOCAL) with SCOPE_LOCAL
+can bind to receivers with &lt;MEMBER_LOCAL, SCOPE_LOCAL&gt; or
+&lt;MEMBER_LOCAL, SCOPE_GLOBAL&gt;. There is an internal table
+recording
+all such valid combinations.</li>
+</ul>
+Named_Out and Named_In don't bind to each other directly (as in most
+event dispatching systems). Instead, they bind to names in name
+space. Based on binding and matching rules, their binding set will
+be resolved which will contain the direct pointers to their
+counterpart. Actual message passing and dispatching happen on the
+binding set; never need to go thru name space again. So the actual
+message passing and dispatching behaviour and performance should be the
+same as&nbsp; we&nbsp; have registered the Named_In directly with
+Named_Out ( as we would have done in normal event dispatching systems ).<br>
+Based on name-matching, there are possibly the following 4 kinds of
+binding sets:<br>
+<ul>
+ <li>1 - 1:&nbsp; one named_out binds with exactly one named_in</li>
+ <li>1 - N: one named_out binds with a group of named_ins (e.g. when
+many subscribers subscribe to the same name)</li>
+ <li>N - 1: one named_in binds with a group of named_outs (e.g. when a
+subscriber subscribes using a wildcard name or regex pattern, it could
+receive from multiple sources)</li>
+ <li>N - M: both named_out and named_in bind with a group of
+counterparts.<br>
+ </li>
+</ul>
+<h4><a class="mozTocH4" name="mozTocId891206"></a>4.1.4 Name spaces
+merge and connections<br>
+</h4>
+When 2 channels (A &amp; B) are connected/mounted, their name spaces
+are
+merged as following:<br>
+<ul>
+ <li>names flowing from B-&gt;A:&nbsp; the intersection of A's set of
+Named_In with global/remote scope (global subscriptions) and B's set
+of&nbsp; Named_Out with global/remote scope (global
+publications) </li>
+ <li>names flowing from A-&gt;B:&nbsp; the intersection of B's set of
+Named_In with global/remote scope (global subscriptions) and A's set
+of&nbsp; Named_Out with global/remote scope (global
+publications) </li>
+ <li>newly created names/ids are automatically
+propogated to connected channels. So peers in channel A can communicate
+with peers in channel B transparently the same way as with the local
+peers. </li>
+</ul>
+Filter, translator can be specified at connections among channels to
+control name space merge:<br>
+<ul>
+ <li>filter: decide which ids are allowed to be exported/sent to
+(visible at) remote
+channels and which remote ids are allowed be imported to local name
+space<br>
+ </li>
+ <li>translator: allow translation of ids imported to local name space
+and ids exported to remote name space; so we can relocate the imported
+remote name space ids to a specific subspace in the local name space,
+similar to the way that in distributed file systems, a remote file
+system can be mounted to a specific point in local file system.</li>
+</ul>
+Based on applications name space management requirements, we may need
+to "relocate"/"mount" the names imported (from a connection to a remote
+name space) to a specific sub-region in name space. For example, if we
+have a name space in desktop computer and connect to a PDA and a
+laptop, we can set translators at connections so that names imported
+from PDA will appear under "/pda/" and names from laptop will appear
+under "/laptop/". Or if our application use integer as ids/names, we
+may want to relocate ids from the 1st connection to [1000-1999] and ids
+from next connection to [2000-2999] and so on. That is similar to the
+way how we mount remote file-systems to local file-system.<br>
+Based on security requirements, we may need to use filters to restrict
+the valid range of names allowed to pass in/out specific channel
+connections. For example, a server's name space connect to 2 clients
+and we want that these clients' name spaces and messaging are totally
+separate, so that one client is unware of anything happening inside the
+other client's name space such as new name-publications and message
+passing. That is also similar to the way we protect network by
+firewalls and NATs.
+<ul>
+</ul>
+<h4><a class="mozTocH3" name="mozTocId210395"></a>4.2 Dispatching</h4>
+Dispatchers or dispatching policies are operations or algorithms
+defined over name binding set. They define the semantics of
+"interactions
+thru names". Based on RobinMilner's separation of
+calling and co-calling, there are 2 parts defined for each
+dispatching algorithm:<br>
+<ul>
+ <li>sending (or sender) algorithm: corresponding to calling<br>
+ </li>
+ <ul>
+ <li>defined over the set of bound Named_In (receiver) objects</li>
+ <li>may contain message buffering mechanism inside channel
+(Named_Outs)<br>
+ </li>
+ </ul>
+ <li>receiving (or receiver) algorithm: corresponding to co-calling<br>
+ </li>
+ <ul>
+ <li>defined over the set of bound Named_Out (sender) objects</li>
+ <li>may support high level messaging coordination patterns (such as
+Choice and Join)</li>
+ </ul>
+</ul>
+The following are major design considerations for dispatchers.<br>
+<h4><a class="mozTocH4" name="mozTocId862080"></a>4.2.1 How message
+data move: push/pull, buffering</h4>
+There are 2 basic models of passing messages/events from senders to
+receivers:<br>
+<ul>
+ <li>push model: message data are pushed by senders to receivers</li>
+ <li>pull model: message data are pulled by receivers from senders</li>
+</ul>
+Since Channel is for asynchronous messaging, mostly the following 2
+dispatching categories are used:<br>
+<ul>
+ <li>push:&nbsp;</li>
+</ul>
+<div style="margin-left: 40px;">Dispatching variations can be:
+broadcast, round-robin,...<br>
+Execution variations can be: <br>
+<ul>
+ <li>synchronous: the sending threads will push messages all the way
+to
+receviers and invoke receiving callbacks directly</li>
+ <li>asynchronous: the sending threads will push messages to receivers
+and dispatch the receiving callbacks to some executors for later
+executions<br>
+ </li>
+</ul>
+</div>
+<ul>
+ <li>buffering+pull:</li>
+</ul>
+<div style="margin-left: 40px;">Messages are buffered inside channel at
+Named_Out side; receivers pull message data in two ways:<br>
+</div>
+<ul style="margin-left: 40px;">
+ <li>sync/blocking receiver: in this model, receivers are active
+receiving threads block-waiting at Named_In, unblocked when message
+data are
+available and pull data from Named_Out</li>
+ <li>async receiver: async callback operations are registered to
+logical conditions of message arrivals (choice and join) and will be
+dispatched to executors depending on message arrivals.</li>
+</ul>
+<div style="margin-left: 40px;">Message coordination patterns (choice
+and join) are applied for both pull synchronous and asynchronous model
+to
+decide when a synchronous receiving thread can be unblocked or
+asynchronous callback can be fired based on the available messages.<br>
+<br>
+</div>
+For message buffering inside channel, we can have various design
+choices:<br>
+<ul>
+ <li>synchronized queues with flow control: low water mark and high
+water mark</li>
+ <li>timeouts for when messages will expire</li>
+</ul>
+<h4><a class="mozTocH4" name="mozTocId629360"></a>4.2.2 How operations
+are performed: synchronous/asynchronous</h4>
+When messages arrive, we have 2 choices for how dispatching operations
+and callbacks are performed:<br>
+<ul>
+ <li>synchronous: the sending thread will carry out dispatching and
+callbacks</li>
+ <li>asynchronous: dispatching or callbacks will be scheduled in an
+executor; and later executed by the executor in a different calling
+context or thread</li>
+</ul>
+There are various designs of executors. [7] provides detailed
+discussion about Java's executor design. <br>
+Different executors can run threads in different scheduling priorities
+and we can assign callbacks to run in propr executors according to
+applications' requirements<br>
+<h4><a class="mozTocH4" name="mozTocId248159"></a>4.2.3 Message passing
+coordination
+patterns<br>
+</h4>
+Join-calculus, Comega, and CCR [5][6] define a few messaging
+coordination
+patterns regarding to when and how messages will be consumed and
+callbacks be fired: <br>
+<ul>
+ <li>Choice: a combo registration of a group of &lt;name,
+callback&gt;; whenever any "name" has message delivered, its associated
+callback will be fired<br>
+ </li>
+ <li>Join: a callback is registered with a set of names; when messages
+become available on all names, the messages will be taken from all
+names "atomically" and the registered callback will be invoked.<br>
+ </li>
+</ul>
+In channel, both choice and join are applied in synchronous and
+asynchronous forms.<br>
+<h4><a class="mozTocH4" name="mozTocId995030"></a>4.2.4 Messages
+handling</h4>
+life-time management of messages:<br>
+<ul>
+ <li>avoid data copying, pass pointers to messages instead of
+duplicating message data</li>
+ <li>wrap message data pointer inside boost::shared_ptr so that
+message data's life time management is automatic<br>
+ </li>
+</ul>
+marshaling/demarshaling of messages:<br>
+<ul>
+ <li>use Boost.Serialization for marshaling/demarshaling</li>
+ <li>a channel could have multiple remote connections, each of them
+could use different transport (tcp/ip, soap, shared-memory) and on-wire
+message format
+(text/binary/xml). In Channel based applications, a marshaler_registry
+can be created for each specific transport type and format.
+By registering message data type with a marshaler_registry using ids as
+key, internal marshaling/demarshaling functions will be created for the
+registered message data types and invoked automatically when messages
+are sent-to and received-from remote channels. When a
+channel is connected to a remote channel thru "streams", we must
+specify
+which marshaler_registry to use for marshaling. <br>
+ </li>
+ <li>for each id/msg-type, we can have different settings of
+marshaling:</li>
+</ul>
+<ul style="margin-left: 40px;">
+ <li>explicitly register a message data type: internally a marshaler
+object will be created and registered with ids<br>
+ </li>
+ <li>use a globally registered default marshaler (if all ids use the
+same data structure)</li>
+</ul>
+<h4><a class="mozTocH3" name="mozTocId967906"></a>4.3 Connection related</h4>
+The following are design considerations related to channel connections.<br>
+<h4><a class="mozTocH4" name="mozTocId216417"></a>4.3.1 Connections</h4>
+there are 2 kinds of connections:<br>
+<ul>
+ <li>local connection:&nbsp; inside the same process, we can have
+multiple channels for different purposes; we can connect these local
+channels to facilitate the communication among their peers.<br>
+ </li>
+ <li>remote connection: we can connect channel to a remote channel
+inside a different process or different machines; the remote interface
+is represented as "streams": socket stream, pipe, or a message queue
+inside shared memory;</li>
+</ul>
+connection object is a simple object, just containing the two
+peers/ends of the connection.<br>
+ways to break a connection:<br>
+<ul>
+ <li>delete connection object; peers are deleted and channels
+disconnect</li>
+ <li>one peer channel is destroyed, the connection will be destroyed
+automatically and the other channel disconnect</li>
+</ul>
+<h4><a class="mozTocH4" name="mozTocId162029"></a>4.3.2 Peer</h4>
+&nbsp;&nbsp;&nbsp; the common interface for connection peers:
+interfaces and streams<br>
+<ul>
+ <li>interface:</li>
+</ul>
+<div style="margin-left: 40px;">proxy of peer channel<br>
+core of channel connection logic:<br>
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;. how remote
+binding/unbinding events will effect local name space<br>
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;. how messages are
+propagated from and to remote channels<br>
+</div>
+<ul>
+ <li>stream:</li>
+</ul>
+<div style="margin-left: 40px;">Stream is used to wrap a remote
+transport connection (socket, pipe or message queue inside shared
+memory).<br>
+In earlier implementation of Channel on ACE[8], a Connector class is
+included as one of the core classes; which will connect local and
+remote channels. the disadvantage of this design is that Channel is
+tied to a specific architecture (such as thread per connection); making
+it difficult to integrate channel with other existing servers.<br>
+In plan9/inferno, when we mount a remote name space to local, the real
+function is to mount a descriptor (file, pipe, or socket connection) to
+a specific point in name space.<br>
+Following this style, remote channel connection is to connect/mount a
+"stream" to a local channel/name_space; the stream wraps a socket,
+pipe, or shared_memory message
+queue connecting a remote channel in another process or machine. thus
+avoid interfering with servers' internal design: such as
+threading; so that channel can work well with both single-thread async
+and multi-thread sync server design.<br>
+</div>
+<h4><a name="unnamed_design"></a>4.4 "Unnamed" binding of output/input
+or points of tightly-coupled
+local
+interactions</h4>
+&nbsp;&nbsp;&nbsp; As discussed in the "Overall Design Idea" section,
+message passing happens on the binding of calling(the sender of
+dispatcher) and co-calling(the receiver of dispatcher).<br>
+&nbsp;&nbsp;&nbsp; All the above discussions focus on setting up this
+binding thru name-matching in name spaces. "Binding thru names"
+provides a loosely coupled computing model. A agent or thread can
+perform or provide its functionality thru the "names" which it
+publishes and subscribs in application channel. It can be moved to
+another process or another machine and continue functioning as before
+as long as in its new enviroment there is a channel connected to the
+original channel and the moved agent attaches to the new channel with
+the same set of "names". However sometimes it may be too much
+burden/overhead than benefit to set up a name space and assign proper
+names, if all we want is performing "localized" computation based on
+message passing model.<br>
+&nbsp;&nbsp;&nbsp; In many message passing based
+systems,
+threads(or
+processes in CSP meaning) communicate thru "ports" or
+"channels" which are normal local objects with possible internal
+message queue.
+Choice/Join arbiters work directly with these local objects. Pointers
+to these objects can be passed inside messages to enable various
+message-passing based idioms. These provide a tightly coupled localized
+models inside the same address space.<br>
+&nbsp;&nbsp;&nbsp; From channel's design perspective, these localized
+communication primitives can be encoded as special kinds of binding set
+of senders (named_out) and
+receivers (named_in). They are "unnamed", not set up thru name matching
+in name space. For example in C++CSP, there are One2OneChannel,
+Any2OneChannel and One2AnyChannel. One2OneChannel can be encoded as the
+binding of one "unnamed_out" and one "unnamed_in"; Any2OneChannel can
+be encoded as the binding of a group of "unnamed_out" and a single
+"unnamed_in"; One2AnyChannel can be encoded as the binding of a single
+"unnamed_out" and a group of "unnamed_in" (please note that CSP
+requires synchronous rendezvous of sender and recevier which can be
+implemented thru a
+special dispatcher). There is a similar case with normal event
+dispatching systems
+where application code directly attaches event receivers (slots) to
+event sources (signals), not thru name-matching in name space.<br>
+&nbsp;&nbsp;&nbsp; Channel provides generic functions to set up
+and break binding among any pair of named_out and named_in:<br>
+<span style="font-weight: bold; font-style: italic;">&nbsp;&nbsp;&nbsp;
+template &lt;typename name&gt; void bind(name *named_out, name
+*named_in);</span><br style="font-weight: bold; font-style: italic;">
+<span style="font-weight: bold; font-style: italic;">
+&nbsp;&nbsp;&nbsp; template &lt;typename name&gt; void unbind(name
+*named_out, name *named_in);</span><br>
+&nbsp;&nbsp;&nbsp; By means of these functions, we can setup any
+imaginable bindings (1-N, N-1, N-M) among named_out and named_in.<br>
+&nbsp;&nbsp;&nbsp; Various message passing systems use different idioms
+or patterns of binding sets. Channel provides the following
+sample tightly coupled idioms thru "unnamed" in/out objects (<a
+ href="../../../boost/channel/unnamed_in_out.hpp">unnamed_in_out.hpp</a>):
+<br>
+<ul>
+ <li>Ports are objects with internal message buffering. Applications
+can
+send messages thru ports. Choice/Join arbiters coordinate how messages
+are consumed from ports and how handlers are called. (similar to CCR's
+ports)<br>
+ </li>
+ <li>Signals and Slots objects provide direct support for "localized"
+event dispatching. Slots objects identify the bindings between&nbsp;
+event source (signal) and callbacks; Deletion of either signal or slots
+will remove these bindings automatically.<br>
+ </li>
+</ul>
+&nbsp;&nbsp;&nbsp; Ports and Signals are simple template specialization
+of
+Named_Out and Named_Ins with null_id (unnamed!) and proper dispatchers
+(pull dispatcher for Port and push dispatcher for Signal/Slot). They
+can be customized by template parameters just as normal
+channel entities, e.g. Port can be customized with different queue
+types and Signal/Slot can be customized with different dispatching
+algorithms (broadcast, round-robin ...). Ports and Signals are well
+integrated with "named" entities:<br>
+<ul>
+ <li>Ports can participate in the same Choice/Join arbiter as
+"ids/names"; so arbiters can coordinate both local and remote messages.
+Some important usage of this is to implement the timeout or exception
+exit of Choice/Join. A timer generate events into a timeout port which
+can be included in a Choice. Choice could receive timeout message and
+exit when it happens.</li>
+ <li>Ports and Signals can later be attached to names in name space;
+so they become normal "named" entities and can enjoy binding thru
+name-matching and remote message passing as usual.</li>
+</ul>
+<div style="margin-left: 40px;"></div>
+<h4><a class="mozTocH4" name="mozTocId970853"></a>4.5 Application
+architecture and integration</h4>
+Channel is intentionally designed to be indepedent of threading models
+and connection strategies. So channel can be helpful to implement
+various applications with different designs of threading and connection:<br>
+<ul>
+ <li>event dispatching/callbacks based applications: such as GUI
+frameworks where there is no explicit mentioning of thread (single
+threaded)</li>
+ <li>asynchronous I/O based server applications: such as servers based
+on Boot.Asio, eventlib or libasync; in these kind of servers, there may
+be single or a few "main" threads driving the reactive or proactive
+main event loop; all threads play equal role.</li>
+ <li>active objects or communicating processes based design: this is
+the original target applications of Channel; they are popular in large
+scale distributed embedded systems design. In these designs, the whole
+system is partitioned into many interacting processes/threads; each of
+which performs a specific functionality (defined mostly by its
+publishing/sending names-set and subscribing/receiving names-set),
+maintains/own a part of system
+state (finite state machines) and interacting with each other ONLY thru
+message passing. No one can directly change the system state owned by
+another process/thread; Change requests can only be sent to owner
+process/thread as messages and owner can reasonably reject them.</li>
+ <li>thread pool based server design: In these systems, servers' job
+can be partitioned into scheduling units - tasks, which are dispatched
+to a dedicated pool of threads for execution. There are two kind of
+threads in system: <br>
+ </li>
+ <ul>
+ <li>master threads: listening for incoming client requests and
+dispatch tasks to pool</li>
+ <li>worker threads: member of pool, waiting for tasks and execute
+them</li>
+ </ul>
+</ul>
+Channel's independence of threading and connection also makes it easy
+to integrate Channel with exising server applications of various
+designs. Basically we'll write wrapper classes to glue channel to
+existing server mechanisms:<br>
+<ul>
+ <li>"executors" wrappers to integrate channel's asynchronous
+operations execution into servers' threading model</li>
+ <li>"streams" wrappers to implement remote channel connection thru
+server existing connection strategies<br>
+ </li>
+</ul>
+<div style="margin-left: 40px;"></div>
+<hr style="width: 100%; height: 2px;">
+<h3><a class="mozTocH3" name="mozTocId39115"></a>5. Classes</h3>
+<h4><a class="mozTocH4" name="mozTocId591675"></a>5.1 name space related</h4>
+<h4><a class="mozTocH4" name="mozTocId899602"></a>5.1.1 name spaces</h4>
+&nbsp;&nbsp;&nbsp; The major purpose of name space is to set up the
+bindings among named_outs and named_ins based on id-matching and
+scoping rules. There are 3 kinds of name spaces:<br>
+<ul>
+ <li><a href="../../../boost/channel/name_spaces/linear_name_space.hpp">linear
+name_space (with exact matching)<br>
+ </a></li>
+ <li><a
+ href="../../../boost/channel/name_spaces/hierarchical_name_space.hpp">hierarchical
+name_space (with prefix matching)</a><br>
+ </li>
+ <li>associative
+name_space (implemented as linear name space with associative matching)<br>
+ </li>
+</ul>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name space API are fixed, must support
+the following methods:<br>
+<div style="margin-left: 40px;">void bind_named_out(name *n);<br>
+void unbind_named_out(name *n);<br>
+void bind_named_in(name *n);<br>
+void unbind_named_in(name *n);<br>
+</div>
+<h4><a class="mozTocH4" name="mozTocId828224"></a> 5.1.2 id_type and
+id_trait </h4>
+As described above, various id_types (integer, string, PODS, pathnames,
+tuples etc) can be used for different applications and name spaces. To
+support
+name binding operations, id_type should support the following
+operations:<br>
+<ul>
+ <li>id_types used for linear name space support operator&lt;() for
+linear "ordering" among ids</li>
+ <li>id_types used for hierarchical name space support "containment"
+operation to decide among 2 ids which will contain the other</li>
+ <li>all id_type should define "match" operation in its id_trait
+classes:</li>
+</ul>
+<ul>
+ <ul>
+ <li>For ids in linear name space, we define exact match in <a
+ href="../../../boost/channel/name_spaces/linear_id_trait.hpp">linear_id_trait</a><br>
+ </li>
+ <li>For ids in hierarchical name space, we define prefix match in <a
+ href="../../../boost/channel/name_spaces/hierarchical_id_trait.hpp">hierarchical_id_trait</a>
+(ie.
+"/sports/*" will match both "/sports/basketball" and
+"/sport/baseball")&nbsp; <br>
+ </li>
+ <li>For ids in associative name space, ids will be either regex or
+tuples
+containing
+multiple fields; for regex ids, regex pattern matching is used; for
+tuple ids, 2 ids will match if all their fields match or some
+fields are wildcards. regex ids and tuple ids are defined in <a
+ href="../../../boost/channel/name_spaces/assoc_id_trait.hpp">assoc_id_trait</a>.<br>
+ </li>
+ </ul>
+</ul>
+To be able to use primitive data types as name space ids, containment
+and matching operations are defined inside id_trait classes.<br>
+For channels to be connected with remote name spaces, non-primitive
+id_type should define serialize() methods to allow ids be marshaled and
+demarshaled using Boost.Serialization.<br>
+Id_trait classes also contain definitions of the following 8 system ids:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static id_type channel_conn_msg;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static id_type channel_disconn_msg;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static id_type
+init_subscription_info_msg;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static id_type connection_ready_msg;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static id_type subscription_info_msg;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static id_type unsubscription_info_msg;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static id_type publication_info_msg;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static id_type unpublication_info_msg.<br>
+These ids are used internally for channel name space management.
+Applications can also subscribe to these system ids to receive
+notifications about name space changes and add application logic to
+react properly; for example:<br>
+<ul>
+ <li>start communication when remote channels connect in or remote
+peers join
+in.<br>
+ </li>
+ <li>perform special handlings when channel disconnect.<br>
+ </li>
+</ul>
+<h4><a class="mozTocH4" name="mozTocId856863"></a>5.1.3 name and name
+binding callback</h4>
+Class name
+is an internal class; application code will not use names
+directly however. Applications will instantiate <a
+ href="../../../boost/channel/named_in_out.hpp">named_out
+and named_in</a> to set up message passing logic.<br>
+Class name
+contains the most important information in name space: id,
+scope, membership and binding_set.<br>
+When Named_In and Named_Out are instantiated, a name binding callback
+can be specified to allow applications to be notify when peers bind
+to the name. Its signature :<br>
+<span style="font-weight: bold;">void binding_callback(name *n,
+typename name::binding_event e).</span><br>
+<h4><a class="mozTocH4" name="mozTocId915384"></a>5.1.4 named_out and
+named_in; publisher and subscriber</h4>
+Class <a href="../../../boost/channel/named_in_out.hpp">named_out
+and named_in</a> are where name space and dispatcher meets.
+In fact, they inherit from both class name and dispatcher.<br>
+Class <a href="../../../boost/channel/named_in_out.hpp">named_out_bundle
+and named_in_bundle</a> are helper classes to
+conveniently use a group of name bindings.<br>
+On top of named_out_bundle and named_in_bundle, class <a
+ href="../../../boost/channel/pub_sub.hpp">publisher
+and
+subscriber</a> provide direct support for publish/subscribe model.<br>
+<h4><a name="unnamed_class"></a>5.1.5 <a
+ href="../../../boost/channel/unnamed_in_out.hpp">unnamed in/out: port
+and signal/slot</a></h4>
+Class port provides direct support for localized tightly coupled
+message passing model. Port inherit pull_dispatcher's sender which
+inherit queue class. So port can be used directly as a message queue
+and application can put messages into it and get messages from it.
+However ports are mostly used with choice/join arbiters.<br>
+Class signal/slot support localized "unnamed" event dispatching model.<br>
+<h4><a class="mozTocH4" name="mozTocId750531"></a><a
+ href="../../../boost/channel/binder.hpp">5.1.6
+binder, filter and translator</a></h4>
+Filters and translators are defined to control name space changes
+during name space connection and binding. Binders contain both filters
+and translators and are specified in channel connection function calls.
+APIs and dummy operations of binders, filters and translators are
+defined here,<br>
+<h4><a class="mozTocH4" name="mozTocId985604"></a>5.2 dispatching
+related</h4>
+<h4><a class="mozTocH4" name="mozTocId308124"></a>5.2.1 dispatchers</h4>
+As we discussed above, dispatchers have 2 parts: sending and receiving
+algorithms.
+Dispatcher's API are not fixed, depending on whether it uses push or
+pull model and it is synchronous or asynchronous. The following sample
+dispatchers are provided:<br>
+<ul>
+ <li><a
+ href="../../../boost/channel/dispatchers/push_dispatcher_base.hpp">push
+dispatchers</a>:<br>
+ </li>
+ <ul>
+ <li><a
+ href="../../../boost/channel/dispatchers/broadcast_dispatcher.hpp">broadcast_dispatcher</a>:
+ <br>
+ </li>
+ </ul>
+</ul>
+<div style="margin-left: 80px;">senders/named_out broadcast
+messages/events to all bound receivers/named_in. This is the most
+common event dispatching semantics.<br>
+</div>
+<ul>
+ <ul>
+ <li><a
+ href="../../../boost/channel/dispatchers/round_robin_dispatcher.hpp">round_robin_dispatcher</a>:&nbsp;</li>
+ </ul>
+</ul>
+<div style="margin-left: 80px;">senders/named_out send messages/events
+to bound receivers/named_in in round-robin manner. Simple server load
+balance can be achieved thru this.<br>
+</div>
+<ul>
+ <ul>
+ <li><a
+ href="../../../boost/channel/dispatchers/always_1st_dispatcher.hpp">always_latest_dispatcher</a>:</li>
+ </ul>
+</ul>
+<div style="margin-left: 80px;">senders/named_out always send
+messages/events to the latest bound receivers/named_in. This is a
+dispatcher to simulate plan9's union directory (though most semantics
+is achieved thru nam space binding/connection). Suppose we use an id
+(such as "/dev/printer") represent a printer resource. To print
+something, we send a message to that id. On another machine there is
+another printer bound to the same id in their local channel.&nbsp; To
+be able to use the 2nd printer, we could connect or mount the remote
+channel to local channel. Then if always_latest_dispatcher is used, all
+following printouts (sent to&nbsp; /dev/printer) will come from the
+remote printer. The local printer will get
+print messages again after the channels disconnect.<br>
+</div>
+<ul>
+ <li><a
+ href="../../../boost/channel/dispatchers/pull_dispatcher_base.hpp">pull
+dispatcher</a>:</li>
+</ul>
+<div style="margin-left: 40px;">In pull dispatcher, messages/events are
+buffered inside channel at Named_Outs, high level messaging
+coordination patterns - "arbiters" are defined at Named_Ins to decide
+when and how messages are pulled from Named_Outs and consumed by
+receiving threads or callbacks.<br>
+</div>
+<ul>
+ <ul>
+ <li><a href="../../../boost/channel/dispatchers/arbiters_sync.hpp">synchronous
+arbiters (choice_sync, join_sync)</a>:</li>
+ </ul>
+</ul>
+<div style="margin-left: 80px;">Both senders and
+receivers are active threads. Messages are buffered inside channel at
+sender/named_out side and sending thread returns right away. Receiving
+threads block waiting messages at synchronous arbiters. They unblock
+and process messages when messages are
+available at named_outs and their associated arbiters fired.<br>
+</div>
+<ul>
+ <ul>
+ <li><a href="../../../boost/channel/dispatchers/arbiters_async.hpp">asynchronous
+arbiters (choice_async, join_async)</a>:</li>
+ </ul>
+</ul>
+<div style="margin-left: 80px;">Callbacks are registered with
+asynchronous arbiters. Messages are buffered inside channel at
+sender/named_out
+side and sending thread will notify receivers before return. Depending
+on arriving messages, asynchronous arbiters will decide which callbacks
+will fire; and schedule them to execute in an executor. Join arbiters
+will quarantee that
+related messages are consumed atomically.<br>
+</div>
+<h4><a class="mozTocH4" name="mozTocId187818"></a>5.2.2 messages</h4>
+<ul>
+</ul>
+<div style="margin-left: 40px;">Application message/event data can be
+any data type : primitives, structs and classes.&nbsp; For remote
+message passing, proper serialization functions must be defined using
+Boost.Serialization:<br>
+<ul>
+ <li>free serialization functions for non-intrusive serialization<br>
+ </li>
+ <li>message struct and classes can define serialize() methods; and
+should
+define default construtor for serialization, otherwise
+save_construct/load_construct need to be overwritten.</li>
+</ul>
+Please refer to the tutorials for sample message definitions.<br>
+</div>
+<h4><a class="mozTocH4" name="mozTocId953831"></a>5.2.3 queues</h4>
+Queues are used for inside channel message buffering. One of pull
+dispatcher's template parameter is queue type. Various applications can
+specify and use different queue types based on applications'
+requirements and queues' capability. Queues will support the following
+common interface:<br>
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void
+put(elem_type &amp; e);</span><br style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void
+get(elem_type &amp; e);</span><br style="font-weight: bold;">
+<br>
+The following sample queue implementations are or will be provided:<br>
+<ul>
+ <li>unbounded_queue:
+a simple synchronized queue with unlimited buffer size, so senders are
+never blocked.<br>
+ </li>
+ <li>bounded_queue:
+a synchronized queue bounded with a maximum number of buffered
+messages; when queue buffer is full, the senders will be blocked till
+some messages are removed from the queue.<br>
+ </li>
+ <li>dropping_queue:
+a synchronized queue bounded with a maximum number of buffered
+messages; when queue buffer is full, newly added messages will force
+oldest messages to be dropped and senders will never be blocked.<br>
+ </li>
+ <li>flow_controlled_queue (coming): a flow controlled queue
+supporting priority based message enqueue and dequeue; modelled after
+ACE's message queue<br>
+ </li>
+ <li>timed_queue (coming): modelled after JavaSpace's "Lease on
+entries" mechanism; for each message inserted into queue, a time-out
+value will be specified; the message will be dropped if it is not
+consumed by receivers when its time-out expires.<br>
+ </li>
+</ul>
+<ul>
+</ul>
+<h4><a class="mozTocH4" name="mozTocId573559"></a>5.2.4 executors<br>
+</h4>
+Executors allow us avoid explicitly spawning threads for asynchronous
+operations; thus avoiding thread life cycle overhead and resource
+consumption. &nbsp; Executors should support the following common
+interface to allow application register asynchronous operations to be
+executed later and cancel this registration:<br>
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+template &lt;typename task_type&gt;</span><br style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+async_task_base * execute(task_type
+task);</span><br style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool
+cancel(async_task_base *task);</span><br style="font-weight: bold;">
+<br>
+The following sample executors are provided:<br>
+<ul>
+ <li>in_place_executor:
+just run the asynchronous task in current
+thread and current calling context.<br>
+ </li>
+ <li>delayed_executor:
+asynchronous task is queued and calling thread
+returns. The queued tasks can be executed later by calling run().<br>
+ </li>
+ <li>asio_executor:
+a wrapper over asio's io_service.post() method.
+asynchronous tasks will be dispatched to asio's main thread to execute.<br>
+ </li>
+ <li><a
+ href="../../../boost/channel/executors/thread_pool_executor.hpp">thread_pool_executor</a>:
+a dedicated pool of threads executing
+submited tasks.</li>
+ <li>threadpool_executor:
+a wrapper over Philipp Henkel's <a
+ href="http://threadpool.sourceforge.net">threadpool</a> library<br>
+ </li>
+</ul>
+There are two places to plugin executors in framework:<br>
+<ul>
+ <li>channel-wide.</li>
+</ul>
+<div style="margin-left: 40px;">specifying an executor when channel is
+created. By default, all asynchronous operations (event/message
+callbacks, name binding callbacks,...) will be scheduled and executed
+in this executor.<br>
+</div>
+<ul>
+ <li>where callbacks are bound.</li>
+</ul>
+<div style="margin-left: 40px;">For example, some applications may want
+to give different priorities to handling different event ids (or
+message types). We can create several
+executors with their threads running in different scheduling priority;
+and specify proper executors when named_in and named_out are created.<br>
+</div>
+<h4><a class="mozTocH4" name="mozTocId872320"></a>5.3 connection related</h4>
+<h4><a class="mozTocH4" name="mozTocId460401"></a>5.3.1&nbsp; global
+functions for connecting channels </h4>
+There are 3 overloaded global functions for connecting channels:<br>
+<ul>
+ <li>one for connecting 2 local channels of the same type:</li>
+</ul>
+<div style="margin-left: 40px;"><span style="font-weight: bold;">template
+&lt;typename channel&gt;<br>
+typename channel::connection*
+connect(channel &amp;peer1, channel &amp;peer2,</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; typename channel::binder_type *binder1 = NULL, </span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; typename channel::binder_type *binder2 = NULL)</span><br
+ style="font-weight: bold;">
+connecting 2 local channels so that peers at both channels can
+communicate to each other transparently. binders1 (containing filter
+and translator) defines how channel peer1's name space will be changed.
+<br>
+</div>
+<ul>
+ <li>&nbsp;one for connecting 2 local channels of different types:</li>
+</ul>
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+template &lt;typename channel1, typename channel2&gt;</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+typename channel1::connection* connect(channel1 &amp;peer1, channel2
+&amp;peer2,</span><br style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; typename channel1::binder_type *binder1 = NULL, </span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; typename channel2::binder_type *binder2 = NULL);</span><br>
+<ul>
+ <li>one for connecting local channel
+to remote channels (streams):</li>
+</ul>
+<div style="margin-left: 40px;"><span style="font-weight: bold;">template
+&lt;typename channel, typename stream_t&gt;<br>
+connection*
+connect(channel &amp;peer, </span><br style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;
+stream_t * stream, </span><br style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; bool
+active,</span><br style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;
+typename channel::binder_type *binder = NULL)<br>
+</span></div>
+<h4 style="margin-left: 40px;"><span class="mozTocH4"></span><span
+ class="mozTocH4"></span><span style="font-weight: normal;">Normally a
+connection to remote channel
+is represented as a "stream" objtect (tcp/ip socket connection or
+shared memory connection). This connect() function is used to connect a
+local channel to a remote channel represented by the stream.</span><br>
+</h4>
+<h4><a class="mozTocH4" name="mozTocId964803"></a>5.3.2 connection</h4>
+Class connection
+represent the connection between 2 channels. Deleting a connection
+object will break the connection between 2 channels; and deleting any
+of the member channels will result in connection object being
+deleted.&nbsp; <br>
+<h4><a class="mozTocH4" name="mozTocId581357"></a>5.3.3 peer and
+interface</h4>
+Class peer defines the
+common base class of connection proxies such as interface and streams.
+Normally application code will not need class peer, unless creating a
+new channel connection mechanism such as SOAP based streams.<br>
+Class interface is
+the proxy between its owner channel and a peer channel. It contains all
+the logic for how remote name space will be "mounted" at local name
+space and how local name space change will propagate to the remote name
+space and vice versa. It is here that filters filt message ids and
+translators translate incoming and outgoing messages<br>
+<h4><a class="mozTocH4" name="mozTocId567580"></a>5.3.4 streams</h4>
+Streams are proxies for remote channels and wrap transport mechanisms.
+The following streams are and will be provided:<br>
+<ul>
+ <li>asio_stream:
+a stream class using Boost.Asio socket to connect to peer channels.<br>
+ </li>
+ <ul>
+ <li>asio_connector:
+a helper class providing 2 functions:</li>
+ <ul>
+ <li>publishing local channels at specific ports (so that remote
+peer channel can connect)</li>
+ </ul>
+ </ul>
+</ul>
+<div style="margin-left: 120px;"><span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+template &lt;typename sock_conn_handler&gt;</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void
+async_accept(int port, sock_conn_handler hndl) ;</span><br>
+</div>
+<ul>
+ <ul>
+ <ul>
+ <li>connecting to remote channels at their publication addresses
+(host, port):</li>
+ </ul>
+ </ul>
+</ul>
+<div style="margin-left: 120px;"><span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+template &lt;typename sock_conn_handler&gt;</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void
+sync_connect(std::string host, std::string port, sock_conn_handler
+hndl) ;</span><br style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+template &lt;typename sock_conn_handler&gt;</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void
+async_connect(std::string host, std::string port, sock_conn_handler
+hndl) ;</span><br>
+</div>
+<ul>
+ <li>shmem_stream:
+a stream class using Boost.Interprocess shared memory message queues to
+connect to channels in a separate process inside the same node.<br>
+ </li>
+ <li>soap_stream (coming): use SOAP protocol to connect to remote
+channels<br>
+ </li>
+</ul>
+<h4><a class="mozTocH4" name="mozTocId711260"></a>5.3.5 marshaling
+registry</h4>
+<h4><a class="mozTocH4" name="mozTocId128213"></a>5.4 platform
+abstraction policy and synchronization policy<br>
+</h4>
+<h4><a class="mozTocH4" name="mozTocId345412"></a>5.4.1 platform
+abstraction</h4>
+Platform independence is one key factor for Channel's portability.
+Channel's internal implementation depends on some system facilities,
+such as
+mutex, condition, timers and logging. Various platforms have different
+levels of support and different APIs for these system facilities. Some
+boost libraries already provide nice wrappers over system facilities
+such as Boost.Thread and Boost.Date_Time. However for some system
+functions, boost doesn't have an approved library yet, such as logging.
+Class boost_platform
+is a platform policy class defined to support platform independence.
+All the system facilities Channel uses for internal implementation are
+either defined as nested classes wrapped inside it or its static
+methods. To port Channel to a different software/hardware platform, one
+major work is to reimplement the platform policy class using native
+functions (another is coping with compiler difference). Take logging
+for example, in future if we have a portable boost library for it, we
+could redefine boost_platform class to interface to it. Otherwise for a
+Windows specific application, we can implement platform class logging
+API using Windows event log facility; for linux based application, we
+can use syslog.<br>
+<h4><a class="mozTocH4" name="mozTocId405486"></a>5.4.2 synchronization
+policy</h4>
+Modeled after ACE's synchronization wrapper facades (ACE_Thread_Mutex,
+ACE_Null_Mutex, ACE_Null_Condition,...) and Null Object&nbsp; pattern,
+two "no-op" classes null_mutex and null_condition are defined. They
+follow the same interface as their counterparts in Boost.Thread and
+implement the methods as "no-op" inline functions, which can be
+optimized away by compilers. Also modeled after ACE's Synch_Strategy
+classes (MT_SYNCH, NULL_SYNCH) and Strategized Locking pattern, two
+synchronization policy classes are defined: <a
+ href="../../../boost/channel/platforms/synch_policy.hpp">mt_synch and
+null_synch</a>. mt_synch is for multithreaded applications which
+contains Boost.Thread's mutex/condition classes as nested types.
+null_synch is for single-threaded applications whose nested types are
+"null" types we mentioned above. synchronization policy class is one of
+channel template parameters which we can use either mt_synch for
+channel to be used in multithreaded application or use null_synch for
+single threaded application (such as event dispatching) without
+incurring overhead. The usage is different from the above mentioned
+platform independence, it is for application requirement and efficiency.<br>
+<br>
+<hr style="width: 100%; height: 2px;">
+<h3><a class="mozTocH3" name="mozTocId283551"></a>6. Class Concepts and
+How to extend
+Channel framework</h3>
+One essential task of Generic Programming is to find the set of
+requirements for each class/type so that the template framework can
+compile and operate properly. These requirements are called "concepts"
+and include the following:<br>
+<ul>
+ <li>valid expressions</li>
+ <li>associated types</li>
+ <li>invariants</li>
+ <li>complexity guarantees</li>
+</ul>
+To extend Channel framework, new classes / types must satisfy the
+requirements of its "concept" so that code can compile and run.<br>
+In the following discussions, we classify 2 kinds of requirements:<br>
+<ul>
+ <li>Primary requirements: must be satisfied for the main framework
+design idea<br>
+ </li>
+ <li>Secondary requirements: should be satisfied per local
+implementations<br>
+ </li>
+</ul>
+<h4><a class="mozTocH4" name="mozTocId162285"></a>6.1 id_type and
+id_trait</h4>
+<ol>
+ <li>Primary requirements</li>
+</ol>
+<div style="margin-left: 40px;">For each id_type, a partially
+specialized template class id_trait should be defined with the
+following definitions:<br>
+<ul>
+ <li>nested/associated types: id_type</li>
+ <li>system internal message ids/names:</li>
+</ul>
+<div style="margin-left: 40px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static
+id_type channel_conn_msg;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static id_type channel_disconn_msg;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static id_type
+init_subscription_info_msg;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static id_type connection_ready_msg;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static id_type subscription_info_msg;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static id_type unsubscription_info_msg;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static id_type publication_info_msg;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static id_type unpublication_info_msg<br>
+</div>
+<ul>
+ <li>match() method: define the id-matching algorithm</li>
+ <li>serialize() method: marshaling/demarshaling method for passing id
+to remote channel (only need for user defined class / structs as
+id_type) &nbsp;&nbsp; <br>
+ </li>
+ <li>for the code to work in Windows/VC++, the class definition should
+contain BOOST_CHANNEL_DECL. </li>
+</ul>
+</div>
+<ol start="2">
+ <li>Secondary requirements</li>
+</ol>
+<div style="margin-left: 40px;">Per implementations, there are the
+following secondary requirements:<br>
+<ul>
+ <li>linear name space</li>
+</ul>
+<div style="margin-left: 40px;">Since current implementation use
+std::map to implement linear name space, user defined id_type must
+define the following methods to satisfy the requirements of std::map :<br>
+bool operator&lt; (const struct_id &amp;id) const<br>
+bool operator== (const struct_id &amp;id) const<br>
+bool operator!= (const struct_id &amp;id) const<br>
+</div>
+<ul>
+ <li>hierarchical name space</li>
+</ul>
+<div style="margin-left: 40px;">Hierarchical name space is implemented
+using trie data structure; to support trie related operations, id_trait
+should add the following definitions:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static token_type
+root_token;&nbsp;&nbsp;&nbsp;&nbsp; //just a name for root trie node,
+not in name_space<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static token_type wildcard_token;<br>
+&nbsp;&nbsp;&nbsp; &nbsp; static bool id1contains2(id_type id1, id_type
+id2)<br>
+<br>
+</div>
+</div>
+<div style="margin-left: 40px;">Here is <a href="assoc_id_text.html">a
+detailed description of how to add id_type and id_trait for associative
+name_space based on Linda-style associative lookup</a>.<a
+ href="assoc_id_text.html"></a><br>
+</div>
+<h4><a class="mozTocH4" name="mozTocId605583"></a>6.2 name space</h4>
+<ol>
+ <li>Primary requirements</li>
+</ol>
+<div style="margin-left: 40px;">
+<ul>
+ <li>nested/associated types:</li>
+</ul>
+<div style="margin-left: 40px;">id_type;<br>
+id_trait;<br>
+synch_policy;<br>
+executor;<br>
+platform;<br>
+name;<br>
+</div>
+<ul>
+ <li>name space management methods:</li>
+</ul>
+<div style="margin-left: 40px;">void bind_named_out(name *n)<br>
+void unbind_named_out(name *n)<br>
+void bind_named_in(name *n)<br>
+void unbind_named_in(name *n)<br>
+</div>
+</div>
+<ol start="2">
+ <li>Secondary requirements<br>
+ </li>
+</ol>
+<div style="margin-left: 40px;">name space query related:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; template &lt;typename Predicate&gt;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void bound_ids_for_in(Predicate p,
+std::vector&lt;id_type&gt; &amp;ids)<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; template &lt;typename Predicate&gt;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void bound_ids_for_out(Predicate p,
+std::vector&lt;id_type&gt; &amp;ids)<br>
+executor_type * get_exec(void)<br>
+<br>
+</div>
+Please refer to <a
+ href="../../../boost/channel/name_spaces/linear_name_space.hpp">linear_name_space.hpp</a>
+and
+hierarchical_name_space.hpp
+for detailed code.<br>
+<h4><a class="mozTocH4" name="mozTocId379587"></a>6.3 dispatcher</h4>
+Dispatchers are used as policy classes for channel template. As
+discussed above, each dispatcher contains 2 algorithms: sending and
+receiving.<br>
+Dispatchers' API are not fixed, depending on whether it uses push or
+pull model and it is synchronous or asynchronous. The API of provided
+dispatchers follow the general convention of providing various
+send() and recv().
+<ol>
+ <li>Primary requirements</li>
+</ol>
+<div style="margin-left: 40px;">Each dispatcher class should define 2
+nested types:<br>
+<ul>
+ <li>sender </li>
+ <li>recver</li>
+</ul>
+These nested types are the parent classes of named_in and named_out.<br>
+Inside dispatcher nested types (sender and receiver classes),
+dispatching algorithms retrieve name binding set from associated "name"
+object.<br>
+</div>
+<ol start="2">
+ <li>Secondary requirements</li>
+</ol>
+<div style="margin-left: 40px;">For dispatchers which are used in
+channel types with possible remote connections, the nested receiver
+classes will expect the callback function's signature as :<br>
+&nbsp;&nbsp;&nbsp; void callback(id_type id,
+boost::shared_ptr&lt;void&gt; msg).<br>
+This requirement is because of the implementation of "interface" class.<br>
+<br>
+</div>
+Here is a <a href="../example/sample_dispatcher/dispatcher_text.html">detailed
+description of a
+sample pull dispatcher</a>.<br>
+<div style="margin-left: 40px;"></div>
+<h4><a class="mozTocH4" name="mozTocId872924"></a>6.4 executor</h4>
+<h4><a class="mozTocH4" name="mozTocId760775"></a>6.5 queue</h4>
+<h4><a class="mozTocH4" name="mozTocId441870"></a>6.6
+streams/connectors (or integrate into new architecture)</h4>
+<br>
+<hr style="width: 100%; height: 2px;">
+<h3><a class="mozTocH3" name="mozTocId631535"></a>7. Compare Channel to
+others (plan9, STL)</h3>
+<h4><a class="mozTocH4" name="mozTocId547030"></a>7.1 Compare
+Unix/Plan9/Inferno file-system name space and Channel's name space</h4>
+In Unix and other OSes, file system provides the machine-wide
+hierarchical name space for most system resources. Applications
+use&nbsp; resources mostly by the standard file system calls:
+open/close/read/write. By mounting remote file-systems, remote name
+space (and resources) can be imported and accessed transparently by
+local applications.<br>
+Plan9/inferno push this idea further by 3 ideas: 1. all resources are
+represented as files. 2. each process has its own private name space
+which can be customized according to applications' requirements. 3. an
+uniform protocol - 9P is used for all remote message passings.[1][2]<br>
+<br>
+Channel provides a process local name space for asynchronous message
+passing and event dispatching. Compared to unix/plan9 name space:<br>
+<ul>
+ <li>Channel's name space is a light-weight user-space data structure;
+A process can create and use multiple name spaces for different
+purpose.
+Unix(plan9/inferno)'s name space is a more fundamental kernel feature
+well integrated with all system facilities (shell, window system,..).
+Each process has only one. </li>
+ <li>file-system name spaces are based on function-call (local or
+remote procedure call) or (request-response) semantics. Channel's name
+space is for asynchronous message passing or one way request.</li>
+ <li>file-system name spaces are based on normal client-server model:
+file servers purely serve; ie. clients will import names from servers,
+but servers never import names from clients. Channel is peer-peer
+model; connected channels will import names from each other for
+communication.</li>
+ <li>In file-system name spaces, names refer to assumely
+stable/permanent entites (either disk files or long-running servers);
+file name spaces are relatively static, ie, a specific name mostly
+refer to
+the same resource either local or from a specific server; operations on
+names with stale/empty binding will result in serious errors. Channel
+name spaces are purely dynamic. It is totally valid to have a Named_Out
+object in name space without bound Named_In object (since message
+subscribers may join in later). The binding of names (bound senders or
+receivers) can be different between this and next invocations. Just as
+RobinMilner has clarified [3]: &nbsp;&nbsp;&nbsp; <br>
+ </li>
+</ul>
+<div style="margin-left: 40px;">"... is built upon the idea that the
+respondent to (or referent of) a name<br>
+exists no more persistently than a caller of the name. In other words,
+the notions of<br>
+calling and responding are more basic than the notions of caller and
+respondent; every<br>
+activity contains calls and responses, but to have a persistent
+respondent to x &#8211; one that<br>
+responds similarly to every call on x &#8211; is a design choice that may be
+sensible but is<br>
+not forced."<br>
+</div>
+<ul>
+ <li>File-systems identify entities by string path names in a
+hierachical directories. Channel use different naming schemes in
+different applications:
+linear name space (such as integer ids), hierarchical name space (such
+as
+string path names), and associative name space (linda style)</li>
+ <li>in plan9, request dispatching is unicast - only one server get
+req and serve it. Channel can support various dispatching policies -
+broadcast, unicast, buffered,...</li>
+ <li>file-system api is stream oriented: byte-streams are read from
+file or write to file. channel's api is discrete message oriented.</li>
+</ul>
+<h4><a class="mozTocH4" name="mozTocId82643"></a>7.2 compare STL and
+Channel</h4>
+Some mapping between STL and Channel's concepts:<br>
+<ul>
+ <li>containers (sequence, assoc) &lt;=&gt; name spaces
+(linear/hier/assoc)</li>
+ <li>elements in container &lt;=&gt; names (unit/element in name space)</li>
+ <li>iterator_range (target of algorithms) &lt;=&gt; name binding set
+(sender-&gt;receiver(s), receiver-&gt;sender(s)) target of dispatchers</li>
+ <li>algorithms &lt;=&gt; dispatchers</li>
+</ul>
+Dispatchers are defined using named bindings of senders and receivers,
+which is provided by name space; similar to that STL algorithms are
+defined in iterator range of [begin_iterator, end_iterator), while
+iterator range is provided by containers.<br>
+<br>
+<hr style="width: 100%; height: 2px;">
+<h3><a class="mozTocH3" name="mozTocId802804"></a>8. Reference Links</h3>
+[1] <a href="http://plan9.bell-labs.com/sys/man/preface.html">Preface
+to the Second (1995) Edition (Doug McIlroy)</a><br>
+[2] <a href="http://cm.bell-labs.com/sys/doc/names.html">The Use of
+Name Spaces in Plan 9 (Rob Pike,...)</a><br>
+[3] <a href="http://www.cl.cam.ac.uk/%7Erm135/wosname.pdf">What's in a
+name? (Robin Milner)</a><br>
+[4] <a href="http://www.cl.cam.ac.uk/%7Erm135/turing.pdf">Turing,
+Computing and Communication (Robin Milner)</a><br>
+[5] <a
+ href="http://research.microsoft.com/Users/luca/Papers/Polyphony%20%28TOPLAS%29.pdf">Comega</a><br>
+[6] <a
+ href="http://research.microsoft.com/%7Etharris/scool/papers/sing.pdf">CCR</a><br>
+[7] Java's executor<br>
+[8] http://channel.sourceforge.net<br>
+<br>
+<br>
+<br>
+<platform_type><idtype ,executor_type,synchpolicy=""><name_space
+ ,platform_type=""></name_space></idtype></platform_type>
+</body>
+</html>

Added: sandbox/channel/libs/channel/doc/index.html
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/doc/index.html 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,213 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="keywords"
+ content="channel, namespace, distributed, communication, C++, template, Windows, Unix, Linux, NFS">
+ <meta name="description"
+ content="Channel - a C++ template framework for distributed computing.">
+ <title>Channel -- a C++ template framework for distributed message
+passing and event dispatching</title>
+ <link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<div id="title">
+<h1> Channel </h1>
+<h2>A Name Space Based C++ Template Framework For Asynchronous
+Distributed Message
+Passing and Event Dispatching</h2>
+</div>
+<hr>
+<div class="link-bar"><small>Overview | <a
+ href="#boost"><span style="text-decoration: underline;">Boost Channel</span></a>
+| <span style="text-decoration: underline;"></span></small><small><a
+ href="#ace">ACE Channel</a></small><small>
+| <a href="#source"><span style="text-decoration: underline;">Download
+at Sourceforge</span></a> | Supported Platforms
+| Build | <a href="#contact">Contact /
+Support</a> </small>
+</div>
+<hr>
+<div>
+<h3><a id="intro">Overview</a></h3>
+<a id="intro">
+Channel is a C++ template library to provide name spaces for
+asynchronous, distributed message passing and event dispatching.
+Message senders and receivers bind to names in name space; binding and
+matching rules decide which senders will bind to which receivers; then
+message passing and event dispatching could happen among bound senders
+and receivers.<br>
+<br>
+Channel's signature:<br>
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; template &lt;</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+typename idtype,</span><br style="font-weight: bold;">
+<span style="font-weight: bold;"></span><span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+typename platform_type = boost_platform,</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+typename synchpolicy = mt_synch&lt;platform_type&gt;,</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;"></span><span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+typename executor_type = abstract_executor, </span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;"></span><span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+typename name_space =
+linear_name_space&lt;idtype,executor_type,synchpolicy&gt;,</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+typename dispatcher =
+broadcast_dispatcher&lt;name_space,platform_type&gt; </span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; &gt;</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">&nbsp;&nbsp;&nbsp; class
+channel;&nbsp;&nbsp; </span><br>
+<br>
+Various name spaces (linear/hierarchical/associative) can be used for
+different applications. For example, we can use integer ids as names to
+send messages in linear name space, we can use path name ids (such as
+"/sports/basketball") to send
+messages in hierarchical name space and we can use regex patterns or
+Linda tuple-space style tuples to send messages in associative name
+space; User can configure name space
+easily
+by setting a channel template parameter.<br>
+<br>
+Channel's other major components are dispatchers; which dispatch
+messages/events from senders to bounded receivers. Dispatcher is also a
+channel template parameter. </a>Sample dispatchers includes :
+synchronous broadcast dispatcher,
+buffered asynchronous dispatchers,...<br>
+<br>
+Name space and dispatchers are orthogonal; they can mix and match
+together freely; just as STL algorithms can be used with any STL
+containers. <br>
+<br>
+By combining different name space and dispatching policies, we can
+achieve various models:<br>
+<ul>
+ <li>synchronous event dispatching&nbsp;&nbsp;&nbsp; </li>
+ <li>associative name space based on matching/look-up rules similar to
+Linda tuple space</li>
+ <li>asynchronous messaging model similar to Microsoft CCR
+(Concurrency Coordination Runtime)<br>
+ </li>
+</ul>
+Similar to distributed files systems, distributed channels can be
+connected or "mounted" to allow transparent distributed message
+passing. Filters and translators are used to control name space changes.<br>
+<br>
+For tightly coupled single-address-space applications/modules,
+Channel's "unnamed" in/out
+objects : ports and signal/slots support fine grained and local message
+passing model without
+the hassle of setting up a name space and assigning names.<br>
+<hr style="width: 100%; height: 2px;">
+<h3><a name="boost"></a>Boost Channel</h3>
+Boost Channel is the latest implementation of Channel framework for
+Boost. Boost provides free
+peer-reviewed portable C++ source libraries. It is emphasized that
+libraries work well with the C++ Standard Library. Boost libraries are
+intended to be widely useful, and usable across a broad spectrum of
+applications. Boost Channel is solely based on standard boost
+facilities:<br>
+<ul>
+ <li>Boost::shared_ptr for message/event data life-time management</li>
+ <li>Boost.Bind, Boost.Function for callback</li>
+ <li>Boost.Thread for synchronization</li>
+ <li>Boost.Serialization for message marshaling/demarshaling</li>
+ <li>Boost.Regex and Boost.Tuple for associative name-matching<br>
+ </li>
+ <li><big><small>Boost.Asio and Boost.Shmem are used to build
+transports among remote channels.</small></big></li>
+</ul>
+Detailed Info:<br>
+<ul>
+ <li><a
+ href="http://channel.sourceforge.net/boost_channel/libs/channel/doc/design.html">Design
+Document</a></li>
+ <li><a
+ href="http://channel.cvs.sourceforge.net/channel/boost_channel/boost_channel/">Browse
+CVS Source Code</a><br>
+ </li>
+</ul>
+<ul>
+</ul>
+</div>
+<hr>
+<div>
+<h3><a name="ace"></a>ACE Channel</h3>
+ACE Channel is the first implementation of Channel framework on top of <a
+ href="http://www.cs.wustl.edu/%7Eschmidt/ACE.html">ACE (Adaptive
+Communication Environment) </a>. ACE is a
+powerful and portable OO/C++ framework for system programming. It
+provides not only wrapper facade classes to abstract the complete OS
+facilities, but also frameworks and design patterns for developing
+multithreaded and distributed applications. ACE Channel uses several
+key ACE facilities including Reactor,
+Service Configurator, Task and Acceptor-Connector.
+<ul>
+ <li><a href="http://channel.sourceforge.net/ace_index.html">Design
+Docs and more info...</a></li>
+ <li><a href="http://channel.cvs.sourceforge.net/channel/channel/">Browse
+CVS Source Code</a><br>
+ </li>
+</ul>
+<ul>
+</ul>
+</div>
+<hr>
+<div>
+<h3><a name="source"></a><a id="source">Source Code Download<br>
+</a></h3>
+<ul>
+ <li>Download</li>
+</ul>
+All released files are hosted at sf.net: <a
+ href="http://sourceforge.net/projects/channel">http://sourceforge.net/projects/channel>
+</div>
+<hr>
+<div>
+<div>
+<h3><a name="platform"></a><a id="source">Supported Platforms<br>
+</a></h3>
+Theoretically Boost Channel can work on any platforms where Boost is
+supported, since it is solely dependent on&nbsp; Boost
+facilities.&nbsp; Currently Boost Channel is being actively developed
+and tested in the
+following platforms:<br>
+<ul>
+ <li>Linux (Fedora, Ubuntu) with gcc</li>
+ <li>Windows XP with Visual C++ 2005 Express</li>
+</ul>
+It will be tested on other platforms (Solaris, NetBSD...) when time and
+resources are available.<br>
+</div>
+<hr>
+<h3><a name="build"></a><a id="source">Build<br>
+</a></h3>
+<a href="
http://www.boost.org/more/getting_started.html">checkout boost
+cvs source code</a><br>
+download latest boost_channel_x_x.tar.gz<br>
+tar xvzf boost_channel_x_x.tar.gz<br>
+cd &lt;top directory of channel&gt;<br>
+copy subdirectory boost/channel/ to &lt;boost
+root directory&gt;/boost/<br>
+copy subdirectory
+libs/channel/ to &lt;boost root directory&gt;/libs/<br>
+cd to &lt;boost root
+directory&gt;/libs/channel/exmaple/&lt;specific samples such as
+ping_pong&gt;<br>
+bjam
+<hr>
+<h3><a id="contact">Contact / Support</a></h3>
+yigongliu@gmail.com
+</div>
+<hr>
+<div class="footer"><small>This page is maintained by: <a
+ href="yigongliu_at_[hidden]">yigongliu_at_[hidden]</a></small>
+</div>
+</body>
+</html>

Added: sandbox/channel/libs/channel/example/buffered_async_join/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/buffered_async_join/Jamfile.v2 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,21 @@
+#//
+#// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+#//
+#// Distributed under the Boost Software License, Version 1.0. (See accompanying
+#// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#//
+
+project
+ : requirements
+ <library>/boost/thread//boost_thread
+ <library>/boost/system//boost_system
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ ;
+
+obj chat_join.obj : chat_join.cpp ;
+exe chat_join : chat_join.obj ;
+obj chat_join2.obj : chat_join_2chan.cpp ;
+exe chat_join2 : chat_join2.obj ;
+obj chat_join_timer.obj : chat_join_timer.cpp ;
+exe chat_join_timer : chat_join_timer.obj ;

Added: sandbox/channel/libs/channel/example/buffered_async_join/chat_defs.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/buffered_async_join/chat_defs.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,80 @@
+//
+// chat_defs.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#ifndef CHAT_DEFS_HPP
+#define CHAT_DEFS_HPP
+
+#include <string>
+#include <boost/channel/channel.hpp>
+#include <boost/channel/executors/thread_pool_executor.hpp>
+
+using namespace std;
+using namespace boost::channel;
+
+//instantiate event channel type, using string as id_type
+typedef str_path_id<'/'> id_type;
+//use channel internal simple thread_pool_executor
+typedef thread_pool_executor<mt_synch<boost_platform> > exec_type;
+//use Philipp Henkel's threadpool library
+//#include <boost/channel/executors/threadpool_executor.hpp>
+//typedef threadpool_executor<> exec_type;
+typedef hierarchical_name_space<id_type,
+ exec_type,
+ mt_synch<boost_platform> > name_space_type;
+typedef pull_dispatcher<name_space_type,boost_platform,unbounded_que> dispatcher_type;
+typedef dispatcher_type::choice_async choice_arbiter_t;
+typedef dispatcher_type::join_async join_arbiter_t;
+//chat channel type to consume mesgs
+typedef channel<
+ id_type,
+ boost_platform,
+ mt_synch<boost_platform>,
+ exec_type,
+ name_space_type,
+ dispatcher_type
+ > chat_chan;
+//distribution channel type to distribute mesgs
+typedef channel<
+ id_type,
+ boost_platform,
+ mt_synch<boost_platform>,
+ exec_type,
+ name_space_type,
+ broadcast_dispatcher<name_space_type, boost_platform>
+> dist_chan;
+
+//define sys ids
+DEFINE_SLASH_PATH_SYS_IDS
+
+//sample subject ids in chat_chan
+//sports
+id_type basketball = "/sports/basketball";
+id_type tennis = "/sports/tennis";
+id_type baseball = "/sports/baseball";
+//financial
+id_type tax = "/financial/tax";
+id_type stock = "/financial/stock";
+id_type investment = "/financial/investment/";
+
+//a simple struct for chat msg
+struct chat_msg {
+ string data_;
+ chat_msg(char *d) : data_(d) {}
+ chat_msg() {} //have to define this for marshaling to work
+ //serialization function for chat_msg
+ template <typename Archive>
+ void serialize(Archive & ar, const unsigned int version)
+ {
+ ar & data_;
+ }
+};
+
+struct null_event {
+};
+
+#endif

Added: sandbox/channel/libs/channel/example/buffered_async_join/chat_join.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/buffered_async_join/chat_join.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,120 @@
+//
+// chat_join.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <vector>
+#include <boost/shared_ptr.hpp>
+#include "./chat_defs.hpp"
+
+//chat msg handler; print out data
+void choice_msg_hdlr1(boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << "choice_msg_hdlr1 recved: [" << msg->data_ << "]" << endl;
+}
+void choice_msg_hdlr2(boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << "choice_msg_hdlr2 recved: [" << msg->data_ << "]" << endl;
+}
+
+void join_msg_hdlr(std::vector<boost::shared_ptr<void> >& p)
+{
+ cout << "join_msg_hdlr recved " << p.size() << "msgs:\n";
+ for(size_t i=0; i < p.size(); i++) {
+ cout << "msg " << i << ":";
+ chat_msg *msg = (chat_msg *) p[i].get();
+ cout << " [" << msg->data_ << "]" << endl;
+ }
+}
+
+int main(int, char **) {
+ //create executor with one thread
+ exec_type exec(1);
+
+ //create local channel and run all channel async operations inside executor
+ chat_chan chan(&exec);
+
+ //create/bind-to subjects i am going to speak about
+ chat_chan::out basketball_o(chan, basketball);
+ chat_chan::out tennis_o(chan, tennis);
+ chat_chan::out baseball_o(chan, baseball);
+ chat_chan::out tax_o(chan, tax);
+ chat_chan::out stock_o(chan, stock);
+ chat_chan::out investment_o(chan, investment);
+
+ //subscribe to sport msgs thru choice which will
+ //fire callback mesg handlers when any mesg arrives
+ choice_arbiter_t choice(chan);
+ choice.bind(basketball, choice_msg_hdlr1);
+ choice.bind(tennis, choice_msg_hdlr2);
+ choice.bind(baseball, choice_msg_hdlr1);
+
+ //subscribe to financial msgs thru join which will
+ //only fire the callback mesg handler when all subjects
+ //have messages arriving
+ join_arbiter_t join(chan, join_msg_hdlr);
+ join.bind(tax);
+ join.bind(stock);
+ join.bind(investment);
+
+ //start sending msgs and see how choice and join work differently
+ char msg[1024];
+ bool cont = true;
+ while (cont) {
+ //speak
+ cout << "which subject : 1-basket_ball, 2-tennis, 3-baseball, 4-tax, 5-stock, 6-investment, 7-exit:\n";
+ int subject;
+ cin.getline(msg, 1024);
+ subject = atoi(msg);
+ switch(subject) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ cout << "enter your message: ";
+ cin.getline(msg, 1024);
+ switch (subject) {
+ case 1:
+ basketball_o.send(new chat_msg(msg));
+ break;
+ case 2:
+ tennis_o.send(new chat_msg(msg));
+ break;
+ case 3:
+ baseball_o.send(new chat_msg(msg));
+ break;
+ case 4:
+ tax_o.send(new chat_msg(msg));
+ break;
+ case 5:
+ stock_o.send(new chat_msg(msg));
+ break;
+ case 6:
+ investment_o.send(new chat_msg(msg));
+ break;
+ default:
+ break;
+ }
+ break;
+ case 7:
+ cont = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ exec.shut_down_wait();
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/buffered_async_join/chat_join_2chan.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/buffered_async_join/chat_join_2chan.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,123 @@
+//
+// chat_join_2chan.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <vector>
+#include <boost/shared_ptr.hpp>
+#include "./chat_defs.hpp"
+
+//chat msg handler; print out data
+void choice_msg_hdlr1(boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << "choice_msg_hdlr1 recved: [" << msg->data_ << "]" << endl;
+}
+void choice_msg_hdlr2(boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << "choice_msg_hdlr2 recved: [" << msg->data_ << "]" << endl;
+}
+
+void join_msg_hdlr(std::vector<boost::shared_ptr<void> >& p)
+{
+ cout << "join_msg_hdlr recved " << p.size() << "msgs:\n";
+ for(size_t i=0; i < p.size(); i++) {
+ cout << "msg " << i << ":";
+ chat_msg *msg = (chat_msg *) p[i].get();
+ cout << " [" << msg->data_ << "]" << endl;
+ }
+}
+
+int main(int, char **) {
+ //create executor with one thread
+ exec_type exec(1);
+
+ //create local channel and run all channel async operations inside executor
+ chat_chan chan(&exec);
+ dist_chan chan0;
+
+ connect(chan0, chan);
+
+ //create/bind-to subjects i am going to speak about
+ dist_chan::out basketball_o(chan0, basketball);
+ dist_chan::out tennis_o(chan0, tennis);
+ dist_chan::out baseball_o(chan0, baseball);
+ dist_chan::out tax_o(chan0, tax);
+ dist_chan::out stock_o(chan0, stock);
+ dist_chan::out investment_o(chan0, investment);
+
+ //subscribe to sport msgs thru choice which will
+ //fire callback mesg handlers when any mesg arrives
+ choice_arbiter_t choice(chan);
+ choice.bind(basketball, choice_msg_hdlr1);
+ choice.bind(tennis, choice_msg_hdlr2);
+ choice.bind(baseball, choice_msg_hdlr1);
+
+ //subscribe to financial msgs thru join which will
+ //only fire the callback mesg handler when all subjects
+ //have messages arriving
+ join_arbiter_t join(chan, join_msg_hdlr);
+ join.bind(tax);
+ join.bind(stock);
+ join.bind(investment);
+
+ //start sending msgs and see how choice and join work differently
+ char msg[1024];
+ bool cont = true;
+ while (cont) {
+ //speak
+ cout << "which subject : 1-basket_ball, 2-tennis, 3-baseball, 4-tax, 5-stock, 6-investment, 7-exit:\n";
+ int subject;
+ cin.getline(msg, 1024);
+ subject = atoi(msg);
+ switch(subject) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ cout << "enter your message: ";
+ cin.getline(msg, 1024);
+ switch (subject) {
+ case 1:
+ basketball_o.send(new chat_msg(msg));
+ break;
+ case 2:
+ tennis_o.send(new chat_msg(msg));
+ break;
+ case 3:
+ baseball_o.send(new chat_msg(msg));
+ break;
+ case 4:
+ tax_o.send(new chat_msg(msg));
+ break;
+ case 5:
+ stock_o.send(new chat_msg(msg));
+ break;
+ case 6:
+ investment_o.send(new chat_msg(msg));
+ break;
+ default:
+ break;
+ }
+ break;
+ case 7:
+ cont = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ exec.shut_down_wait();
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/buffered_async_join/chat_join_timer.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/buffered_async_join/chat_join_timer.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,160 @@
+//
+// chat_join_timer.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <vector>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/asio.hpp>
+#include <boost/thread.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include "./chat_defs.hpp"
+
+typedef chat_chan::port port_t;
+
+//timeout handler
+void timeout_hdlr(boost::shared_ptr<void> p)
+{
+ cout << "recv a timeout event at choice !" << endl;
+}
+//chat msg handler; print out data
+void choice_msg_hdlr1(boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << "choice_msg_hdlr1 recved: [" << msg->data_ << "]" << endl;
+}
+void choice_msg_hdlr2(boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << "choice_msg_hdlr2 recved: [" << msg->data_ << "]" << endl;
+}
+
+void join_msg_hdlr(std::vector<boost::shared_ptr<void> >& p)
+{
+ cout << "join_msg_hdlr recved " << p.size() << "msgs:\n";
+ for(size_t i=0; i < p.size(); i++) {
+ cout << "msg " << i << ":";
+ chat_msg *msg = (chat_msg *) p[i].get();
+ cout << " [" << msg->data_ << "]" << endl;
+ }
+}
+
+class my_timer
+{
+public:
+ my_timer(boost::asio::io_service& io, port_t &p)
+ : timer_(io, boost::posix_time::seconds(5)),
+ port_(p)
+ {
+ timer_.async_wait(boost::bind(&my_timer::timeout, this));
+ }
+
+ void timeout()
+ {
+ port_.send(new null_event); //send timeout notifications
+ timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(5));
+ timer_.async_wait(boost::bind(&my_timer::timeout, this));
+ }
+
+private:
+ boost::asio::deadline_timer timer_;
+ port_t &port_;
+};
+
+int main(int, char **) {
+ //create executor with one thread
+ exec_type exec(1);
+
+ //create local channel and run all channel async operations inside executor
+ chat_chan chan(&exec);
+
+ //create/bind-to subjects i am going to speak about
+ chat_chan::out basketball_o(chan, basketball);
+ chat_chan::out tennis_o(chan, tennis);
+ chat_chan::out baseball_o(chan, baseball);
+ chat_chan::out tax_o(chan, tax);
+ chat_chan::out stock_o(chan, stock);
+ chat_chan::out investment_o(chan, investment);
+
+ boost::asio::io_service io;
+ port_t timeout_port;
+ my_timer(io,timeout_port);
+ //spawn a thread to run timer
+ boost::thread t(boost::bind(&boost::asio::io_service::run, &io));
+
+ //subscribe to sport msgs thru choice which will
+ //fire callback mesg handlers when any mesg arrives
+ choice_arbiter_t choice(chan);
+ choice.bind(basketball, choice_msg_hdlr1);
+ choice.bind(tennis, choice_msg_hdlr2);
+ choice.bind(baseball, choice_msg_hdlr1);
+ choice.bind(timeout_port, timeout_hdlr);
+
+ //subscribe to financial msgs thru join which will
+ //only fire the callback mesg handler when all subjects
+ //have messages arriving
+ join_arbiter_t join(chan, join_msg_hdlr);
+ join.bind(tax);
+ join.bind(stock);
+ join.bind(investment);
+
+ //start sending msgs and see how choice and join work differently
+ char msg[1024];
+ bool cont = true;
+ while (cont) {
+ //speak
+ cout << "which subject : 1-basket_ball, 2-tennis, 3-baseball, 4-tax, 5-stock, 6-investment, 7-exit:\n";
+ int subject;
+ cin.getline(msg, 1024);
+ subject = atoi(msg);
+ switch(subject) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ cout << "enter your message: ";
+ cin.getline(msg, 1024);
+ switch (subject) {
+ case 1:
+ basketball_o.send(new chat_msg(msg));
+ break;
+ case 2:
+ tennis_o.send(new chat_msg(msg));
+ break;
+ case 3:
+ baseball_o.send(new chat_msg(msg));
+ break;
+ case 4:
+ tax_o.send(new chat_msg(msg));
+ break;
+ case 5:
+ stock_o.send(new chat_msg(msg));
+ break;
+ case 6:
+ investment_o.send(new chat_msg(msg));
+ break;
+ default:
+ break;
+ }
+ break;
+ case 7:
+ cont = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ exec.shut_down_wait();
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/buffered_async_join/sample6_text.html
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/buffered_async_join/sample6_text.html 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+</head>
+<body>
+<h2>Sample 6: Buffered Channel With Asynchronous Receivers (choice,
+join synchronization patterns)</h2>
+<br>
+This sample shows a buffered channel support asynchronous receivers
+using asynchronous coordination patterns: choice and join. The callback
+actions are dispatched thru a thread pool executor.<br>
+<br>
+More comments to come ...<br>
+<br>
+Complete source code:<br>
+chat_defs.hpp<br>
+chat_join.cpp<br>
+<br>
+</body>
+</html>

Added: sandbox/channel/libs/channel/example/buffered_sync_sendrecv/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/buffered_sync_sendrecv/Jamfile.v2 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,17 @@
+#//
+#// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+#//
+#// Distributed under the Boost Software License, Version 1.0. (See accompanying
+#// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#//
+
+project
+ : requirements
+ <library>/boost/thread//boost_thread
+ <library>/boost/system//boost_system
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ ;
+
+obj sync_send_recv.obj : sync_send_recv.cpp ;
+exe sync_send_recv : sync_send_recv.obj ;

Added: sandbox/channel/libs/channel/example/buffered_sync_sendrecv/sample5_text.html
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/buffered_sync_sendrecv/sample5_text.html 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+</head>
+<body>
+<h2>Sample 5:<span style="font-weight: bold;"> </span>Buffered Channel
+With Blocking Active Receiver
+</h2>
+<br>
+A sample shows the usage of buffered channels implemented thru a
+synchronous pull dispatcher. In this channel
+configuration, messages are buffered inside channel at sender side. The
+receiver is active, a thread blocking waiting for the arrival of
+messages at synchronous join/choice arbiters and then processing the
+messages.<br>
+<br>
+More comments to come...<br>
+<br>
+Complete source code:<br>
+sync_send_recv.cpp<br>
+<br>
+</body>
+</html>

Added: sandbox/channel/libs/channel/example/buffered_sync_sendrecv/sync_send_recv.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/buffered_sync_sendrecv/sync_send_recv.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,90 @@
+//
+// sync_send_recv.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+//
+// demo of buffered synchronous dispatcher: ie. recver is blocking waiting for data to arrive
+//
+
+#include <iostream>
+#include <string>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/channel/channel.hpp>
+
+using namespace std;
+using namespace boost::channel;
+
+//instantiate event channel type, using string as id_type
+typedef pull_dispatcher<linear_name_space<string, abstract_executor, mt_synch<boost_platform> >,
+ boost_platform> dispatcher_type;
+typedef channel<
+ string,
+ boost_platform,
+ mt_synch<boost_platform>,
+ abstract_executor,
+ linear_name_space<string, abstract_executor, mt_synch<boost_platform> >,
+ dispatcher_type
+> evt_chan;
+typedef dispatcher_type::choice_sync choice_type;
+
+//define sys ids
+DEFINE_STRING_SYS_IDS
+
+//event ids in name_space
+//sample events for sending text
+string evt_id1 = "_1st_event_to_send_text_";
+string evt_id2 = "_2nd_event_to_send_text_";
+
+//a simple struct for event data
+struct evt_data {
+ string data_;
+ evt_data(const char *d) : data_(d) {}
+};
+
+//entry point function for recving thread; print out data
+void evt_recv(choice_type & recver)
+{
+ string id;
+ boost::shared_ptr<void> p;
+ while (1) {
+ recver.recv(id, p);
+ cout << "recv event [id=" << id << "], [data=" << ((evt_data*)p.get())->data_ << "]" << endl;
+ }
+}
+
+int main(int, char **) {
+ //create event channel
+ evt_chan chan;
+
+ //bind event source to channel
+ evt_chan::out sender1(chan, evt_id1);
+ evt_chan::out sender2(chan, evt_id2);
+
+ //bind event sink to channel
+ choice_type choice(chan);
+ choice.bind(evt_id1);
+ choice.bind(evt_id2);
+
+ //a separate thread to run recver
+ boost::thread t(boost::bind(evt_recv, boost::ref(choice)));
+
+ //main thread fire events
+ char msg[1024];
+ for(int i=0;;i++) {
+ cin.getline(msg, 1024);
+ if(i % 2 == 0)
+ sender1.send(new evt_data(msg));
+ else
+ sender2.send(new evt_data(msg));
+ }
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/chat_assoc/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_assoc/Jamfile.v2 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,43 @@
+#
+# Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#
+#//
+#// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+#//
+#// Distributed under the Boost Software License, Version 1.0. (See accompanying
+#// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#//
+
+import os ;
+
+if [ os.name ] = SOLARIS
+{
+ lib socket ;
+ lib nsl ;
+}
+else if [ os.name ] = NT
+{
+ lib ws2_32 ;
+ lib mswsock ;
+}
+
+project
+ : requirements
+ <library>/boost/serialization//boost_serialization
+ <library>/boost/thread//boost_thread
+ <library>/boost/system//boost_system
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <os>SOLARIS:<library>socket
+ <os>SOLARIS:<library>nsl
+ <os>NT,<toolset>gcc:<library>ws2_32
+ <os>NT,<toolset>gcc:<library>mswsock
+ ;
+
+obj chat1.obj : chat1.cpp ;
+exe chat1 : chat1.obj ;
+obj chat2.obj : chat2.cpp ;
+exe chat2 : chat2.obj ;

Added: sandbox/channel/libs/channel/example/chat_assoc/chat1.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_assoc/chat1.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,104 @@
+//
+// chat1.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/channel/streams/asio_stream_async.hpp>
+#include "./chat_defs.hpp"
+
+//chat msg handler; print out data
+void msg_handler(id_type id, boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << msg->source_ << " speak on [" << chat_chan::id_trait::id_to_string(id) << "]:\n";
+ cout << msg->data_ << endl;
+}
+
+int main(int, char **) {
+ const char *my_name = "chatter 1";
+ try {
+ //create asio io_service
+ boost::asio::io_service io_service;
+ //create local channel and bind local event source/sink
+ chat_chan chan;
+
+ //create/bind-to subjects i am going to speak about
+ chat_chan::out robin_o(chan, robin_s_id);
+ chat_chan::out adam_o(chan, adam_s_id);
+ chat_chan::out tina_o(chan, tina_s_id);
+
+ //subscribe to subjects i am interested in listening
+ chat_chan::in smith_i(chan, smith_r_id, msg_handler);
+ chat_chan::in math_i(chan, math_r_id, msg_handler);
+
+ //register chat msg type for marshaling/demarshaling
+ chat_chan::text_marshaler_registry mar_reg;
+ mar_reg.register_default_msg_marshaler<chat_msg>();
+
+ //create asio connectors and connect to remote channel
+ asio_connector_async connector(io_service);
+ connector.async_connect("localhost", "8888", //remote channel address
+ boost::bind(asio_bind_sock_chan<chat_chan, chat_chan::text_marshaler_registry>(),
+ boost::ref(chan), boost::ref(mar_reg), _1, _2, _3));
+ //a separate thread to run io_service
+ boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));
+
+ char msg[1024];
+ bool cont = true;
+ while (cont) {
+ //speak
+ cout << "which id : 1-(robin,smith,M,art), 2-(adam,smith,M,math), 3-(tina,su,F,physics), 4-exit:\n";
+ int subject;
+ cin.getline(msg, 1024);
+ subject = atoi(msg);
+ switch(subject) {
+ case 1:
+ case 2:
+ case 3:
+ cout << "enter your message: ";
+ cin.getline(msg, 1024);
+ switch (subject) {
+ case 1:
+ robin_o.send(new chat_msg(my_name, msg));
+ break;
+ case 2:
+ adam_o.send(new chat_msg(my_name, msg));
+ break;
+ case 3:
+ tina_o.send(new chat_msg(my_name, msg));
+ break;
+ default:
+ break;
+ }
+ break;
+ case 4:
+ cont = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ connector.shutdown();
+ t.join();
+ }
+ catch (boost::system::error_code& e)
+ {
+ std::cerr << e << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/chat_assoc/chat2.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_assoc/chat2.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,133 @@
+//
+// chat2.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/channel/streams/asio_stream_async.hpp>
+#include "./chat_defs.hpp"
+
+//chat msg handler; print out data
+void msg_handler(id_type id, boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << "chan1: " << msg->source_ << " speak on [" << chat_chan::id_trait::id_to_string(id) << "]:\n";
+ cout << msg->data_ << endl;
+}
+
+void msg_handler21(id_type id, boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << "chan2.1: " << msg->source_ << " speak on [" << chat_chan::id_trait::id_to_string(id) << "]:\n";
+ cout << msg->data_ << endl;
+}
+
+void msg_handler22(id_type id, boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << "chan2.2: " << msg->source_ << " speak on [" << chat_chan::id_trait::id_to_string(id) << "]:\n";
+ cout << msg->data_ << endl;
+}
+
+/**
+ * here we are going to use the publish/subscribe API built on top of
+ * named_in/named_out
+ */
+
+int main(int, char **) {
+ const char* my_name = "chatter 2";
+ try {
+ //create asio io_service
+ boost::asio::io_service io_service;
+ //create local channels and connect them
+ chat_chan chan;
+ chat_chan chan2;
+ connect(chan, chan2);
+
+ //create/bind-to subjects i am going to speak about
+ chat_chan::publisher pub(chan);
+ pub.publish(adam_s_id);
+ pub.publish(robin_s_id);
+ pub.publish(tina_s_id);
+
+ //subscribe to subjects i am interested in listening
+ chat_chan::subscriber sub(chan, msg_handler);
+ //i am a sports fan
+ sub.subscribe(female_r_id);
+ sub.subscribe(robin_s_id);
+
+ //subscribe at chan2, using named_in/out api
+ chat_chan::in smith_i(chan2, smith_r_id, msg_handler21);
+ chat_chan::in math_i(chan2, math_r_id, msg_handler22);
+
+ //register chat msg type for marshaling/demarshaling
+ chat_chan::text_marshaler_registry mar_reg;
+ mar_reg.register_default_msg_marshaler<chat_msg>();
+
+ //create asio connectors and connect to remote channel
+ asio_connector_async connector(io_service);
+ connector.async_accept(8888, // channel address
+ boost::bind(asio_bind_sock_chan<chat_chan, chat_chan::text_marshaler_registry>(),
+ boost::ref(chan), boost::ref(mar_reg), _1, _2, _3));
+ //a separate thread to run io_service
+ boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));
+
+ //in the following code, main thread will drive the interactive loop
+ char msg[1024];
+ bool cont = true;
+ while (cont) {
+ //speak
+ cout << "which id : 1-(robin,smith,M,art), 2-(adam,smith,M,math), 3-(tina,su,F,physics), 4-exit:\n";
+ int subject;
+ cin.getline(msg, 1024);
+ subject = atoi(msg);
+ switch(subject) {
+ case 1:
+ case 2:
+ case 3:
+ cout << "enter your message: ";
+ cin.getline(msg,1024);
+ switch (subject) {
+ case 1:
+ pub.send(robin_s_id, new chat_msg(my_name, msg));
+ break;
+ case 2:
+ pub.send(adam_s_id, new chat_msg(my_name, msg));
+ break;
+ case 3:
+ pub.send(tina_s_id, new chat_msg(my_name, msg));
+ break;
+ default:
+ break;
+ }
+ break;
+ case 4:
+ cont = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ connector.shutdown();
+ t.join();
+ }
+ catch (boost::system::error_code& e)
+ {
+ std::cerr << e << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/chat_assoc/chat_defs.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_assoc/chat_defs.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,96 @@
+//
+// chat_defs.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#ifndef CHAT_DEFS_HPP
+#define CHAT_DEFS_HPP
+
+#include <string>
+#include <boost/tuple/tuple_comparison.hpp>
+#include <boost/tuple/tuple_io.hpp>
+#include <boost/channel/channel.hpp>
+
+using namespace std;
+using namespace boost::channel;
+
+//instantiate channel type, define id_type
+/**
+ * using the following tuple fields to identify a person
+ * string - first name
+ * string - last name
+ * int - male(0), female(1)
+ * int - department: math(0), physics(1), art(2)...
+ */
+typedef boost::tuple<string, string, int, int> tuple_type;
+typedef tuple_id<tuple_type> id_type;
+
+typedef channel<
+ id_type,
+ boost_platform,
+ mt_synch<boost_platform>,
+ abstract_executor, //force in place execution
+ linear_name_space<id_type, abstract_executor, mt_synch<boost_platform>, false> ///false - assoc matching
+///broadcast dispatcher by default
+ > chat_chan;
+
+//define sys ids
+DEFINE_TUPLE_SYS_IDS(tuple_type)
+
+//sample subject ids in chat_chan
+//1. all msgs for student with last name "smith"
+id_type smith_r_id(tuple_type(
+ field_trait<string>::wildcard,
+ "smith",
+ field_trait<int>::wildcard,
+ field_trait<int>::wildcard));
+//2. all msgs for student in "math" department
+id_type math_r_id(tuple_type(
+ field_trait<string>::wildcard,
+ field_trait<string>::wildcard,
+ field_trait<int>::wildcard,
+ 0));
+//2. all msgs for female
+id_type female_r_id(tuple_type(
+ field_trait<string>::wildcard,
+ field_trait<string>::wildcard,
+ 1,
+ field_trait<int>::wildcard));
+//3. id for a specific person
+id_type robin_s_id(tuple_type(
+ "robin",
+ "smith",
+ 0,
+ 2));
+//4. id for a specific person
+id_type adam_s_id(tuple_type(
+ "adam",
+ "smith",
+ 0,
+ 0));
+//5. id for a specific person
+id_type tina_s_id(tuple_type(
+ "tina",
+ "su",
+ 1,
+ 1));
+
+//a simple struct for chat msg
+struct chat_msg {
+ string source_;
+ string data_;
+ chat_msg(const char *s, char *d) : source_(s), data_(d) {}
+ chat_msg() {} //have to define this for marshaling to work
+ //serialization function for chat_msg
+ template <typename Archive>
+ void serialize(Archive & ar, const unsigned int version)
+ {
+ ar &source_ & data_;
+ }
+};
+
+
+#endif

Added: sandbox/channel/libs/channel/example/chat_assoc/sample10_text.html
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_assoc/sample10_text.html 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,240 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+</head>
+<body style="color: rgb(0, 0, 0);" alink="#ee0000" link="#0000ee"
+ vlink="#551a8b">
+<h2>Sample 10.&nbsp; channel using Linda-style associative lookup<br>
+</h2>
+This sample modifies chat_direct sample to show how we can pass
+messages and events among distributed processes based on Linda-style
+associative name lookup.<br>
+<br>
+Lets walk thru the code.<br>
+<br>
+All name space related types are defined in chat_defs.hpp.<br>
+<br>
+In Linda tuple space, each tuple consist of a set of fields. When
+tuples are read from tuple space, some fields can be set as wildcard
+and they can match any values. In Channel we can use tuples as
+names/ids in name space and similarly associative lookup will be used
+for
+name-matching. Please refer to <a href="../../doc/assoc_id_text.html">simple
+design doc</a> for more details. Boost.Tuple is used for tuple
+implementation, so &lt;boost/tuple.hpp&gt; is included.<br>
+<br>
+For this sample, we use the following tuple type with 4 fields:<br>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">typedef
+boost::tuple&lt;string, string, int, int&gt; tuple_type;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">typedef
+tuple_id&lt;tuple_type&gt; id_type;<br>
+</span></div>
+These 4 fields are used to identify a person:<br>
+&nbsp;*&nbsp; string - first name<br>
+&nbsp;*&nbsp; string - last name<br>
+&nbsp;*&nbsp; int&nbsp;&nbsp;&nbsp; - male(0), female(1)<br>
+&nbsp;*&nbsp; int&nbsp;&nbsp;&nbsp; - department: math(0), physics(1),
+art(2)...<br>
+Next we instantiate the channel type. A associative name space is
+implemented as a linear namespace with associative&nbsp; lookup. The
+lookup method is defined as the last template argument of
+linear_name_space class template. The default value "true" means "exact
+matching"; for "associative lookup" we set it to false.<br>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">typedef channel&lt;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; id_type,</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+boost_platform,</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+mt_synch&lt;boost_platform&gt;,</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+abstract_executor, //force in place execution</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+linear_name_space&lt;id_type, abstract_executor,
+mt_synch&lt;boost_platform&gt;, false&gt; ///false - assoc matching</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; &gt;
+chat_chan;</span><br>
+</div>
+<br>
+Next we define ids/names we are going to use in this application. They
+are names and attributes of persons we are interested. Two sets of ids
+are defined: ids for specific persons and ids for categories:<br>
+Ids for specific persons:<br>
+<div style="margin-left: 40px;">A person with name "robin smith", male
+and in department of "art"<br>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">id_type
+robin_s_id(tuple_type(</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "robin",</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "smith",</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 0,</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 2));</span><br>
+</div>
+A person with name "adam smith", male and in department of "math"<br>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">id_type
+adam_s_id(tuple_type(</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "adam",</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "smith",</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 0,</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 0));</span><br>
+</div>
+A person with name "tina su", female and in department of "physics"<br>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">id_type
+tina_s_id(tuple_type(</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "tina",</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "su",</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 1,</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 1));</span><br>
+</div>
+</div>
+<span style="font-style: italic;"></span>Ids for categories:<br>
+<div style="margin-left: 40px;">Id for all people with last name "smith"<br>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">id_type
+smith_r_id(tuple_type(</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+field_trait&lt;string&gt;::wildcard,</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "smith",</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+field_trait&lt;int&gt;::wildcard,</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+field_trait&lt;int&gt;::wildcard));</span><br>
+</div>
+Id for all people in "math" department<br>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">id_type
+math_r_id(tuple_type(</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+field_trait&lt;string&gt;::wildcard,</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+field_trait&lt;string&gt;::wildcard,</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+field_trait&lt;int&gt;::wildcard,</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 0));</span><br>
+</div>
+Id for all female<br>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">id_type
+female_r_id(tuple_type(</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+field_trait&lt;string&gt;::wildcard,</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+field_trait&lt;string&gt;::wildcard,</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 1,</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+field_trait&lt;int&gt;::wildcard));</span><br>
+</div>
+</div>
+<br>
+Next we define a simple structure for message data:<br>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">struct chat_msg {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; string
+source_;</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; string
+data_;</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+chat_msg(char *s, char *d) : source_(s), data_(d) {}</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+chat_msg() {} //have to define this for marshaling to work</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+//serialization function for chat_msg</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+template &lt;typename Archive&gt;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; void
+serialize(Archive &amp; ar, const unsigned int version)</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+ar &amp;source_ &amp; data_;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; }</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">};</span><br>
+</div>
+<br>
+As a last step, we need to add the following macro to define the system
+internal messages (ugly):<br>
+<span style="font-style: italic; color: rgb(153, 0, 0);">DEFINE_ASSOC_SYS_IDS(tuple_type)
+</span><br>
+<br>
+The code in the peer process (chat1.cpp,
+chat2.cpp) are similar to
+other samples. We bind to names to send messages to distributed
+processes, except that we are using associative lookup for
+name-matching. So if application subscribe to <span
+ style="font-style: italic; color: rgb(153, 0, 0);">"smith_r_id", </span><span
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);">it
+will receive messages for both "robin smith" and "adam smith".</span></span><br>
+<br>
+Complete source code listing:<br>
+chat_defs.hpp<br>
+chat1.cpp<br>
+chat2.cpp<br>
+<br>
+</body>
+</html>

Added: sandbox/channel/libs/channel/example/chat_direct/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_direct/Jamfile.v2 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#
+#//
+#// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+#//
+#// Distributed under the Boost Software License, Version 1.0. (See accompanying
+#// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#//
+
+
+import os ;
+
+if [ os.name ] = SOLARIS
+{
+ lib socket ;
+ lib nsl ;
+}
+else if [ os.name ] = NT
+{
+ lib ws2_32 ;
+ lib mswsock ;
+}
+
+project
+ : requirements
+ <library>/boost/serialization//boost_serialization
+ <library>/boost/thread//boost_thread
+ <library>/boost/system//boost_system
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <os>SOLARIS:<library>socket
+ <os>SOLARIS:<library>nsl
+ <os>NT,<toolset>gcc:<library>ws2_32
+ <os>NT,<toolset>gcc:<library>mswsock
+ ;
+
+obj chat1.obj : chat1.cpp ;
+exe chat1 : chat1.obj ;
+obj chat2.obj : chat2.cpp ;
+exe chat2 : chat2.obj ;

Added: sandbox/channel/libs/channel/example/chat_direct/chat1.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_direct/chat1.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,107 @@
+//
+// chat1.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/channel/streams/asio_stream_async.hpp>
+#include "./chat_defs.hpp"
+
+//chat msg handler; print out data
+void msg_handler(id_type id, boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << msg->source_ << " speak on [" << chat_chan::id_trait::id_to_string(id) << "]:\n";
+ cout << msg->data_ << endl;
+}
+
+int main(int, char **) {
+ const char *my_name = "chatter 1";
+ try {
+ //create asio io_service
+ boost::asio::io_service io_service;
+ //create local channel and bind local event source/sink
+ chat_chan chan;
+
+ //create/bind-to subjects i am going to speak about
+ chat_chan::out basketball_o(chan, basketball);
+ chat_chan::out tennis_o(chan, tennis);
+ chat_chan::out stock_o(chan, stock);
+
+ //subscribe to subjects i am interested in listening
+ chat_chan::in basketball_i(chan, basketball, msg_handler);
+ //i want hear all about financials
+ chat_chan::in all_financial_i(chan, all_financial, msg_handler);
+
+ //register chat msg type for marshaling/demarshaling
+ chat_chan::text_marshaler_registry mar_reg;
+ mar_reg.register_default_msg_marshaler<chat_msg>();
+
+ //create asio connectors and connect to remote channel
+ asio_connector_async connector(io_service);
+ connector.async_connect("localhost", "8888", //remote channel address
+ boost::bind(asio_bind_sock_chan<chat_chan, chat_chan::text_marshaler_registry>(),
+ boost::ref(chan), boost::ref(mar_reg), _1, _2, _3));
+ //a separate thread to run io_service
+ boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));
+
+ char msg[1024];
+ bool cont = true;
+ while (cont) {
+ //speak
+ cout << "which subject : 1-basket_ball, 2-tennis, 3-stock, 4-exit:\n";
+ int subject;
+ cin.getline(msg, 1024);
+ subject = atoi(msg);
+ switch(subject) {
+ case 1:
+ case 2:
+ case 3:
+ cout << "enter your message: ";
+ cin.getline(msg, 1024);
+ switch (subject) {
+ case 1:
+ basketball_o.send(new chat_msg(my_name, msg));
+ break;
+ case 2:
+ tennis_o.send(new chat_msg(my_name, msg));
+ break;
+ case 3:
+ stock_o.send(new chat_msg(my_name, msg));
+ break;
+ default:
+ break;
+ }
+ break;
+ case 4:
+ cont = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ connector.shutdown();
+ std::cout << "---1" << std::endl;
+ t.join();
+ std::cout << "---2" << std::endl;
+ }
+ catch (boost::system::error_code& e)
+ {
+ std::cerr << e << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/chat_direct/chat2.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_direct/chat2.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,132 @@
+//
+// chat2.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/channel/streams/asio_stream_async.hpp>
+#include "./chat_defs.hpp"
+
+//chat msg handler; print out data
+void msg_handler(id_type id, boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << "chan1: " << msg->source_ << " speak on [" << chat_chan::id_trait::id_to_string(id) << "]:\n";
+ cout << msg->data_ << endl;
+}
+
+void msg_handler2(id_type id, boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << "chan2: " << msg->source_ << " speak on [" << chat_chan::id_trait::id_to_string(id) << "]:\n";
+ cout << msg->data_ << endl;
+}
+
+/**
+ * here we are going to use the publish/subscribe API built on top of
+ * named_in/named_out
+ */
+
+int main(int, char **) {
+ const char* my_name = "chatter 2";
+ try {
+ //create asio io_service
+ boost::asio::io_service io_service;
+ //create local channels and connect them
+ chat_chan chan;
+ chat_chan chan2;
+ connect(chan, chan2);
+
+ //create/bind-to subjects i am going to speak about
+ chat_chan::publisher pub(chan);
+ pub.publish(basketball);
+ pub.publish(baseball);
+ pub.publish(tax);
+ pub.publish(investment);
+
+ //subscribe to subjects i am interested in listening
+ chat_chan::subscriber sub(chan, msg_handler);
+ //i am a sports fan
+ sub.subscribe(all_sports);
+ sub.subscribe(stock);
+ sub.subscribe(tax);
+
+ //subscribe at chan2, using named_in/out api
+ chat_chan::in basketball_i(chan2, basketball, msg_handler2);
+ chat_chan::in all_financial_i(chan2, all_financial, msg_handler2);
+
+ //register chat msg type for marshaling/demarshaling
+ chat_chan::text_marshaler_registry mar_reg;
+ mar_reg.register_default_msg_marshaler<chat_msg>();
+
+ //create asio connectors and connect to remote channel
+ asio_connector_async connector(io_service);
+ connector.async_accept(8888, // channel address
+ boost::bind(asio_bind_sock_chan<chat_chan, chat_chan::text_marshaler_registry>(),
+ boost::ref(chan), boost::ref(mar_reg), _1, _2, _3));
+ //a separate thread to run io_service
+ boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));
+
+ //in the following code, main thread will drive the interactive loop
+ char msg[1024];
+ bool cont = true;
+ while (cont) {
+ //speak
+ cout << "which subject : 1-basket_ball, 2-base_ball, 3-tax, 4-investment, 5-exit:\n";
+ int subject;
+ cin.getline(msg, 1024);
+ subject = atoi(msg);
+ switch(subject) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ cout << "enter your message: ";
+ cin.getline(msg,1024);
+ switch (subject) {
+ case 1:
+ pub.send(basketball, new chat_msg(my_name, msg));
+ break;
+ case 2:
+ pub.send(baseball, new chat_msg(my_name, msg));
+ break;
+ case 3:
+ pub.send(tax, new chat_msg(my_name, msg));
+ break;
+ case 4:
+ pub.send(investment, new chat_msg(my_name, msg));
+ break;
+ default:
+ break;
+ }
+ break;
+ case 5:
+ cont = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ connector.shutdown();
+ t.join();
+ }
+ catch (boost::system::error_code& e)
+ {
+ std::cerr << e << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/chat_direct/chat_defs.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_direct/chat_defs.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,58 @@
+//
+// chat_defs.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#ifndef CHAT_DEFS_HPP
+#define CHAT_DEFS_HPP
+
+#include <string>
+#include <boost/channel/channel.hpp>
+
+using namespace std;
+using namespace boost::channel;
+
+//instantiate event channel type, using string as id_type
+typedef str_path_id<'/'> id_type;
+typedef channel<
+ id_type,
+ boost_platform,
+ mt_synch<boost_platform>,
+ abstract_executor, //force in place execution
+ hierarchical_name_space<id_type, abstract_executor, mt_synch<boost_platform> >
+///broadcast dispatcher by default
+ > chat_chan;
+
+//define sys ids
+DEFINE_SLASH_PATH_SYS_IDS
+
+//sample subject ids in chat_chan
+//sports
+id_type basketball = "/sports/basketball";
+id_type tennis = "/sports/tennis";
+id_type baseball = "/sports/baseball";
+id_type all_sports = "/sports/*";
+//financial
+id_type tax = "/financial/tax";
+id_type stock = "/financial/stock";
+id_type investment = "/financial/investment/";
+id_type all_financial = "/financial/*";
+
+//a simple struct for chat msg
+struct chat_msg {
+ string source_;
+ string data_;
+ chat_msg(const char *s, const char *d) : source_(s), data_(d) {}
+ chat_msg() {} //have to define this for marshaling to work
+ //serialization function for chat_msg
+ template <typename Archive>
+ void serialize(Archive & ar, const unsigned int version)
+ {
+ ar &source_ & data_;
+ }
+};
+
+#endif

Added: sandbox/channel/libs/channel/example/chat_direct/sample4_text.html
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_direct/sample4_text.html 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+</head>
+<body>
+<h2>Sample 4: Chat with direct connection</h2>
+<br>
+This sample shows the usage of hierarchical namespace by defining chat
+subjects as string path names. Chat peers directly connect to
+each other, subscribing to the subjects they are interested and send
+messages with each other. Since it a hierarchical namespace, peers can
+subscribe to wildcard ids such as "all sports related subjects".<br>
+<br>
+More comments...<br>
+<br>
+Complete source code:<br>
+chat_defs.hpp<br>
+chat1.cpp<br>
+<a href="chat2.cpp">chat2.cpp<br>
+</a><br>
+<br>
+</body>
+</html>

Added: sandbox/channel/libs/channel/example/chat_regex/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_regex/Jamfile.v2 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#
+#//
+#// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+#//
+#// Distributed under the Boost Software License, Version 1.0. (See accompanying
+#// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#//
+
+import os ;
+
+if [ os.name ] = SOLARIS
+{
+ lib socket ;
+ lib nsl ;
+}
+else if [ os.name ] = NT
+{
+ lib ws2_32 ;
+ lib mswsock ;
+}
+
+project
+ : requirements
+ <library>/boost/serialization//boost_serialization
+ <library>/boost/thread//boost_thread
+ <library>/boost/regex//boost_regex
+ <library>/boost/system//boost_system
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <os>SOLARIS:<library>socket
+ <os>SOLARIS:<library>nsl
+ <os>NT,<toolset>gcc:<library>ws2_32
+ <os>NT,<toolset>gcc:<library>mswsock
+ ;
+
+obj chat1.obj : chat1.cpp ;
+exe chat1 : chat1.obj ;
+obj chat2.obj : chat2.cpp ;
+exe chat2 : chat2.obj ;

Added: sandbox/channel/libs/channel/example/chat_regex/chat1.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_regex/chat1.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,107 @@
+//
+// chat1.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/channel/streams/asio_stream_async.hpp>
+#include "./chat_defs.hpp"
+
+//chat msg handler; print out data
+void msg_handler(id_type id, boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << msg->source_ << " speak on [" << chat_chan::id_trait::id_to_string(id) << "]:\n";
+ cout << msg->data_ << endl;
+}
+
+int main(int, char **) {
+ const char *my_name = "chatter 1";
+ try {
+ //create asio io_service
+ boost::asio::io_service io_service;
+ //create local channel and bind local event source/sink
+ chat_chan chan;
+
+ //create/bind-to subjects i am going to speak about
+ chat_chan::out basketball_o(chan, basketball);
+ chat_chan::out tennis_o(chan, tennis);
+ chat_chan::out stock_o(chan, stock);
+
+ //subscribe to subjects i am interested in listening
+ chat_chan::in basketball_i(chan, basketball, msg_handler);
+ //i want hear all about financials
+ chat_chan::in all_financial_i(chan, all_financial, msg_handler);
+
+ //register chat msg type for marshaling/demarshaling
+ chat_chan::text_marshaler_registry mar_reg;
+ mar_reg.register_default_msg_marshaler<chat_msg>();
+
+ //create asio connectors and connect to remote channel
+ asio_connector_async connector(io_service);
+ connector.async_connect("localhost", "8888", //remote channel address
+ boost::bind(asio_bind_sock_chan<chat_chan, chat_chan::text_marshaler_registry>(),
+ boost::ref(chan), boost::ref(mar_reg), _1, _2, _3));
+ //a separate thread to run io_service
+ boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));
+
+ char msg[1024];
+ bool cont = true;
+ while (cont) {
+ //speak
+ cout << "which subject : 1-basket_ball, 2-tennis, 3-stock, 4-exit:\n";
+ int subject;
+ cin.getline(msg, 1024);
+ subject = atoi(msg);
+ switch(subject) {
+ case 1:
+ case 2:
+ case 3:
+ cout << "enter your message: ";
+ cin.getline(msg, 1024);
+ switch (subject) {
+ case 1:
+ basketball_o.send(new chat_msg(my_name, msg));
+ break;
+ case 2:
+ tennis_o.send(new chat_msg(my_name, msg));
+ break;
+ case 3:
+ stock_o.send(new chat_msg(my_name, msg));
+ break;
+ default:
+ break;
+ }
+ break;
+ case 4:
+ cont = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ connector.shutdown();
+ std::cout << "---1" << std::endl;
+ t.join();
+ std::cout << "---2" << std::endl;
+ }
+ catch (boost::system::error_code& e)
+ {
+ std::cerr << e << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/chat_regex/chat2.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_regex/chat2.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,133 @@
+//
+// chat2.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/channel/streams/asio_stream_async.hpp>
+#include "./chat_defs.hpp"
+
+//chat msg handler; print out data
+void msg_handler(id_type id, boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << "chan1: " << msg->source_ << " speak on [" << chat_chan::id_trait::id_to_string(id) << "]:\n";
+ cout << msg->data_ << endl;
+}
+
+void msg_handler2(id_type id, boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << "chan2: " << msg->source_ << " speak on [" << chat_chan::id_trait::id_to_string(id) << "]:\n";
+ cout << msg->data_ << endl;
+}
+
+/**
+ * here we are going to use the publish/subscribe API built on top of
+ * named_in/named_out
+ */
+
+int main(int, char **) {
+ const char* my_name = "chatter 2";
+ try {
+ //create asio io_service
+ boost::asio::io_service io_service;
+ //create local channels and connect them
+ chat_chan chan;
+ chat_chan chan2;
+ connect(chan, chan2);
+
+ //create/bind-to subjects i am going to speak about
+ chat_chan::publisher pub(chan);
+ pub.publish(basketball);
+ pub.publish(baseball);
+ pub.publish(tax);
+ pub.publish(investment);
+
+ //subscribe to subjects i am interested in listening
+ chat_chan::subscriber sub(chan, msg_handler);
+ //i am a sports fan
+ sub.subscribe(all_balls);
+ sub.subscribe(tennis);
+ sub.subscribe(stock);
+ sub.subscribe(tax);
+
+ //subscribe at chan2, using named_in/out api
+ chat_chan::in basketball_i(chan2, basketball, msg_handler2);
+ chat_chan::in all_financial_i(chan2, all_financial, msg_handler2);
+
+ //register chat msg type for marshaling/demarshaling
+ chat_chan::text_marshaler_registry mar_reg;
+ mar_reg.register_default_msg_marshaler<chat_msg>();
+
+ //create asio connectors and connect to remote channel
+ asio_connector_async connector(io_service);
+ connector.async_accept(8888, // channel address
+ boost::bind(asio_bind_sock_chan<chat_chan, chat_chan::text_marshaler_registry>(),
+ boost::ref(chan), boost::ref(mar_reg), _1, _2, _3));
+ //a separate thread to run io_service
+ boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));
+
+ //in the following code, main thread will drive the interactive loop
+ char msg[1024];
+ bool cont = true;
+ while (cont) {
+ //speak
+ cout << "which subject : 1-basket_ball, 2-base_ball, 3-tax, 4-investment, 5-exit:\n";
+ int subject;
+ cin.getline(msg, 1024);
+ subject = atoi(msg);
+ switch(subject) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ cout << "enter your message: ";
+ cin.getline(msg,1024);
+ switch (subject) {
+ case 1:
+ pub.send(basketball, new chat_msg(my_name, msg));
+ break;
+ case 2:
+ pub.send(baseball, new chat_msg(my_name, msg));
+ break;
+ case 3:
+ pub.send(tax, new chat_msg(my_name, msg));
+ break;
+ case 4:
+ pub.send(investment, new chat_msg(my_name, msg));
+ break;
+ default:
+ break;
+ }
+ break;
+ case 5:
+ cont = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ connector.shutdown();
+ t.join();
+ }
+ catch (boost::system::error_code& e)
+ {
+ std::cerr << e << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/chat_regex/chat_defs.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_regex/chat_defs.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,59 @@
+//
+// chat_defs.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#ifndef CHAT_DEFS_HPP
+#define CHAT_DEFS_HPP
+
+#include <string>
+#include <boost/regex.hpp>
+#include <boost/channel/channel.hpp>
+
+using namespace std;
+using namespace boost::channel;
+
+//instantiate event channel type, using regex_id as id_type
+typedef regex_id id_type;
+typedef channel<
+ id_type,
+ boost_platform,
+ mt_synch<boost_platform>,
+ abstract_executor, //force in place execution
+ linear_name_space<id_type, abstract_executor, mt_synch<boost_platform>, false> ///false - assoc matching
+///broadcast dispatcher by default
+ > chat_chan;
+
+//define sys ids
+DEFINE_REGEX_SYS_IDS
+
+//sample subject ids in chat_chan
+//sports
+id_type basketball = "[sports]: basketball";
+id_type tennis = "[sports]: tennis";
+id_type baseball = "[sports]: baseball";
+id_type all_balls(new boost::regex(".*ball.*"));
+//financial
+id_type tax = "[financial]: tax";
+id_type stock = "[financial]: stock";
+id_type investment = "[financial]: investment";
+id_type all_financial(new boost::regex(".*financial.*"));
+
+//a simple struct for chat msg
+struct chat_msg {
+ string source_;
+ string data_;
+ chat_msg(const char *s, const char *d) : source_(s), data_(d) {}
+ chat_msg() {} //have to define this for marshaling to work
+ //serialization function for chat_msg
+ template <typename Archive>
+ void serialize(Archive & ar, const unsigned int version)
+ {
+ ar &source_ & data_;
+ }
+};
+
+#endif

Added: sandbox/channel/libs/channel/example/chat_regex/sample9_text.html
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_regex/sample9_text.html 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+</head>
+<body style="color: rgb(0, 0, 0);" alink="#ee0000" link="#0000ee"
+ vlink="#551a8b">
+<h2>Sample 9.&nbsp; channel using regex name matching<br>
+</h2>
+<br>
+This sample modifies chat_direct sample to show how we can pass
+messages and events among distributed processes based on regex name
+matching.<br>
+<br>
+Lets walk thru the code.<br>
+<br>
+All name space related types are defined in chat_defs.hpp.<br>
+<br>
+First we set regex_id to be the id_type. With regex_id, applications
+can use strings and regex patterns (Boost.Regex) as message ids and
+names (also we need to include &lt;boost/regex.hpp&gt;). <br>
+Next we instantiate the channel type. A associative name space is
+implemented as a linear namespace with associative&nbsp; lookup. The
+lookup method is defined as the last template argument of
+linear_name_space class template. The default value "true" means "exact
+matching"; for "associative lookup" we set it to false.<br>
+<div style="margin-left: 40px;"><span
+ style="color: rgb(153, 0, 0); font-style: italic;">typedef regex_id
+id_type;</span><br style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">typedef
+channel&lt;</span><br style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; id_type,</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;
+boost_platform,</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;
+mt_synch&lt;boost_platform&gt;,</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;
+abstract_executor, //force in place execution</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;
+linear_name_space&lt;id_type, abstract_executor,
+mt_synch&lt;boost_platform&gt;, false&gt; ///false - assoc matching</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; &gt;
+chat_chan;</span><br>
+</div>
+Next we define ids/names we are going to use in this channel
+application. We define 2 sets of ids: plain text strings and&nbsp;
+regex patterns: <br>
+<div style="margin-left: 40px; background-color: rgb(255, 255, 255);"><span
+ style="color: rgb(153, 0, 0); font-style: italic;">id_type basketball
+= "[sports]: basketball";</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">id_type tennis
+= "[sports]: tennis";</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">id_type
+baseball = "[sports]: baseball";</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="font-style: italic; color: rgb(0, 0, 102);">id_type
+all_balls(new boost::regex(".*ball.*"));</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<br style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">id_type tax =
+"[financial]: tax";</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">id_type stock
+= "[financial]: stock";</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">id_type
+investment = "[financial]: investment";</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="font-style: italic; color: rgb(0, 0, 102);">id_type
+all_financial(new boost::regex(".*financial.*"));</span><br
+ style="color: rgb(0, 0, 102);">
+</div>
+<br>
+Next we define a simple structure for message data:<br>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">struct chat_msg {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; string
+source_;</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; string
+data_;</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+chat_msg(char *s, char *d) : source_(s), data_(d) {}</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+chat_msg() {} //have to define this for marshaling to work</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+//serialization function for chat_msg</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+template &lt;typename Archive&gt;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; void
+serialize(Archive &amp; ar, const unsigned int version)</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+ar &amp;source_ &amp; data_;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; }</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">};</span><br>
+</div>
+<br>
+The code in the peer process (chat1.cpp,
+chat2.cpp) are similar to
+other samples. We bind to names to send messages to distributed
+processes, except that
+we are using regex matching for name-matching. So if application
+subscribe to <span style="font-style: italic; color: rgb(153, 0, 0);">"all_balls",
+</span><span style="color: rgb(153, 0, 0);"><span
+ style="color: rgb(0, 0, 0);">it will receive messages for both
+"basketball", "baseball" and any other balls.</span></span><br>
+<br>
+Complete source code listing:<br>
+chat_defs.hpp<br>
+chat1.cpp<br>
+chat2.cpp<br>
+<br>
+</body>
+</html>

Added: sandbox/channel/libs/channel/example/chat_regex/test.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_regex/test.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,18 @@
+#include <string>
+#include <iostream>
+#include <boost/regex.hpp>
+
+using namespace std;
+using namespace boost;
+
+regex *re = new regex(".*ball.*");
+
+int main(int argc, char **argv) {
+ string s = "/sports/basketball";
+ regex rn(re->str(),re->flags());
+ if (regex_match(s,rn) == true) {
+ std::cout << "matched\n";
+ } else
+ std::cout << "not matched\n";
+ return 0;
+}

Added: sandbox/channel/libs/channel/example/chat_shmem/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_shmem/Jamfile.v2 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,20 @@
+#//
+#// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+#//
+#// Distributed under the Boost Software License, Version 1.0. (See accompanying
+#// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#//
+
+project
+ : requirements
+ <library>/boost/serialization//boost_serialization
+ <library>/boost/thread//boost_thread
+ <library>/boost/system//boost_system
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ ;
+
+obj chat1.obj : chat1.cpp ;
+exe chat1 : chat1.obj ;
+obj chat2.obj : chat2.cpp ;
+exe chat2 : chat2.obj ;

Added: sandbox/channel/libs/channel/example/chat_shmem/chat1.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_shmem/chat1.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,96 @@
+//
+// chat1.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/channel/streams/shmem_stream.hpp>
+#include "./chat_defs.hpp"
+
+//chat msg handler; print out data
+void msg_handler(id_type id, boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << msg->source_ << " speak on [" << chat_chan::id_trait::id_to_string(id) << "]:" << endl;
+ cout << msg->data_ << endl;
+}
+
+int main(int, char **) {
+ const char *my_name = "chatter 1";
+ //create local channel and bind local event source/sink
+ chat_chan chan;
+
+ //create/bind-to subjects i am going to speak about
+ chat_chan::out basketball_o(chan, basketball);
+ chat_chan::out tennis_o(chan, tennis);
+ chat_chan::out stock_o(chan, stock);
+
+ //subscribe to subjects i am interested in listening
+ chat_chan::in basketball_i(chan, basketball, msg_handler);
+ //i want hear all about financials
+ chat_chan::in all_financial_i(chan, all_financial, msg_handler);
+
+ //register chat msg type for marshaling/demarshaling
+ chat_chan::text_marshaler_registry mar_reg;
+ mar_reg.register_default_msg_marshaler<chat_msg>();
+
+ //create shmem stream and connect to channel
+ //let the other side (chat2) create shmem, we jus open and use it
+ shmem_stream<
+ id_type,
+ chat_chan::text_marshaler_registry
+ >
+ shmstream(false, que_name, que_max_num, que_max_size, mar_reg);
+
+ //as active connection side, so we start connection handshaking
+ //inside shmem_stream, an internal thread will pump messages
+ connect(chan, &shmstream, true);
+
+ //in the following code, main thread will drive the interactive loop
+ char msg[1024];
+ bool cont = true;
+ while (cont) {
+ //speak
+ cout << "which subject : 1-basket_ball, 2-tennis, 3-stock, 4-exit:\n";
+ int subject;
+ cin.getline(msg, 1024);
+ subject = atoi(msg);
+ switch(subject) {
+ case 1:
+ case 2:
+ case 3:
+ cout << "enter your message: ";
+ cin.getline(msg, 1024);
+ switch (subject) {
+ case 1:
+ basketball_o.send(new chat_msg(my_name, msg));
+ break;
+ case 2:
+ tennis_o.send(new chat_msg(my_name, msg));
+ break;
+ case 3:
+ stock_o.send(new chat_msg(my_name, msg));
+ break;
+ default:
+ break;
+ }
+ break;
+ case 4:
+ cont = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ shmstream.shutdown_wait();
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/chat_shmem/chat2.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_shmem/chat2.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,122 @@
+//
+// chat2.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include "./chat_defs.hpp"
+#include <boost/channel/streams/shmem_stream.hpp>
+
+//chat msg handler; print out data
+void msg_handler(id_type id, boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << "chan1: " << msg->source_ << " speak on [" << chat_chan::id_trait::id_to_string(id) << "]:" << endl;
+ cout << msg->data_ << endl;
+}
+
+void msg_handler2(id_type id, boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << "chan2: " << msg->source_ << " speak on [" << chat_chan::id_trait::id_to_string(id) << "]:" << endl;
+ cout << msg->data_ << endl;
+}
+
+/**
+ * here we are going to use the publish/subscribe API built on top of
+ * named_in/named_out
+ */
+
+int main(int, char **) {
+ const char* my_name = "chatter 2";
+ //create local channels and connect them
+ chat_chan chan;
+ chat_chan chan2;
+ connect(chan, chan2);
+
+ //create/bind-to subjects i am going to speak about
+ chat_chan::publisher pub(chan);
+ pub.publish(basketball);
+ pub.publish(baseball);
+ pub.publish(tax);
+ pub.publish(investment);
+
+ //subscribe to subjects i am interested in listening
+ chat_chan::subscriber sub(chan, msg_handler);
+ //i am a sports fan
+ sub.subscribe(all_sports);
+ sub.subscribe(stock);
+ sub.subscribe(tax);
+
+ //subscribe at chan2, using named_in/out api
+ chat_chan::in basketball_i(chan2, basketball, msg_handler2);
+ chat_chan::in all_financial_i(chan2, all_financial, msg_handler2);
+
+ //register chat msg type for marshaling/demarshaling
+ chat_chan::text_marshaler_registry mar_reg;
+ mar_reg.register_default_msg_marshaler<chat_msg>();
+
+ //create shmem stream and connect to channel
+ //we'll create shmem msg_que and allow chat1 to connect
+ shmem_stream<
+ id_type,
+ chat_chan::text_marshaler_registry
+ >
+ shmstream(true, que_name, que_max_num, que_max_size, mar_reg);
+
+ //as passive conn side, we wait for chat1 to start connection handshaking
+ //inside shmem_stream, an internal thread will pump messages
+ connect(chan, &shmstream, false);
+
+ //in the following code, main thread will drive the interactive loop
+ char msg[1024];
+ bool cont = true;
+ while (cont) {
+ //speak
+ cout << "which subject : 1-basket_ball, 2-base_ball, 3-tax, 4-investment, 5-exit:\n";
+ int subject;
+ cin.getline(msg, 1024);
+ subject = atoi(msg);
+ switch(subject) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ cout << "enter your message: ";
+ cin.getline(msg,1024);
+ switch (subject) {
+ case 1:
+ pub.send(basketball, new chat_msg(my_name, msg));
+ break;
+ case 2:
+ pub.send(baseball, new chat_msg(my_name, msg));
+ break;
+ case 3:
+ pub.send(tax, new chat_msg(my_name, msg));
+ break;
+ case 4:
+ pub.send(investment, new chat_msg(my_name, msg));
+ break;
+ default:
+ break;
+ }
+ break;
+ case 5:
+ cont = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ shmstream.shutdown_wait();
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/chat_shmem/chat_defs.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_shmem/chat_defs.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,62 @@
+//
+// chat_defs.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#ifndef CHAT_DEFS_HPP
+#define CHAT_DEFS_HPP
+
+#include <string>
+#include <boost/channel/channel.hpp>
+
+using namespace std;
+using namespace boost::channel;
+
+//instantiate event channel type, using string as id_type
+typedef str_path_id<'/'> id_type;
+typedef channel<
+ id_type,
+ boost_platform,
+ mt_synch<boost_platform>,
+ abstract_executor, //force in place execution
+ hierarchical_name_space<id_type, abstract_executor, mt_synch<boost_platform> >
+///broadcast dispatcher by default
+ > chat_chan;
+
+//define sys ids
+DEFINE_SLASH_PATH_SYS_IDS
+
+//sample subject ids in chat_chan
+//sports
+id_type basketball = "/sports/basketball";
+id_type tennis = "/sports/tennis";
+id_type baseball = "/sports/baseball";
+id_type all_sports = "/sports/*";
+//financial
+id_type tax = "/financial/tax";
+id_type stock = "/financial/stock";
+id_type investment = "/financial/investment/";
+id_type all_financial = "/financial/*";
+
+//a simple struct for chat msg
+struct chat_msg {
+ string source_;
+ string data_;
+ chat_msg(const char *s, const char *d) : source_(s), data_(d) {}
+ chat_msg() {} //have to define this for marshaling to work
+ //serialization function for chat_msg
+ template <typename Archive>
+ void serialize(Archive & ar, const unsigned int version)
+ {
+ ar &source_ & data_;
+ }
+};
+
+const char *que_name = "chat_shmem_que";
+int que_max_num = 100;
+int que_max_size = sizeof(chat_msg) + 1024 /* add some buffers for internal msgs */ ;
+
+#endif

Added: sandbox/channel/libs/channel/example/chat_shmem/sample8_text.html
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_shmem/sample8_text.html 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+</head>
+<body style="color: rgb(0, 0, 0);" alink="#ee0000" link="#0000ee"
+ vlink="#551a8b">
+<h2>Sample 8.&nbsp; channel
+connection thru shared memory</h2>
+<br>
+This sample shows that remote channels at 2 processes (chat1, chat2)
+can be connected thru shared memory message queues based on
+Boost.Interprocess.<br>
+<br>
+Boost.Interprocess provides rich facilities for intra-node
+inter-process communication, including message queues residing inside
+shared memory. Channel uses this shmem message queue as one of its
+transport among processes in the same node.<br>
+<br>
+Here is the code walk thru at one of peer process (chat1.cpp):<br>
+First we define a message handler function which just print out the
+received messages.<span style="color: rgb(153, 0, 0);"></span><br
+ style="color: rgb(153, 0, 0);">
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="color: rgb(153, 0, 0);">void msg_handler(id_type id, boost::shared_ptr&lt;void&gt; p, int sz, timeout_type * t)</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);">{</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> chat_msg *msg = (chat_msg *) p.get();</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> cout &lt;&lt; msg-&gt;source_ &lt;&lt; " speak on [" &lt;&lt; chat_chan::id_trait::id_to_string(id) &lt;&lt; "]:\n";</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> cout &lt;&lt; msg-&gt;data_ &lt;&lt; "\n";</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);">}</span><br
+ style="color: rgb(153, 0, 0);"></pre>
+In the main function, we create channel; bind named_out to ids for
+sending messages; bind named_in to ids and message handler for handling
+incoming messages.<br>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="color: rgb(153, 0, 0);">int main(int, char **) {</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> char *my_name //create local channel and bind local event source/sink<br> chat_chan chan;<br><br> //create/bind-to subjects i am going to speak about<br> chat_chan::out basketball_o(chan, basketball);<br> chat_chan::out tennis_o(chan, tennis);<br> chat_chan::out stock_o(chan, stock);<br><br> //subscribe to subjects i am interested in listening<br> chat_chan::in basketball_i(chan, basketball, msg_handler);<br> //i want hear all about financials<br> chat_chan::in all_financial_i(chan, all_financial, msg_handler);<br></span></pre>
+register message type for marshaling/demarshaling:<br>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"> //register chat msg type for marshaling/demarshaling<br> chat_chan::text_marshaler_registry mar_reg;<br> mar_reg.register_default_msg_marshaler&lt;chat_msg&gt;();<br></span></pre>
+Next we create a "stream" based on shared memory message queue for
+connecting chat channel to remote channel in other processes. The 1st
+argument "false" means this process just open the share memory message
+queue and don't create it.<br>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"> shmem_stream&lt;<br> id_type,<br> chat_chan::text_marshaler_registry,<br> timeout_type<br> &gt; <br> shmstream(false, que_name, que_max_num, que_max_size, mar_reg); //let the other side create shmem<br></span></pre>
+Then we connect channel to this shmem "stream" and this is the active
+side to start channel connection hand shaking.<br>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"> connect(chan, &amp;shmstream, true); //active connection side<br></span></pre>
+Here comes the main loop for sending chat messages:<br>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"> char msg[1024];<br> bool cont = true;<br> while (cont) {<br> //speak<br> cout &lt;&lt; "which subject : 1-basket_ball, 2-tennis, 3-stock, 4-exit:\n";<br> int subject;<br> cin.getline(msg, 1024);<br> subject = atoi(msg);<br> switch(subject) {<br> case 1:<br> case 2:<br> case 3:<br> cout &lt;&lt; "enter your message: ";<br> cin.getline(msg, 1024);<br> switch (subject) {<br> case 1:<br> basketball_o.send(new chat_msg(my_name, msg));<br> break;<br> case 2:<br> tennis_o.send(new chat_msg(my_name, msg));<br> break;<br> case 3:<br> stock_o.send(new chat_msg(my_name, msg));<br> break;<br> default:<br> break;<br> }<br></span></pre>
+<br>
+Next we walk thru the code for 2nd peer process (chat2.cpp).
+Most code is
+similar to chat1.cpp, besides we have 2 local channels here.<br>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"><br>int main(int, char **) {<br> char* my_name = "chatter 2";<br> //create local channels and connect them<br> chat_chan chan;<br> chat_chan chan2;<br> connect(chan, chan2);<br><br> //create/bind-to subjects i am going to speak about<br> chat_chan::publisher pub(chan);<br> pub.publish(basketball);<br> pub.publish(baseball);<br> pub.publish(tax);<br> pub.publish(investment);<br> <br> //subscribe to subjects i am interested in listening<br> chat_chan::subscriber sub(chan, msg_handler);<br> //i am a sports fan<br> sub.subscribe(all_sports);<br> sub.subscribe(stock);<br> sub.subscribe(tax);<br><br> //subscribe at chan2, using named_in/out api<br> chat_chan::in basketball_i(chan2, basketball, msg_handler2);<br> chat_chan::in all_financial_i(chan2, all_financial, msg_handler2);<br><br> //register chat msg type for marshaling/demarshaling<br> chat_chan::text_marshaler_registry mar_reg;<br> mar_reg.register_default_msg_marshaler&lt;chat_msg&gt;();<br></span>
</pre>
+Here we create shared memory "stream" to connect to remote channel;
+notice that the 1st argument is "true", so the shared memory message
+queue will be created if it doesn't exist.<br>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"> //create shmem stream and connect to channel<br> shmem_stream&lt;<br> id_type,<br> chat_chan::text_marshaler_registry,<br> timeout_type<br> &gt; <br> shmstream(true, que_name, que_max_num, que_max_size, mar_reg); //i'll create shmem<br> connect(chan, &amp;shmstream, false); //i am passive side</span><span
+ style="color: rgb(153, 0, 0);"><br></span></pre>
+<br>
+Complete source code listing:<br>
+chat_defs.hpp<br>
+chat1.cpp<br>
+chat2.cpp<br>
+<br>
+</body>
+</html>

Added: sandbox/channel/libs/channel/example/chat_thru_server/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_thru_server/Jamfile.v2 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#
+#//
+#// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+#//
+#// Distributed under the Boost Software License, Version 1.0. (See accompanying
+#// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#//
+
+
+import os ;
+
+if [ os.name ] = SOLARIS
+{
+ lib socket ;
+ lib nsl ;
+}
+else if [ os.name ] = NT
+{
+ lib ws2_32 ;
+ lib mswsock ;
+}
+
+project
+ : requirements
+ <library>/boost/serialization//boost_serialization
+ <library>/boost/thread//boost_thread
+ <library>/boost/system//boost_system
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <os>SOLARIS:<library>socket
+ <os>SOLARIS:<library>nsl
+ <os>NT,<toolset>gcc:<library>ws2_32
+ <os>NT,<toolset>gcc:<library>mswsock
+ ;
+
+obj chat_cli.obj : chat_cli.cpp ;
+exe chat_cli : chat_cli.obj ;
+obj chat_srv.obj : chat_srv.cpp ;
+exe chat_srv : chat_srv.obj ;

Added: sandbox/channel/libs/channel/example/chat_thru_server/chat_cli.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_thru_server/chat_cli.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,112 @@
+//
+// chat_cli.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/channel/streams/asio_stream_async.hpp>
+#include "./chat_defs.hpp"
+
+//chat msg handler; print out data
+void msg_handler(id_type id, boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << msg->source_ << " speak on [" << chat_chan::id_trait::id_to_string(id) << "]:\n";
+ cout << msg->data_ << endl;
+}
+
+int main(int argc, char **argv) {
+ if (argc < 4) {
+ std::cout << "Usage: chat_cli chatter_name srv_name srv_port\n";
+ exit(0);
+ }
+ const char *my_name = argv[1];
+ const char *srv_name = argv[2];
+ const char *srv_port = argv[3];
+ try {
+ //create asio io_service
+ boost::asio::io_service io_service;
+ //create asio_executor and run callbacks in asio main thread
+ asio_executor asio_exec(io_service);
+ //create local channel
+ chat_chan chan(&asio_exec);
+
+ //register chat msg type for marshaling/demarshaling
+ chat_chan::text_marshaler_registry mar_reg;
+ mar_reg.register_default_msg_marshaler<chat_msg>();
+
+ //create asio connectors and connect to chat server
+ asio_connector_async connector(io_service);
+ connector.async_connect(srv_name, srv_port,
+ boost::bind(asio_bind_sock_chan<chat_chan, chat_chan::text_marshaler_registry>(),
+ boost::ref(chan), boost::ref(mar_reg), _1, _2, _3));
+
+ //a separate thread to run io_service
+ boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));
+
+ //in main thread, we pub/sub subjects and send/recv msgs
+ chat_chan::publisher pub(chan);
+ chat_chan::subscriber sub(chan, msg_handler);
+
+ bool cont = true;
+ char buf[1024];
+ while (cont) {
+ cout << "action : 1-join, 2-leave, 3-send, 4-exit:\n";
+ int action;
+ cin.getline(buf, 1024);
+ action = atoi(buf);
+ switch (action) {
+ case 1:
+ case 2:
+ case 3:
+ {
+ cout << "subject: ";
+ cin.getline(buf, 1024);
+ id_type id(buf);
+ switch (action) {
+ case 1:
+ pub.publish(id);
+ sub.subscribe(id, chat_chan::in::scope_remote);
+ break;
+ case 2:
+ pub.unpublish(id);
+ sub.unsubscribe(id);
+ break;
+ case 3:
+ cout << "message: ";
+ cin.getline(buf, 1024);
+ pub.send(id, new chat_msg(my_name,buf));
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case 4:
+ cont = false;
+ break;
+ }
+ }
+
+ connector.shutdown();
+ t.join();
+ }
+ catch (boost::system::error_code& e)
+ {
+ std::cerr << e << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/chat_thru_server/chat_defs.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_thru_server/chat_defs.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,45 @@
+//
+// chat_defs.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#ifndef CHAT_DEFS_HPP
+#define CHAT_DEFS_HPP
+
+#include <string>
+#include <boost/channel/channel.hpp>
+#include <boost/channel/executors/asio_executor.hpp>
+
+using namespace std;
+using namespace boost::channel;
+
+//instantiate event channel type, using string as id_type
+typedef string id_type;
+typedef channel<
+ id_type,
+ boost_platform,
+ mt_synch<boost_platform>,
+ asio_executor //asynchronous channel
+ > chat_chan;
+
+//define sys ids
+DEFINE_STRING_SYS_IDS
+
+//a simple struct for chat msg
+struct chat_msg {
+ string source_;
+ string data_;
+ chat_msg(const char *s, const char *d) : source_(s), data_(d) {}
+ chat_msg() {} //have to define this for marshaling to work
+ //serialization function for chat_msg
+ template <typename Archive>
+ void serialize(Archive & ar, const unsigned int version)
+ {
+ ar &source_ & data_;
+ }
+};
+
+#endif

Added: sandbox/channel/libs/channel/example/chat_thru_server/chat_srv.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_thru_server/chat_srv.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,98 @@
+//
+// chat_srv.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/channel/streams/asio_stream_async.hpp>
+#include "./chat_defs.hpp"
+
+//chat srv handler: update name space based clients' publications and subscriptions
+//and forward chat msgs
+class msg_handler {
+public:
+ chat_chan::publisher pub;
+ chat_chan::subscriber sub;
+ msg_handler(chat_chan &chan) :
+ pub(chan),
+ sub(chan,boost::bind(&msg_handler::handling, this, _1,_2))
+ {
+ //subscribe to name space change events
+ sub.subscribe(chat_chan::publication_info_msg, chat_chan::in::scope_remote);
+ }
+ void handling(id_type id, boost::shared_ptr<void> p)
+ {
+ typedef pubsub_info_msg_t<id_type> pubsub_info_msg_t;
+ pubsub_info_msg_t *pubsub_info = NULL;
+ if(id == chat_chan::publication_info_msg) {
+ pubsub_info = (pubsub_info_msg_t *) p.get();
+ for(std::vector<id_type>::iterator iter = pubsub_info->msg_types.begin();
+ iter != pubsub_info->msg_types.end(); iter++) {
+ pub.publish((*iter), chat_chan::in::scope_remote);
+ sub.subscribe((*iter), chat_chan::in::scope_remote);
+ }
+ }
+ else { //chat subject ids
+ //forward chat msgs to subscribers
+ pub.send(id, p);
+ }
+ }
+};
+
+
+/**
+ * here we are going to use the publish/subscribe API built on top of
+ * named_in/named_out
+ */
+
+int main(int argc, char **argv) {
+ if (argc < 2) {
+ std::cout << "Usage: chat_srv srv_port\n";
+ exit(0);
+ }
+
+ const char * srv_port = argv[1];
+
+ try {
+ //create asio io_service
+ boost::asio::io_service io_service;
+ //create asio_executor and run callbacks in asio main thread
+ asio_executor asio_exec(io_service);
+ //create local channel and run all its async operations in asio_exec
+ chat_chan chan(&asio_exec);
+
+ //pub/sub subjects and forard msgs
+ msg_handler handler(chan);
+
+ //register chat msg type for marshaling/demarshaling
+ chat_chan::text_marshaler_registry mar_reg;
+ mar_reg.register_default_msg_marshaler<chat_msg>();
+
+ //create asio connectors and connect to remote channel
+ asio_connector_async connector(io_service);
+ connector.async_accept(atoi(srv_port), // channel address
+ boost::bind(asio_bind_sock_chan<chat_chan, chat_chan::text_marshaler_registry>(),
+ boost::ref(chan), boost::ref(mar_reg), _1, _2,_3));
+
+ //main loop
+ io_service.run();
+ }
+ catch (boost::system::error_code& e)
+ {
+ std::cerr << e << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/chat_thru_server/sample7_text.html
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/chat_thru_server/sample7_text.html 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,197 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+</head>
+<body style="color: rgb(0, 0, 0);" alink="#ee0000" link="#0000ee"
+ vlink="#551a8b">
+<h2>Sample 7.&nbsp; distributed chat thru a central server</h2>
+This sample shows simple chat client and server design. Clients connect
+to server to chat with each other in seperate chat groups identified by
+subject. The chat subject (a string) is the ids in name space. Clients
+can join/leave chat groups identified by subject ids and send messages
+to chat groups. If the chat group (subject) doesn't exist yet, the
+first member's "join" will make it created; so unlimited number of
+subjects (thus chat groups) can be added to the name space.<br>
+<br>
+Here are code for chat client (chat_cli.cpp):<br>
+We first define the handler function for chat messages, simply print
+them out.<br>
+<pre
+ style="background-color: rgb(204, 204, 204); color: rgb(153, 0, 0);">void msg_handler(id_type id, boost::shared_ptr&lt;void&gt; p)<br>{<br> chat_msg *msg = (chat_msg *) p.get();<br> cout &lt;&lt; msg-&gt;source_ &lt;&lt; " speak on [" &lt;&lt; chat_chan::id_trait::id_to_string(id) &lt;&lt; "]:\n";<br> cout &lt;&lt; msg-&gt;data_ &lt;&lt; "\n";<br>}<br></pre>
+Chat clients start with 3 command line arguments: chatter's name,
+chat_server host name and port number:<br>
+<pre
+ style="background-color: rgb(204, 204, 204); color: rgb(153, 0, 0);">int main(int argc, char **argv) {<br> if (argc &lt; 4) {<br> std::cout &lt;&lt; "Usage: chat_cli chatter_name srv_name srv_port\n";<br> exit(0);<br> }<br> const char *my_name = argv[1];<br> const char *srv_name = argv[2];<br> const char *srv_port = argv[3];<br></pre>
+Next, we create ASIO io_service object; create a asio_executor object
+and create an asynchronous channel which will execute all its callbacks
+in asio_executor (in ASIO's main thread).<br>
+<pre
+ style="background-color: rgb(204, 204, 204); color: rgb(153, 0, 0);"> try {<br> boost::asio::io_service io_service;<br> asio_executor asio_exec(io_service);<br> chat_chan chan(&amp;asio_exec);<br></pre>
+Since chat messages will move from one client to server and to other
+subscribed clients, they need to be marshaled/demarshaled for
+transmission. Use channel's text_marshaler_registry which is based on
+Boost.Serialization. Since we only have one message data type, we can
+register its type as default (If we have more than one message data
+types, we can register the major one as default and register other with
+its corresponding ids.<br>
+<pre
+ style="background-color: rgb(204, 204, 204); color: rgb(153, 0, 0);"> chat_chan::text_marshaler_registry mar_reg;<br> mar_reg.register_default_msg_marshaler&lt;chat_msg&gt;();<br></pre>
+Connect chat channel to remote server as following and spawn a separate
+thread run ASIO's main loop:<br>
+<pre
+ style="background-color: rgb(204, 204, 204); color: rgb(153, 0, 0);"> asio_connector connector(io_service);<br> connector.async_connect(srv_name, srv_port, //remote channel address<br> boost::bind(asio_bind_sock_chan&lt;chat_chan, chat_chan::text_marshaler_registry&gt;(), <br> boost::ref(chan), boost::ref(mar_reg), _1, _2));<br> boost::thread t(boost::bind(&amp;boost::asio::io_service::run, &amp;io_service));<br></pre>
+In main thread, we handle chat clients main activities: join/leave
+chat_groups(subjects) and send/receive messages<br>
+<pre
+ style="background-color: rgb(204, 204, 204); color: rgb(153, 0, 0);"> chat_chan::publisher pub(chan);<br> chat_chan::subscriber sub(chan, msg_handler);<br><br> bool cont = true;<br> char buf[1024];<br> while (cont) {<br></pre>
+Clients can do 3 major things: join chat_group (subject), leave
+chat_group and send messages to chat_groups. If the chat group
+(subject) doesn't exist yet, the
+first member's "join" will make it created.
+<pre
+ style="background-color: rgb(204, 204, 204); color: rgb(153, 0, 0);"> cout &lt;&lt; "action : 1-join, 2-leave, 3-send, 4-exit:\n";<br> int action;<br> cin.getline(buf, 1024);<br> action = atoi(buf);<br> switch (action) {<br> case 1:<br> case 2:<br> case 3:<br> {<br> cout &lt;&lt; "subject: ";<br> cin.getline(buf, 1024);<br> id_type id(buf);<br> switch (action) {<br> case 1:<br></pre>
+we join the chat_group by both publishing and subscribing the subject
+id:<br>
+<pre
+ style="background-color: rgb(204, 204, 204); color: rgb(153, 0, 0);"> pub.publish(id);<br> sub.subscribe(id);<br> break;<br> case 2:<br></pre>
+we leave the chat_group by both unpublishing and unsubscribing the
+subject id:
+<pre
+ style="background-color: rgb(204, 204, 204); color: rgb(153, 0, 0);"> pub.unpublish(id);<br> sub.unsubscribe(id);<br> break;<br> case 3:<br></pre>
+clients send messages:<br>
+<pre
+ style="background-color: rgb(204, 204, 204); color: rgb(153, 0, 0);"> cout &lt;&lt; "message: ";<br> cin.getline(buf, 1024);<br> pub.send(id, new chat_msg(my_name,buf));<br> break;<br> default:<br> break;<br> }<br></pre>
+<br>
+Next let's step thru the server code (chat_srv.cpp).
+In
+normal chat server design based on basic socket, the chat server has 2
+main responsibilities: maintaining membership info (which clients are
+in which chat groups) and forwarding messages. Channel's facilities
+greatly simplifies the design and code of chat server.<br>
+First, channel has 4 internal system messages notifying about name
+space changes:<br>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="color: rgb(153, 0, 0);"> id_type subscription_info_msg;</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> id_type unsubscription_info_msg;</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> id_type publication_info_msg;</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> id_type unpublication_info_msg;</span><br></pre>
+These internal system messages are defined inside id_trait class of
+channel type. Application code can bind to (or subscribe to) these
+system messages to get notified whenever name space changes (such as
+some peers join in and starts publishing and subscribing messages).<br>
+During chatting, whenever a client join a group (subject), it will
+publish/send messages on this subject and subscribe/receive messages on
+this subject. By subscribing to <span style="color: rgb(153, 0, 0);"><span
+ style="color: rgb(0, 0, 0);">publication_info_msg, chat servers can
+know when a client joins a group and the subject of this group. In the
+following msg_handler function, chat server does the following to
+fullfill its 2 responsibilities:<br>
+</span></span>
+<ul>
+ <li>When server receives name space change message (<span
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);">publication_info_msg):</span></span></li>
+ <ul>
+ <li>server retrieves ids from publication_info_msg and subscribes
+to these ids, so all of the messages
+about this subject (or in this group) will be sent to server</li>
+ <li>server publishes these subject ids, so all the clients which
+are
+in this group will be connected to server to receive messages in this
+group</li>
+ </ul>
+ <li>When server receives chat messages, just forward them<br>
+ </li>
+</ul>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);">void msg_handler(chat_chan::publisher &amp;pub,</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> chat_chan::subscriber &amp;sub,</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> id_type id, boost::shared_ptr&lt;void&gt; p, int sz, timeout_type * t)</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);">{</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> typedef pubsub_info_msg_t&lt;id_type&gt; pubsub_info_msg_t;</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> pubsub_info_msg_t *pubsub_info = NULL;</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> if(id == chat_chan::publication_info_msg) {</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> //update name space based clients' publications and subscriptions</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> //and forward chat msgs</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"> pubsub_info = (pubsub_info_msg_t *) p.get();</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> for(std::vector&lt;id_type&gt;::iterator iter = pubsub_info-&gt;msg_types.begin();</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> iter != pubsub_info-&gt;msg_types.end(); iter++) {</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> pub.publish((*iter), chat_chan::in::scope_remote);</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> sub.subscribe((*iter), chat_chan::in::scope_remote);</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> }</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> }</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> else { //chat subject ids</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> //forward chat msgs to subscribers</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> pub.send(id, p, sz, t);</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> }</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);">}<br></span></pre>
+Chat server's main function is simple, having port number as only
+argument:<br>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);">int main(int argc, char **argv) {</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> if (argc &lt; 2) {</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> std::cout &lt;&lt; "Usage: chat_srv srv_port\n";</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> exit(0);</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> }</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> </span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> const char * srv_port = argv[1];</span><br
+ style="color: rgb(153, 0, 0);"></pre>
+Similar to chat client code,&nbsp; we create an asynchronous channel
+with asio_executor:<br>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="color: rgb(153, 0, 0);"> try {</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"> boost::asio::io_service io_service;</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"> asio_executor asio_exec(io_service);</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"> chat_chan chan(&amp;asio_exec);</span><br
+ style="color: rgb(153, 0, 0);"></pre>
+Next we create channel publisher and subscriber and bind message handler<br>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"> chat_chan::publisher pub(chan);</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> chat_chan::subscriber sub(chan, boost::bind(msg_handler, boost::ref(pub), </span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> boost::ref(sub), _1,_2));<br></span></pre>
+We subscribe to name space change message here then,<br>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"></span><span
+ style="color: rgb(153, 0, 0);"> </span><span
+ style="color: rgb(153, 0, 0);"> sub.subscribe(chat_chan::publication_info_msg, chat_chan::in::scope_remote);</span><br
+ style="color: rgb(153, 0, 0);"></pre>
+Then same as chat client, server create message marshaler,
+asio_connector and start waiting for remote clients connections:<br>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="color: rgb(153, 0, 0);"> //register chat msg type for marshaling/demarshaling</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> chat_chan::text_marshaler_registry mar_reg;</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> mar_reg.register_default_msg_marshaler&lt;chat_msg&gt;();</span><br
+ style="color: rgb(153, 0, 0);"><br style="color: rgb(153, 0, 0);"><span
+ style="color: rgb(153, 0, 0);"> //create asio connectors and connect to remote channel</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> asio_connector connector(io_service);</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> connector.async_accept(atoi(srv_port), // channel address</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> boost::bind(asio_bind_sock_chan&lt;chat_chan, chat_chan::text_marshaler_registry&gt;(), </span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> boost::ref(chan), boost::ref(mar_reg), _1, _2));</span><br
+ style="color: rgb(153, 0, 0);"><br style="color: rgb(153, 0, 0);"><span
+ style="color: rgb(153, 0, 0);"> //main loop</span><br
+ style="color: rgb(153, 0, 0);"><span style="color: rgb(153, 0, 0);"> io_service.run();<br></span></pre>
+A sample scenario could be as following:<br>
+<ol>
+ <li>start chat server:&nbsp; ./chat_srv 4455<br>
+ </li>
+ <li>start 2 chat clients and connect to server: ./chat_cli steve
+localhost 4455 and ./chat_cli regean localhost 4455<br>
+ </li>
+ <li>join chat&nbsp; groups in clients</li>
+ <li>send messages to groups</li>
+</ol>
+Complete source code listing:<br>
+chat_defs.hpp<br>
+chat_cli.cpp<br>
+chat_srv.cpp<br>
+<br>
+</body>
+</html>

Added: sandbox/channel/libs/channel/example/dist_evt_chan/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/dist_evt_chan/Jamfile.v2 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,43 @@
+#
+# Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#
+#//
+#// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+#//
+#// Distributed under the Boost Software License, Version 1.0. (See accompanying
+#// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#//
+
+import os ;
+
+if [ os.name ] = SOLARIS
+{
+ lib socket ;
+ lib nsl ;
+}
+else if [ os.name ] = NT
+{
+ lib ws2_32 ;
+ lib mswsock ;
+}
+
+project
+ : requirements
+ <library>/boost/serialization//boost_serialization
+ <library>/boost/thread//boost_thread
+ <library>/boost/system//boost_system
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <os>SOLARIS:<library>socket
+ <os>SOLARIS:<library>nsl
+ <os>NT,<toolset>gcc:<library>ws2_32
+ <os>NT,<toolset>gcc:<library>mswsock
+ ;
+
+obj evt_chan1.obj : evt_chan1.cpp ;
+exe evt_chan1 : evt_chan1.obj ;
+obj evt_chan2.obj : evt_chan2.cpp ;
+exe evt_chan2 : evt_chan2.obj ;

Added: sandbox/channel/libs/channel/example/dist_evt_chan/evt_chan1.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/dist_evt_chan/evt_chan1.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,141 @@
+//
+// evt_chan1.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <boost/thread.hpp>
+#include <boost/channel/streams/asio_stream_async.hpp>
+#include <boost/channel/executors/asio_executor.hpp>
+#include "./evt_chan_defs.hpp"
+
+class gui_window {
+ evt_chan & chan_;
+ //a few event src
+ evt_chan::out down_out_;
+ evt_chan::out up_out_;
+ evt_chan::out close_out_;
+ ///should wait for remote channel conneted and ids/names bound and
+ ///then fire some sample events
+ bool rmt_down_bound;
+ bool rmt_up_bound;
+ bool rmt_close_bound;
+public:
+ gui_window(evt_chan & c):
+ chan_(c),
+ down_out_(chan_,
+ down_id,
+ boost::bind(&gui_window::binding_callback, this, _1, _2)),
+ up_out_(chan_,
+ up_id,
+ boost::bind(&gui_window::binding_callback, this, _1, _2)),
+ close_out_(chan_,
+ close_id,
+ boost::bind(&gui_window::binding_callback, this, _1, _2)),
+ rmt_down_bound(false),rmt_up_bound(false),rmt_close_bound(false)
+ {
+ }
+
+ //methods to fire some events
+ void up(const char * msg) {
+ up_out_.send(new evt_data(msg));
+ }
+ void down(const char * msg) {
+ down_out_.send(new evt_data(msg));
+ }
+ void close(const char * msg) {
+ close_out_.send(new evt_data(msg));
+ }
+
+ void binding_callback(evt_chan::name *n, evt_chan::name::binding_event e) {
+ if (n->type_ == evt_chan::name::member_remote && e == evt_chan::name::bind_ev) {
+ if (n->id_ == down_id) rmt_down_bound = true;
+ if (n->id_ == up_id) rmt_up_bound = true;
+ if (n->id_ == close_id) rmt_close_bound = true;
+ ///fire sample events after remote peer connected and ids bound
+ if (rmt_down_bound && rmt_up_bound && rmt_close_bound) {
+ up("..Hi there [mouse-left-up] ..");
+ down(".. a simple window test [mouse-right-down] ..");
+ close(".. simple window wiered [window-closed] ..");
+ }
+ }
+ }
+};
+
+class window_handler {
+ evt_chan & ch_;
+ //a few event sinks
+ evt_chan::in *down_in_;
+ evt_chan::in *up_in_;
+ evt_chan::in *close_in_;
+public:
+ window_handler(evt_chan & c): ch_(c) {
+ down_in_ = ch_.bind_name_in(down_id, boost::bind(&window_handler::down, this, _1, _2));
+ up_in_ = ch_.bind_name_in(up_id, boost::bind(&window_handler::up, this, _1, _2));
+ close_in_ = ch_.bind_name_in(close_id, boost::bind(&window_handler::close, this, _1, _2));
+ }
+ ~window_handler() {
+ delete down_in_;
+ delete up_in_;
+ delete close_in_;
+ }
+
+ //methods to handle events
+ void down(string id, boost::shared_ptr<void> p) {
+ cout << "window_handler::DOWN ... recv event [id=" << id << "], [data=" << ((evt_data*)p.get())->data_ << "]" << endl;
+ }
+ void up(string id, boost::shared_ptr<void> p) {
+ cout << "window_handler::UP ... recv event [id=" << id << "], [data=" << ((evt_data*)p.get())->data_ << "]" << endl;
+ }
+ void close(string id, boost::shared_ptr<void> p) {
+ cout << "window_handler::CLOSE ... recv event [id=" << id << "], [data=" << ((evt_data*)p.get())->data_ << "]" << endl;
+ }
+};
+
+
+int main(int, char **) {
+ try {
+ //create asio io_service
+ boost::asio::io_service io_service;
+ //create asio_executor
+ asio_executor asio_exec(io_service);
+ //create local channel and run all its async operations in asio_exec
+ evt_chan chan(&asio_exec);
+
+ //bind event source (window) to channel and register name_binding_callback
+ //so that when remote channel connected and name bound, we can start firing sample events
+ gui_window window(chan);
+ //bind event sink (handler) to channel
+ window_handler hdlr(chan);
+
+ //register event msg type for marshaling/demarshaling
+ evt_chan::text_marshaler_registry mar_reg;
+ std::vector<evt_chan::id_type> ids;
+ ids.push_back(down_id);
+ ids.push_back(up_id);
+ ids.push_back(close_id);
+ mar_reg.register_msg_marshaler<evt_data>(ids);
+
+ //create asio connectors and connect to remote channel
+ asio_connector_async connector(io_service);
+ connector.async_connect("localhost", "6666", //remote channel address
+ boost::bind(asio_bind_sock_chan<evt_chan, evt_chan::text_marshaler_registry>(),
+ boost::ref(chan), boost::ref(mar_reg), _1, _2,_3));
+ io_service.run();
+ }
+ catch (boost::system::error_code& e)
+ {
+ std::cerr << e << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/dist_evt_chan/evt_chan2.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/dist_evt_chan/evt_chan2.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,58 @@
+//
+// evt_chan2.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <boost/channel/streams/asio_stream_async.hpp>
+#include <boost/channel/executors/asio_executor.hpp>
+#include "./evt_chan_defs.hpp"
+
+//free event handler; print out data
+void evt_handler(string id, boost::shared_ptr<void> p)
+{
+ cout << "free handler ... recv event [id=" << id << "], [data=" << ((evt_data*)p.get())->data_ << "]" << endl;
+}
+
+int main(int, char **) {
+ //create local event channel
+ evt_chan chan;
+ //bind event sinks to channel
+ evt_chan::in window_down_in(chan, down_id, evt_handler);
+ evt_chan::in window_up_in(chan, up_id, evt_handler);
+ evt_chan::in shut_down_in(chan, close_id, evt_handler);
+
+ //register event msg type for marshaling/demarshaling
+ evt_chan::text_marshaler_registry mar_reg;
+ std::vector<evt_chan::id_type> ids;
+ ids.push_back(down_id);
+ ids.push_back(up_id);
+ ids.push_back(close_id);
+ mar_reg.register_msg_marshaler<evt_data>(ids);
+
+ //create asio connectors and wait for remote conn to local channel
+ try {
+ boost::asio::io_service io_service;
+ asio_connector_async connector(io_service);
+ connector.async_accept(6666, //channel published at port 6666
+ boost::bind(asio_bind_sock_chan<evt_chan, evt_chan::text_marshaler_registry>(),
+ boost::ref(chan), boost::ref(mar_reg), _1, _2,_3));
+
+ io_service.run();
+ }
+ catch (boost::system::error_code& e)
+ {
+ std::cerr << e << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/dist_evt_chan/evt_chan_defs.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/dist_evt_chan/evt_chan_defs.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,49 @@
+//
+// evt_chan_defs.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#ifndef EVT_CHAN_DEFS_HPP
+#define EVT_CHAN_DEFS_HPP
+
+#include <string>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/channel/channel.hpp>
+
+using namespace std;
+using namespace boost::channel;
+
+//instantiate event channel type, using string as id_type
+//and execute all async operations in asio executor
+typedef channel<string,
+ boost_platform,
+ mt_synch<boost_platform>,
+ asio_executor> evt_chan;
+
+//define sys ids
+DEFINE_STRING_SYS_IDS
+
+//app event ids in name_space
+//sample events for a gui window
+string down_id = "_window_button_down_";
+string up_id = "_window_button_up_";
+string close_id = "_window_close_";
+
+//a simple struct for event data
+struct evt_data {
+ string data_;
+ evt_data(const char *d) : data_(d) {}
+ evt_data() {} //have to define this for marshaling to work
+ //serialization function for evt_data
+ template <typename Archive>
+ void serialize(Archive & ar, const unsigned int version)
+ {
+ ar & data_;
+ }
+};
+
+#endif

Added: sandbox/channel/libs/channel/example/dist_evt_chan/sample3_text.html
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/dist_evt_chan/sample3_text.html 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,309 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+</head>
+<body>
+<h2>Sample 3: Distributed Event Channel<br>
+</h2>
+<br>
+This sample is based on Sample1 with changes to show how remote
+channels can be connected to facilitate distributed events dispatching.<br>
+<br>
+Now we put the event source (gui_window) in one process with some local
+event sinks and connect it to another process which contains other
+event
+sinks. We are going to use Boost.Asio to set up tcp socket for remote
+connection transport.<br>
+<br>
+All major data types are defined in a common header file <a
+ href="evt_chan_defs.hpp">evt_chan_defs.hpp.</a><br>
+<br>
+First we need to instantiate the concrete channel class. Different from
+Sample1 and Sample2, we are going to make Channel <span
+ style="font-weight: bold;">asynchronous</span> which means that
+callbacks are not executed by the event sending thread directly (or in
+place). In stead callbacks will be scheduled and executed lated in an
+executor. For best integration with asio, Channel provides a special
+executor (asio_executor) to dispatch asynchronous operations to asio's
+main thread. So here is our channel type:<br>
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">typedef
+channel&lt;string, </span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; boost_platform,</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; mt_synch&lt;boost_platform&gt;,</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; asio_executor&gt; evt_chan;</span><br>
+Channel's implementation depends on some system facilities, such as
+mutex, condition, timers. To facilitate platform independence, these
+facilties are defined as nested types inside "platform" wrapper class,
+such as boost_platform used here. mt_synch is synchronization policy
+class for thread safe operations, while another class
+null_synch&lt;&gt; contains empty "null" definitions of synchronization
+primitives and can be used for single threaded application.<br>
+<br>
+Next we define event ids and data structure the same as Sample1.<br>
+<br>
+Since we are doing distributed event dispatching now, the
+messages/event_data need be marshaled/demarshaled across process
+boundary. Channel uses Boost.Serialization for message marshaling. So
+the message class contains the following serialize() method:<br>
+<span
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">struct
+evt_data {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">
+<span
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">&nbsp;
+string data_;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">
+<span
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">&nbsp;
+evt_data(const char *d) : data_(d) {}</span><br
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">
+<span
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">&nbsp;
+evt_data() {} //have to define this for marshaling to work</span><br
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">
+<span
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">&nbsp;
+//serialization function for evt_data</span><br
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">
+<span
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">&nbsp;
+template &lt;typename Archive&gt;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">
+<span
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">&nbsp;
+void serialize(Archive &amp; ar, const unsigned int version)</span><br
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">
+<span
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">&nbsp;
+{</span><br
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">
+<span
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">&nbsp;&nbsp;&nbsp;
+ar &amp; data_;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">
+<span
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">&nbsp;
+}</span><br
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">
+<span
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">};</span><br>
+<br>
+In file evt_chan1.cpp,
+we first define event source (gui_window) and handler class
+(window_handler) the same as Sample1 and Sample2. <br>
+Next we introduce a major addition in this sameple - name binding
+callback. Since we are going to connect channels in 2 processes and
+send events to remote process, we must start sending events after the
+remote process connect in and bind to event ids. Otherwise events will
+be lost. Channel allows registering callbacks to
+names (named_in and named_out) so that application will be notified
+when
+remote peers connect in and bind. The following is the binding callback
+in this sample in which we start sending events after remote peers
+connect and bind:<br>
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">void
+name_binding_callback(evt_chan::name *n, </span><span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">evt_chan::name::binding_event
+e) {</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;
+if (n-&gt;type_ == evt_chan::name::member_remote &amp;&amp; e ==
+evt_chan::name::bind_ev) {</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+if (n-&gt;id_ == down_id) rmt_down_bound = true;</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+if (n-&gt;id_ == up_id) rmt_up_bound = true;</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+if (n-&gt;id_ == close_id) rmt_close_bound = true;</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+///fire sample events after remote peer connected and ids bound</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+if (rmt_down_bound &amp;&amp; rmt_up_bound &amp;&amp; rmt_close_bound) {</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+window-&gt;up("..Hi there [mouse-left-up] ..");</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+window-&gt;down(".. a simple window test [mouse-right-down] ..");</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+window-&gt;close(".. simple window wiered [window-closed] ..");</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+}</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;
+}</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">}</span><br>
+<br>
+Now the main function in evt_chan1.cpp:<br>
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">int
+main(int, char **) {</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;
+try {</span><br>
+First we create asio io_service and asio_executor for asynchronous
+operations.<br>
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+boost::asio::io_service io_service;</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+asio_executor asio_exec(io_service);</span><br>
+Next create local channel and configure it to run all its async
+operations in asio_exec<br>
+<span
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">&nbsp;&nbsp;&nbsp;
+evt_chan chan(&amp;asio_exec);</span><br>
+Same as Sample1 and Sample2, create event source (gui_window) and
+handler and bind them to channel. Also name binding callback is
+registered when creating gui_window.<br>
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+gui_window window(chan</span><span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">);</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+window_handler hdlr(chan);</span><br>
+Since event messages will be sent to remote process, they will be
+marshaled into on-wire format at sender side and demarshaled at
+receiver side. Channel's marshaling mechanism is based on
+Boost.Serialization. Here we register event/message data class
+(evt_data) with corresponding event ids in a marshaler registry inside
+which a marshaler object is created automatically for this data class.
+Later when socket connection is set up, we should specify the
+marshaler_registry to use:<br>
+<span
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">&nbsp;&nbsp;&nbsp;
+evt_chan::text_marshaler_registry mar_reg;</span><br
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">
+<span
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">&nbsp;&nbsp;&nbsp;
+std::vector&lt;evt_chan::id_type&gt; ids;</span><br
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">
+<span
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">&nbsp;&nbsp;&nbsp;
+ids.push_back(down_id);</span><br
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">
+<span
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">&nbsp;&nbsp;&nbsp;
+ids.push_back(up_id);</span><br
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">
+<span
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">&nbsp;&nbsp;&nbsp;
+ids.push_back(close_id);</span><br
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">
+<span
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">&nbsp;&nbsp;&nbsp;
+mar_reg.register_msg_marshaler&lt;evt_data&gt;(ids);</span><br>
+Now we create asio connector and connect local channel to remote
+channel. Since we are using asynchronous API at asio, we pass in a
+callback (asio_bind_sock_chan) asking asio_connector to connect socket
+streams to local channel, including which marshaler_registry to use.
+Here in evt_chan1.cpp, asio connector plays the active connecting role.<br>
+<span
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">&nbsp;&nbsp;&nbsp;
+asio_connector connector(io_service);</span><br
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">
+<span
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">&nbsp;&nbsp;&nbsp;
+connector.async_connect("localhost", "6666", //remote channel address</span><br
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">
+<span
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">&nbsp;&nbsp;&nbsp;
+boost::bind(asio_bind_sock_chan&lt;evt_chan,
+evt_chan::text_marshaler_registry&gt;(), </span><br
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">
+<span
+ style="color: rgb(204, 0, 0); font-weight: bold; font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; boost::ref(chan), boost::ref(mar_reg), _1, _2));<br>
+</span>Finally start asio main event loop.<br>
+<span style="color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+<span style="font-weight: bold; font-style: italic;">io_service.run();</span></span><br>
+<span style="color: rgb(204, 0, 0);">...</span><br
+ style="color: rgb(204, 0, 0);">
+<span style="color: rgb(204, 0, 0);">}</span><br>
+<br>
+In file evt_chan2.cpp,
+most code is similar to code in evt_chan1.cpp
+with one major difference: asio_connector plays the passive side of
+connection (accept):<br>
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;
+try {</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+boost::asio::io_service io_service;</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+asio_connector connector(io_service);</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+connector.async_accept(6666, //channel published at port 6666</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+boost::bind(asio_bind_sock_chan&lt;evt_chan,
+evt_chan::text_marshaler_registry&gt;(), </span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; boost::ref(chan),
+boost::ref(mar_reg), _1, _2));</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;&nbsp;&nbsp;
+io_service.run();</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(204, 0, 0);">&nbsp;
+}</span><br>
+<br>
+During testing, first start evt_chan2 and then start evt_chan1. From
+trace, we should see the events generated at evt_chan1 received and
+processed at both evt_chan1 and evt_chan2 processes.<br>
+<br>
+Here are complete source listing:<br>
+evt_chan_defs.hpp<br>
+evt_chan1.cpp<br>
+evt_chan2.cpp<br>
+<br>
+<br>
+</body>
+</html>

Added: sandbox/channel/libs/channel/example/filter_translator/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/filter_translator/Jamfile.v2 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,43 @@
+#
+# Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#
+#//
+#// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+#//
+#// Distributed under the Boost Software License, Version 1.0. (See accompanying
+#// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#//
+
+import os ;
+
+if [ os.name ] = SOLARIS
+{
+ lib socket ;
+ lib nsl ;
+}
+else if [ os.name ] = NT
+{
+ lib ws2_32 ;
+ lib mswsock ;
+}
+
+project
+ : requirements
+ <library>/boost/serialization//boost_serialization
+ <library>/boost/thread//boost_thread
+ <library>/boost/system//boost_system
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <os>SOLARIS:<library>socket
+ <os>SOLARIS:<library>nsl
+ <os>NT,<toolset>gcc:<library>ws2_32
+ <os>NT,<toolset>gcc:<library>mswsock
+ ;
+
+obj cli.obj : cli.cpp ;
+exe cli : cli.obj ;
+obj srv.obj : srv.cpp ;
+exe srv : srv.obj ;

Added: sandbox/channel/libs/channel/example/filter_translator/chat_defs.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/filter_translator/chat_defs.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,89 @@
+//
+// chat_defs.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#ifndef CHAT_DEFS_HPP
+#define CHAT_DEFS_HPP
+
+#include <string>
+#include <boost/channel/channel.hpp>
+#include <boost/channel/executors/asio_executor.hpp>
+
+using namespace std;
+using namespace boost::channel;
+
+//instantiate event channel type
+typedef string id_type;
+typedef channel<
+ id_type,
+ boost_platform,
+ mt_synch<boost_platform>,
+ asio_executor //asynchronous channel
+ > chat_chan;
+
+//define sys ids
+DEFINE_STRING_SYS_IDS
+
+class filter_t : public filter_type<string> {
+public:
+ string prefix;
+ filter_t(string pre) : prefix(pre) {}
+ bool block_inward (string &id) {
+ if (id.find(prefix) != 0) {
+ cout << "id [" << id << "] blocked at inward<" << prefix << ">" << endl;
+ return true;
+ }
+ return false;
+ }
+ bool block_outward (string &id) {
+ if (id.find(prefix) != 0) {
+ cout << "id [" << id << "] blocked at outward<" << prefix << ">" << endl;
+ return true;
+ }
+ return false;
+ }
+};
+
+class translator_t : public translator_type<string> {
+public:
+ string prefix;
+ translator_t(string pre) : prefix(pre) {}
+ void translate_inward (string & id) {
+ cout << "translate_inward : id[" << id << "] into [" ;
+ id = prefix + id;
+ cout << id << "]\n";
+ }
+ void translate_outward (string & id) {
+ cout << "translate_outward : id[" << id << "] into [" ;
+ id.erase(0,prefix.size());
+ cout << id << "]\n";
+ }
+};
+
+class binder : public binder_type<string> {
+public:
+ binder(string prefix) {
+ filter = new filter_t(prefix);
+ translator = new translator_t(prefix);
+ }
+};
+
+//a simple struct for chat msg
+struct chat_msg {
+ string source_;
+ string data_;
+ chat_msg(const char *s, const char *d) : source_(s), data_(d) {}
+ chat_msg() {} //have to define this for marshaling to work
+ //serialization function for chat_msg
+ template <typename Archive>
+ void serialize(Archive & ar, const unsigned int version)
+ {
+ ar &source_ & data_;
+ }
+};
+
+#endif

Added: sandbox/channel/libs/channel/example/filter_translator/cli.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/filter_translator/cli.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,112 @@
+//
+// cli.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/channel/streams/asio_stream_async.hpp>
+#include "./chat_defs.hpp"
+
+//chat msg handler; print out data
+void msg_handler(id_type id, boost::shared_ptr<void> p)
+{
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << msg->source_ << " speak on [" << chat_chan::id_trait::id_to_string(id) << "]:\n";
+ cout << msg->data_ << endl;
+}
+
+int main(int argc, char **argv) {
+ if (argc < 4) {
+ std::cout << "Usage: cli chatter_name srv_name srv_port\n";
+ exit(0);
+ }
+ const char *my_name = argv[1];
+ const char *srv_name = argv[2];
+ const char *srv_port = argv[3];
+ try {
+ //create asio io_service
+ boost::asio::io_service io_service;
+ //create asio_executor and run callbacks in asio main thread
+ asio_executor asio_exec(io_service);
+ //create local channel
+ chat_chan chan(&asio_exec);
+
+ //register chat msg type for marshaling/demarshaling
+ chat_chan::text_marshaler_registry mar_reg;
+ mar_reg.register_default_msg_marshaler<chat_msg>();
+
+ //create asio connectors and connect to chat server
+ asio_connector_async connector(io_service);
+ connector.async_connect(srv_name, srv_port,
+ boost::bind(asio_bind_sock_chan<chat_chan, chat_chan::text_marshaler_registry>(),
+ boost::ref(chan), boost::ref(mar_reg), _1, _2, _3));
+
+ //a separate thread to run io_service
+ boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));
+
+ //in main thread, we pub/sub subjects and send/recv msgs
+ chat_chan::publisher pub(chan);
+ chat_chan::subscriber sub(chan, msg_handler);
+
+ bool cont = true;
+ char buf[1024];
+ while (cont) {
+ cout << "action : 1-add id, 2-del id, 3-send, 4-exit:\n";
+ int action;
+ cin.getline(buf, 1024);
+ action = atoi(buf);
+ switch (action) {
+ case 1:
+ case 2:
+ case 3:
+ {
+ cout << "id: ";
+ cin.getline(buf, 1024);
+ id_type id(buf);
+ switch (action) {
+ case 1:
+ pub.publish(id);
+ sub.subscribe(id);
+ break;
+ case 2:
+ pub.unpublish(id);
+ sub.unsubscribe(id);
+ break;
+ case 3:
+ cout << "message: ";
+ cin.getline(buf, 1024);
+ pub.send(id, new chat_msg(my_name,buf));
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case 4:
+ cont = false;
+ break;
+ }
+ }
+
+ connector.shutdown();
+ t.join();
+ }
+ catch (boost::system::error_code& e)
+ {
+ std::cerr << e << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/filter_translator/sample11_text.html
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/filter_translator/sample11_text.html 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,248 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+</head>
+<body style="color: rgb(0, 0, 0);" alink="#ee0000" link="#0000ee"
+ vlink="#551a8b">
+<h2>Sample 11.&nbsp; channel name space management and security with
+filter and translator<br>
+</h2>
+Based on applications name space management requirements, we may need
+to "relocate"/"mount" the names imported (from a connection to a remote
+name space) to a specific sub-region in name space. For example, if we
+have a name space in desktop computer and connect to a PDA and a
+laptop, we can set translators at connections so that names imported
+from PDA will appear under "/pda/" and names from laptop will appear
+under "/laptop/". Or if our application use integer as ids/names, we
+may want to relocate ids from the 1st connection to [1000-1999] and ids
+from next connection to [2000-2999] and so on. That is similar to the
+way how we mount remote file-systems to local file-system.<br>
+Based on security requirements, we may need to use filters to restrict
+the valid range of names allowed to pass in/out specific channel
+connections. For example, a server's name space connect to 2 clients
+and we want that these clients' name spaces and messaging are totally
+separate, so that one client is unware of anything happening inside the
+other client's name space such as new name-publications and message
+passing. That is also similar to the way we protect network by
+firewalls and NATs.<br>
+<br>
+This sample uses a linear name space with strings as ids and implements
+a server which can connect to multiple clients. For each connection,
+the server will relocate the imported names to sub-region. For demo
+purpose, we simply put the names from clients under "/client0/...",
+"/client1/..."... and so on. So a name "basketball" in the first client
+will appear in server's name space as "/client0/basketball".<br>
+<br>
+First we define sample filter and translator in <a
+ href="./chat_defs.hpp">chat_defs.hpp</a>.<br>
+<br>
+When filter is created and bound for a connection,&nbsp; a prefix
+string ( such as "/client0/", "/client1/" ) is passed in . Then this
+filter will check name space change messages (init_subscription,
+publication/unpublication, subscription/unsubscription) to block
+names/ids which are not allowed; in our sample, valid names should
+begin with correct prefix. both input and output directions will be
+checked:<br>
+<div style="margin-left: 40px;"><span
+ style="color: rgb(153, 0, 0); font-style: italic;">class filter_t :
+public filter_type&lt;string&gt; {</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">public:</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; string
+prefix;</span><br style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;
+filter_t(string pre) : prefix(pre) {}</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; bool
+block_inward (string &amp;id) {</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+if (id.find(prefix) != 0) {</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+cout &lt;&lt; "id [" &lt;&lt; id &lt;&lt; "] blocked at inward&lt;"
+&lt;&lt; prefix &lt;&lt; "&gt;" &lt;&lt; endl;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+return true;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+}</span><br style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+return false;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; }</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; bool
+block_outward (string &amp;id) {</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+if (id.find(prefix) != 0) {</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+cout &lt;&lt; "id [" &lt;&lt; id &lt;&lt; "] blocked at outward&lt;"
+&lt;&lt; prefix &lt;&lt; "&gt;" &lt;&lt; endl;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+return true;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+}</span><br style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+return false;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; }</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">};</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<br>
+</div>
+When translator is created and bound for a connection,&nbsp; a prefix
+string (
+such as "/client0/", "/client1/" ) is passed in which designates where
+imported names will appear. Then both incoming and outgoing messages
+will be translated by the translator. In our simple demo, the
+translation is adding and removing of the prefix:<br>
+<div style="margin-left: 40px;"><span
+ style="color: rgb(153, 0, 0); font-style: italic;">class translator_t
+: public translator_type&lt;string&gt; {</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">public:</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; string
+prefix;</span><br style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;
+translator_t(string pre) : prefix(pre) {}</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; void
+translate_inward (string &amp; id) { </span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+cout &lt;&lt; "translate_inward : id[" &lt;&lt; id &lt;&lt; "] into [" ;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+id = prefix + id;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+cout &lt;&lt; id &lt;&lt;&nbsp; "]\n";</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; }</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; void
+translate_outward (string &amp; id) { </span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+cout &lt;&lt; "translate_outward : id[" &lt;&lt; id &lt;&lt; "] into ["
+;</span><br style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+id.erase(0,prefix.size());</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+cout &lt;&lt; id &lt;&lt; "]\n";</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; }</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">};</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<br>
+</div>
+A binder is just the combination of filter and translator.<br>
+<div style="margin-left: 40px;"><span
+ style="color: rgb(153, 0, 0); font-style: italic;">class binder :
+public binder_type&lt;string&gt; {</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">public:</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;
+binder(string prefix) {</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+filter = new filter_t(prefix);</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;&nbsp;&nbsp;
+translator = new translator_t(prefix);</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; }</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">};</span><br>
+</div>
+<br>
+Next lets see how filter and translator is set up in srv.cpp.<br>
+<br>
+In srv.cpp, we define the following callback function, so that a proper
+binder object will be created based on information about the connection
+(here we use information about socket). In real applications, we may
+need security provisions such as which range of ids/names are allowed
+for which remote connections. Here we simply relocate names for remote
+clients to "/client0/", "/client1/", etc.<br>
+<div style="margin-left: 40px;"><span
+ style="color: rgb(153, 0, 0); font-style: italic;">binder *
+binder_generator(boost::shared_ptr&lt;tcp::socket&gt; sock)</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">{</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;"></span><span
+ style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; static int
+num = 0;</span><br style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; string
+prefix = "/client";</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp;
+std::ostringstream os;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; os
+&lt;&lt; num;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; num++;</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">&nbsp; return
+new binder(prefix+os.str()+"/");</span><br
+ style="color: rgb(153, 0, 0); font-style: italic;">
+<span style="color: rgb(153, 0, 0); font-style: italic;">}<br>
+</span></div>
+<br>
+Next in srv.cpp when we accept connection from clients,
+binder_generator is passed in so that proper binder will be created and
+used for each new connection:<br>
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+connector.async_accept(atoi(srv_port), // channel address</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+boost::bind(asio_bind_sock_chan&lt;chat_chan,
+chat_chan::text_marshaler_registry&gt;(&amp;binder_generator), </span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; boost::ref(chan),
+boost::ref(mar_reg), _1, _2,_3));</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<br>
+A sample session could be as following:<br>
+1. start server<br>
+&nbsp;&nbsp;&nbsp; srv 8888<br>
+2. start first client (test1)<br>
+&nbsp;&nbsp;&nbsp; cli test1 localhost 8888<br>
+3. start 2nd client (test2)<br>
+&nbsp;&nbsp;&nbsp; cli test2 localhost 8888<br>
+4. in test1, add a new id/name such as "fishing"; from server's log,
+we'll see it appears in server's namespace as "/client0/fishing";<br>
+&nbsp;&nbsp;&nbsp; in test1, we can use "fishing" to send message to
+server, while at server we need to use "/client0/fishing" to send
+message to &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+test1.<br>
+5. in test2, add a new id/name such as "reading"; from server's log,
+we'll see it appears in server's namespace as "/client1/reading";<br>
+&nbsp;&nbsp;&nbsp; in test2, we can use "reading" to send message to
+server, while at
+server we need to use "/client1/reading" to send message to
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; test2.<br>
+6. notice that test1 is not aware of what is happening with test2 and
+vice versa.<br>
+<br>
+Complete source code listing:<br>
+chat_defs.hpp<br>
+cli.cpp<br>
+srv.cpp<br>
+<br>
+</body>
+</html>

Added: sandbox/channel/libs/channel/example/filter_translator/srv.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/filter_translator/srv.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,155 @@
+//
+// srv.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <sstream>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/channel/streams/asio_stream_async.hpp>
+#include "./chat_defs.hpp"
+
+//chat srv handler: update name space based clients' publications and subscriptions
+//and forward chat msgs
+class msg_handler {
+public:
+ chat_chan::publisher pub;
+ chat_chan::subscriber sub;
+ msg_handler(chat_chan &chan) :
+ pub(chan),
+ sub(chan,boost::bind(&msg_handler::handling, this, _1,_2))
+ {
+ //subscribe to name space change events
+ sub.subscribe(chat_chan::publication_info_msg, chat_chan::in::scope_remote);
+ }
+ void handling(id_type id, boost::shared_ptr<void> p)
+ {
+ typedef pubsub_info_msg_t<id_type> pubsub_info_msg_t;
+ pubsub_info_msg_t *pubsub_info = NULL;
+ if(id == chat_chan::publication_info_msg) {
+ pubsub_info = (pubsub_info_msg_t *) p.get();
+ for(std::vector<id_type>::iterator iter = pubsub_info->msg_types.begin();
+ iter != pubsub_info->msg_types.end(); iter++) {
+ cout << "server pub/sub to " << (*iter) << endl;
+ pub.publish((*iter), chat_chan::in::scope_remote);
+ sub.subscribe((*iter), chat_chan::in::scope_remote);
+ }
+ }
+ else if(id == chat_chan::unpublication_info_msg) {
+ pubsub_info = (pubsub_info_msg_t *) p.get();
+ for(std::vector<id_type>::iterator iter = pubsub_info->msg_types.begin();
+ iter != pubsub_info->msg_types.end(); iter++) {
+ pub.unpublish((*iter));
+ sub.unsubscribe((*iter));
+ }
+ }
+ else { //chat subject ids
+ chat_msg *msg = (chat_msg *) p.get();
+ cout << msg->source_ << " speak on [" << chat_chan::id_trait::id_to_string(id) << "]:\n";
+ cout << msg->data_ << endl;
+ }
+ }
+};
+
+/**
+ * binder_generator : based on security requirement and name_space management req
+ * we can use diff binders (filter & translator) for diff sock conn
+ */
+binder * binder_generator(boost::shared_ptr<tcp::socket> sock)
+{
+ //in real application we may create binders based on remote ip address
+ //here we just do simple
+ static int num = 0;
+ string prefix = "/client";
+ std::ostringstream os;
+ os << num;
+ num++;
+ return new binder(prefix+os.str()+"/");
+}
+
+/**
+ * here we are going to use the publish/subscribe API built on top of
+ * named_in/named_out
+ */
+
+int main(int argc, char **argv) {
+ if (argc < 2) {
+ std::cout << "Usage: chat_srv srv_port\n";
+ exit(0);
+ }
+
+ const char * my_name = "server";
+ const char * srv_port = argv[1];
+
+ try {
+ //create asio io_service
+ boost::asio::io_service io_service;
+ //create asio_executor and run callbacks in asio main thread
+ asio_executor asio_exec(io_service);
+ //create local channel and run all its async operations in asio_exec
+ chat_chan chan(&asio_exec);
+
+ //pub/sub subjects and forard msgs
+ msg_handler handler(chan);
+
+ //register chat msg type for marshaling/demarshaling
+ chat_chan::text_marshaler_registry mar_reg;
+ mar_reg.register_default_msg_marshaler<chat_msg>();
+
+ //create asio connectors and connect to remote channel
+ asio_connector_async connector(io_service);
+ connector.async_accept(atoi(srv_port), // channel address
+ boost::bind(asio_bind_sock_chan<chat_chan, chat_chan::text_marshaler_registry>(&binder_generator),
+ boost::ref(chan), boost::ref(mar_reg), _1, _2,_3));
+
+
+ //a separate thread to run io_service
+ boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));
+
+ bool cont = true;
+ char buf[1024];
+ while (cont) {
+ cout << "action : 1-send, 2-exit:\n";
+ int action;
+ cin.getline(buf, 1024);
+ action = atoi(buf);
+ switch (action) {
+ case 1:
+ {
+ cout << "subject: ";
+ cin.getline(buf, 1024);
+ id_type id(buf);
+ cout << "message: ";
+ cin.getline(buf, 1024);
+ handler.pub.send(id, new chat_msg(my_name,buf));
+ }
+ break;
+ case 2:
+ cont = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ connector.shutdown();
+ t.join();
+ }
+ catch (boost::system::error_code& e)
+ {
+ std::cerr << e << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/gui_evt/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/gui_evt/Jamfile.v2 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,20 @@
+#//
+#// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+#//
+#// Distributed under the Boost Software License, Version 1.0. (See accompanying
+#// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#//
+
+project
+ : requirements
+ <library>/boost/thread//boost_thread
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ ;
+
+obj gui_evt_chan1.obj : gui_evt_chan1.cpp ;
+exe gui_evt_chan1 : gui_evt_chan1.obj ;
+obj gui_evt_chan2.obj : gui_evt_chan2.cpp ;
+exe gui_evt_chan2 : gui_evt_chan2.obj ;
+obj gui_evt3.obj : gui_evt3.cpp ;
+exe gui_evt3 : gui_evt3.obj ;

Added: sandbox/channel/libs/channel/example/gui_evt/gui_evt3.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/gui_evt/gui_evt3.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,103 @@
+//
+// gui_evt3.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <string>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/channel/channel.hpp>
+
+using namespace std;
+using namespace boost::channel;
+
+//instantiate event channel type, using string as id_type
+typedef signal<> signal_type;
+typedef signal_type::slot slot_type;
+
+//a simple struct for event data
+struct evt_data {
+ string data_;
+ evt_data(const char *d) : data_(d) {}
+};
+
+class gui_window {
+public:
+ //a few event src
+ signal_type down_;
+ signal_type up_;
+ signal_type close_;
+
+ gui_window(): down_(),
+ up_(),
+ close_() {}
+ //methods to fire some events
+ void up(const char * msg) {
+ up_.send(new evt_data(msg));
+ }
+ void down(const char * msg) {
+ down_.send(new evt_data(msg));
+ }
+ void close(const char * msg) {
+ close_.send(new evt_data(msg));
+ }
+};
+
+class window_handler {
+ gui_window & win_;
+ slot_type *down_slot, *up_slot, *close_slot;
+public:
+ window_handler(gui_window & w): win_(w) {
+ down_slot = win_.down_.bind(boost::bind(&window_handler::down, this, _1));
+ up_slot = win_.up_.bind(boost::bind(&window_handler::up, this, _1));
+ close_slot = win_.close_.bind(boost::bind(&window_handler::close, this, _1));
+ }
+ ~window_handler() {
+ delete down_slot;
+ delete up_slot;
+ delete close_slot;
+ }
+ //methods to handle events
+ void down(boost::shared_ptr<void> p) {
+ cout << "window_handler::DOWN ... recv [data=" << ((evt_data*)p.get())->data_ << "]" << endl;
+ }
+ void up(boost::shared_ptr<void> p) {
+ cout << "window_handler::UP ... recv [data=" << ((evt_data*)p.get())->data_ << "]" << endl;
+ }
+ void close(boost::shared_ptr<void> p) {
+ cout << "window_handler::CLOSE ... recv [data=" << ((evt_data*)p.get())->data_ << "]" << endl;
+ }
+};
+
+
+//free event handler; print out data
+void evt_handler(boost::shared_ptr<void> p)
+{
+ cout << "free handler ... recv event [data=" << ((evt_data*)p.get())->data_ << "]" << endl;
+}
+
+int main(int, char **) {
+ //bind event source (window) to channel
+ gui_window window;
+
+ //bind event sink (handler) to channel
+ window_handler hdlr(window);
+
+ //bind more event sinks
+ window.down_.bind(evt_handler);
+ window.up_.bind(evt_handler);
+ window.close_.bind(evt_handler);
+
+ //fire events
+ window.up("..Hi there [mouse-left-up] ..");
+ window.down(".. a simple window test [mouse-right-down] ..");
+ window.close(".. simple window wiered [window-closed] ..");
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/gui_evt/gui_evt_chan1.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/gui_evt/gui_evt_chan1.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,118 @@
+//
+// gui_evt_chan1.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <iostream>
+#include <string>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/channel/channel.hpp>
+
+using namespace std;
+using namespace boost::channel;
+
+//instantiate event channel type, using string as id_type
+typedef channel<string> evt_chan;
+
+//define sys ids in name_space
+DEFINE_STRING_SYS_IDS
+
+//application ids: sample events for a gui window
+string down_id = "_window_button_down_";
+string up_id = "_window_button_up_";
+string close_id = "_window_close_";
+
+//a simple struct for event data
+struct evt_data {
+ string data_;
+ evt_data(const char *d) : data_(d) {}
+};
+
+class gui_window {
+ evt_chan & chan_;
+ //a few event src
+ evt_chan::out down_out_;
+ evt_chan::out up_out_;
+ evt_chan::out close_out_;
+public:
+ gui_window(evt_chan & c): chan_(c),
+ down_out_(chan_, down_id),
+ up_out_(chan_, up_id),
+ close_out_(chan_, close_id) {}
+ //methods to fire some events
+ void up(const char * msg) {
+ up_out_.send(new evt_data(msg));
+ }
+ void down(const char * msg) {
+ down_out_.send(new evt_data(msg));
+ }
+ void close(const char * msg) {
+ close_out_.send(new evt_data(msg));
+ }
+};
+
+class window_handler {
+ evt_chan & ch_;
+ //a few event sinks
+ evt_chan::in *down_in_;
+ evt_chan::in *up_in_;
+ evt_chan::in *close_in_;
+public:
+ window_handler(evt_chan & c): ch_(c) {
+ down_in_ = ch_.bind_name_in(down_id, boost::bind(&window_handler::down, this, _1, _2));
+ up_in_ = ch_.bind_name_in(up_id, boost::bind(&window_handler::up, this, _1, _2));
+ close_in_ = ch_.bind_name_in(close_id, boost::bind(&window_handler::close, this, _1, _2));
+ }
+ ~window_handler() {
+ delete down_in_;
+ delete up_in_;
+ delete close_in_;
+ }
+ //methods to handle events
+ void down(string id, boost::shared_ptr<void> p) {
+ cout << "window_handler::DOWN ... recv event [id=" << id << "], [data=" << ((evt_data*)p.get())->data_ << "]" << endl;
+ }
+ void up(string id, boost::shared_ptr<void> p) {
+ cout << "window_handler::UP ... recv event [id=" << id << "], [data=" << ((evt_data*)p.get())->data_ << "]" << endl;
+ }
+ void close(string id, boost::shared_ptr<void> p) {
+ cout << "window_handler::CLOSE ... recv event [id=" << id << "], [data=" << ((evt_data*)p.get())->data_ << "]" << endl;
+ }
+};
+
+
+//free event handler; print out data
+void evt_handler(string id, boost::shared_ptr<void> p)
+{
+ cout << "free handler ... recv event [id=" << id << "], [data=" << ((evt_data*)p.get())->data_ << "]" << endl;
+}
+
+int main(int, char **) {
+ //create event channel
+ evt_chan chan;
+
+ //bind event source (window) to channel
+ gui_window window(chan);
+
+ //bind event sink (handler) to channel
+ window_handler hdlr(chan);
+
+ //bind more event sinks
+ evt_chan::in window_down_in(chan, down_id, evt_handler);
+ evt_chan::in window_up_in(chan, up_id, evt_handler);
+ evt_chan::in shut_down_in(chan, close_id, evt_handler);
+
+ //fire events
+ window.up("..Hi there [mouse-left-up] ..");
+ window.down(".. a simple window test [mouse-right-down] ..");
+ window.close(".. simple window wiered [window-closed] ..");
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/gui_evt/gui_evt_chan2.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/gui_evt/gui_evt_chan2.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,120 @@
+//
+// gui_evt_chan2.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <iostream>
+#include <string>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/channel/channel.hpp>
+
+using namespace std;
+using namespace boost::channel;
+
+//instantiate event channel type, using struct_id as id_type
+typedef channel<struct_id> evt_chan;
+
+//define sys ids
+DEFINE_STRUCT_SYS_IDS
+
+//app event ids in name_space
+//sample events for a gui window
+struct_id win_but_down_id = {application_message, 1};
+struct_id win_but_up_id = {application_message, 2};
+struct_id win_close_id = {application_message, 3};
+
+//a simple struct for event data
+struct evt_data {
+ string data_;
+ evt_data(const char *d) : data_(d) {}
+};
+
+class gui_window {
+ evt_chan & chan_;
+ evt_chan::out down_out_;
+ evt_chan::out up_out_;
+ evt_chan::out close_out_;
+public:
+ gui_window(evt_chan & c): chan_(c),
+ down_out_(chan_, win_but_down_id),
+ up_out_(chan_, win_but_up_id),
+ close_out_(chan_, win_close_id) {}
+ //methods to fire some events
+ void up(const char * msg) {
+ up_out_.send(new evt_data(msg));
+ }
+ void down(const char * msg) {
+ down_out_.send(new evt_data(msg));
+ }
+ void close(const char * msg) {
+ close_out_.send(new evt_data(msg));
+ }
+};
+
+class window_handler {
+ evt_chan & ch_;
+ evt_chan::in *down_in_;
+ evt_chan::in *up_in_;
+ evt_chan::in *close_in_;
+public:
+ window_handler(evt_chan & c): ch_(c) {
+ down_in_ = ch_.bind_name_in(win_but_down_id, boost::bind(&window_handler::down, this, _1, _2));
+ up_in_ = ch_.bind_name_in(win_but_up_id, boost::bind(&window_handler::up, this, _1, _2));
+ close_in_ = ch_.bind_name_in(win_close_id, boost::bind(&window_handler::close, this, _1, _2));
+ }
+ ~window_handler() {
+ delete down_in_;
+ delete up_in_;
+ delete close_in_;
+ }
+ //methods to handle events
+ void down(struct_id id, boost::shared_ptr<void> p) {
+ cout << "window_handler::DOWN ... recv event [id=" << evt_chan::id_trait::id_to_string(id) << "], [data=" << ((evt_data*)p.get())->data_ << "]\n";
+ }
+ void up(struct_id id, boost::shared_ptr<void> p) {
+ cout << "window_handler::UP ... recv event [id=" << evt_chan::id_trait::id_to_string(id) << "], [data=" << ((evt_data*)p.get())->data_ << "]\n";
+ }
+ void close(struct_id id, boost::shared_ptr<void> p) {
+ cout << "window_handler::CLOSE ... recv event [id=" << evt_chan::id_trait::id_to_string(id) << "], [data=" << ((evt_data*)p.get())->data_ << "]\n";
+ }
+};
+
+
+//free event handler; print out data
+void evt_handler(struct_id id, boost::shared_ptr<void> p)
+{
+ cout << "free handler ... recv event [id=" << evt_chan::id_trait::id_to_string(id) << "], [data=" << ((evt_data*)p.get())->data_ << "]\n";
+}
+
+int main(int, char **) {
+ //create 2 event channels
+ evt_chan chan1;
+ evt_chan chan2;
+
+ //connect 2 channels
+ connect(chan1, chan2);
+
+ //bind event source (window) to channel1
+ gui_window window(chan1);
+
+ //bind event sink (handler) to channel1
+ window_handler hdlr(chan1);
+
+ //bind more event sinks to channel2
+ evt_chan::in window_down_in(chan2, win_but_down_id, evt_handler);
+ evt_chan::in window_up_in(chan2, win_but_up_id, evt_handler);
+ evt_chan::in shut_down_in(chan2, win_close_id, evt_handler);
+
+ //fire events
+ window.up("..Hi there [mouse-left-up] ..");
+ window.down(".. a simple window test [mouse-right-down] ..");
+ window.close(".. simple window wiered [window-closed] ..");
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/gui_evt/sample1_text.html
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/gui_evt/sample1_text.html 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,121 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+</head>
+<body style="color: rgb(0, 0, 0);" alink="#ee0000" link="#0000ee"
+ vlink="#551a8b">
+<h2>Sample 1: Simple GUI Events Handling</h2>
+<big><small>
+This sample introduces Channel by showing how to implement event
+handling thru Channel.<br>
+<br>
+</small></big>
+<p><big><small>We first include the channel header file</small></big></p>
+<big><small></small></big>
+<pre style="background-color: rgb(204, 204, 204);"><big><small><span
+ style="font-weight: bold; font-style: italic;">#include &lt;boost/channel/channel.hpp&gt;</span></small></big></pre>
+<big><small><span style="font-weight: bold; font-style: italic;"><span
+ style="color: rgb(102, 0, 0);">
+</span></span></small></big>
+<p><big><small>As a first step, instantiate a concrete channel type
+according to
+application's requirement. We could consider what data type to use as
+ids, and what kind of namespace and dispatcher will be best fit the
+application. Here we use strings as ids and use default
+linear_namespace and broadcast dispatcher:</small></big></p>
+<big><small></small></big>
+<pre style="background-color: rgb(204, 204, 204);"><big><em><span
+ style="color: rgb(153, 0, 0); font-weight: bold;"><small>typedef channel&lt;string&gt; evt_chan;</small></span></em></big></pre>
+<big><em><span style="color: rgb(153, 0, 0); font-weight: bold;"></span></em></big><big><span
+ style="color: rgb(0, 0, 0);">Next</span></big> we
+define a few event ids to simulate some possible events inside a GUI
+window:<br>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="font-style: italic; font-weight: bold; color: rgb(153, 0, 0);">string down_id = "_window_button_down_";<br>string up_id = "_window_button_up_";<br>string close_id = "_window_close_";</span></pre>
+<br>
+In this sample, we use the following message/event data structure to
+pass some data:<br>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">struct evt_data {<br> string data_;&nbsp;<br> evt_data(const char *d) : data_(d) {}<br>};</span></pre>
+<br>
+<p>Then we define&nbsp; the event source of this sample: a simplest GUI
+window
+without any features except those for sending events: bound channel and
+named_outs (also typedefed inside channel: evt_chan::out). Inside
+gui_window constructor, we bind named_outs to the above mentioned event
+ids in channel to send events:</p>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;">class gui_window {<br> evt_chan &amp; chan_;<br> &nbsp;//a few event src<br></span></pre>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="font-style: italic; color: rgb(153, 0, 0); font-weight: bold;"> evt_chan::out down_out_;<br>&nbsp; evt_chan::out close_out_;<br>public:<br> gui_window(evt_chan &amp; c): chan_(c),<br> down_out_(chan_, down_id),<br> up_out_(chan_, up_id),<br> close_out_(chan_, close_id) {}<br> ...and define some utility methods to send out events thru named_outs ...<br>};</span></pre>
+<br>
+After defining event source, we define a handler class to demo using
+object methods as event callbacks. In constructor, we create named_in
+(also nested typedefed inside channel: evt_chan::in) objects to bind
+callbacks to event ids in channel namespace. Named_out and named_in
+objects can be created in stack as we have done in class gui_window.
+Here we create them by invoking channel's factory method to create them
+from heap.<br>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">class window_handler {<br>&nbsp; evt_chan &amp; ch_;<br>&nbsp; //a few event sinks<br>&nbsp; evt_chan::in *down_in_;<br>&nbsp; evt_chan::in *up_in_;<br>&nbsp; evt_chan::in *close_in_;&nbsp; <br>public:<br>&nbsp; window_handler(evt_chan &amp; c): ch_(c) {<br>&nbsp;&nbsp;&nbsp; down_in_ = ch_.bind_name_in(down_id, boost::bind(&amp;window_handler::down, this, _1, _2));<br>&nbsp;&nbsp;&nbsp; up_in_ = ch_.bind_name_in(up_id, boost::bind(&amp;window_handler::up, this, _1, _2));<br>&nbsp;&nbsp;&nbsp; close_in_ = ch_.bind_name_in(close_id, boost::bind(&amp;window_handler::close, this, _1, _2));<br>&nbsp; }<br>.... here define methods as event callbacks ...<br>};</span></pre>
+<br>
+We define another global function to be used&nbsp; as event handler.<br>
+<span style="color: rgb(153, 0, 0);">void evt_handler(string id,
+boost::shared_ptr&lt;void&gt; p)</span><br
+ style="color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);">{</span><br
+ style="color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);">&nbsp; cout &lt;&lt; "free handler
+... recv event [id=" &lt;&lt; id &lt;&lt; "], [data=" &lt;&lt;
+((evt_data*)p.get())-&gt;data_ &lt;&lt; "]" &lt;&lt; endl;</span><br
+ style="color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);">}</span><br>
+<br>
+Now here is a simple main function:<br>
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">int main(int, char **) {</span></pre>
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);"></span>The
+first thing is to create the event channel<br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">evt_chan chan;</span></pre>
+create the event source (gui_window) and bind it to channel<br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);"></span><span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">gui_window window(chan);</span></pre>
+create a handler object and bind it to channel<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);"></span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">&nbsp;window_handler hdlr(chan);</span></pre>
+Next we create more event sinks to bind the global function to event
+ids.<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);"></span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">evt_chan::in window_down_in(chan, down_id, evt_handler)<br>evt_chan::in window_up_in(chan, up_id, evt_handler);&nbsp;<br>evt_chan::in shut_down_in(chan, close_id, evt_handler);</span></pre>
+Last, we fire some events<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);"></span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">window.up("..Hi there [mouse-left-up] ..");<br>window.down(".. a simple window test [mouse-right-down] ..");<br>window.close(".. simple window wiered [window-closed] ..");</span></pre>
+Then exit<br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<pre style="background-color: rgb(204, 204, 204);"><span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">cout &lt;&lt; "... exit ...\n";&nbsp;<br>return 0;</span></pre>
+<p><br>
+In this simple sample, we bind event handlers/callbacks to event
+sources indirectly by binding to names in channel namespace. After
+namespace binding, event dispatching happens directly between named_out
+(senders) and named_in (receivers).</p>
+<br>
+Finally, here is <a href="gui_evt_chan1.cpp">the
+complete
+source code.</a><br>
+<br>
+<br>
+<em><span style="color: rgb(153, 0, 0); font-weight: bold;"></span></em>
+</body>
+</html>

Added: sandbox/channel/libs/channel/example/gui_evt/sample2_text.html
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/gui_evt/sample2_text.html 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,112 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+</head>
+<body>
+<h2>Sample 2: Simple GUI Events Handling By Connecting Two Local
+Channels</h2>
+<br>
+This sample is based on sample 1 with changes to demonstrate connecting
+two local channels.<br>
+<br>
+Also we use the following POD struct (defined in linear_id_trait.hpp)
+as message id/names:<br>
+&nbsp;&nbsp;&nbsp; struct struct_id {<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; message_family family;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int type;<br>
+&nbsp;&nbsp;&nbsp; &nbsp; ......<br>
+&nbsp;&nbsp;&nbsp; };<br>
+<br>
+The changes are inside main() function:<br>
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">int
+main(int, char **) {</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);"></span>First
+we create 2 channels<br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+evt_chan chan1;</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+evt_chan chan2;</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+Then we connect these 2 channels<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);"></span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+connect(chan1, chan2);</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+Bind event source to channel 1<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);"></span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+gui_window window(chan1);</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);"></span><span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);"></span>create
+handler object and bind it to channel 1<br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+window_handler hdlr(chan1); </span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+create more event sinks and bind the global function to channel 2.<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);"></span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+evt_chan::in window_down_in(chan2, win_but_down_id, evt_handler);</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+evt_chan::in window_up_in(chan2, win_but_up_id, evt_handler);</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+evt_chan::in shut_down_in(chan2, win_close_id, evt_handler);</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+Now we fire some event for testing.<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);"></span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+window.up("..Hi there [mouse-left-up] ..");</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+window.down(".. a simple window test [mouse-right-down] ..");</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+window.close(".. simple window wiered [window-closed] ..");</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+Last exit<br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+cout &lt;&lt; "... exit ...\n";</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+return 0;</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<span
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">}</span><br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<br>
+From testing, we should see events propagate to both channel 1 and
+channel 2 and events get printed out by callbacks at both channels.<br>
+<a href="gui_evt_chan2.cpp">Complete source
+listing...</a><br>
+<br
+ style="font-weight: bold; font-style: italic; color: rgb(153, 0, 0);">
+<br>
+</body>
+</html>

Added: sandbox/channel/libs/channel/example/ping_pong/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/ping_pong/Jamfile.v2 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,43 @@
+#
+# Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#
+#//
+#// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+#//
+#// Distributed under the Boost Software License, Version 1.0. (See accompanying
+#// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#//
+
+import os ;
+
+if [ os.name ] = SOLARIS
+{
+ lib socket ;
+ lib nsl ;
+}
+else if [ os.name ] = NT
+{
+ lib ws2_32 ;
+ lib mswsock ;
+}
+
+project
+ : requirements
+ <library>/boost/serialization//boost_serialization
+ <library>/boost/thread//boost_thread
+ <library>/boost/system//boost_system
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <os>SOLARIS:<library>socket
+ <os>SOLARIS:<library>nsl
+ <os>NT,<toolset>gcc:<library>ws2_32
+ <os>NT,<toolset>gcc:<library>mswsock
+ ;
+
+obj ping.obj : ping.cpp ;
+exe ping : ping.obj ;
+obj pong.obj : pong.cpp ;
+exe pong : pong.obj ;

Added: sandbox/channel/libs/channel/example/ping_pong/ping.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/ping_pong/ping.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,78 @@
+//
+// ping.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/channel/streams/asio_stream_async.hpp>
+#include "./pingpong_defs.hpp"
+
+//msg handler; print out data
+void msg_handler(msg_chan::out & ping_o, int id, boost::shared_ptr<void> p)
+{
+ pingpong_msg *msg = (pingpong_msg *) p.get();
+ cout << "Ping recv count = " << msg->count_ << endl;
+ ping_o.send(new pingpong_msg(msg->count_+1));
+}
+
+void binding_callback(msg_chan::out ** ping_o, msg_chan::name *n, msg_chan::name::binding_event e) {
+ if (n->type_ == msg_chan::name::member_remote && e == msg_chan::name::bind_ev) {
+ (*ping_o)->send(new pingpong_msg(0));
+ }
+}
+
+int main(int, char **) {
+ try {
+ //create asio io_service
+ boost::asio::io_service io_service;
+ //create local channel and bind local event source/sink
+ msg_chan chan;
+
+ //publish ping msg
+ msg_chan::out *po = NULL;
+ msg_chan::out ping_o(chan,
+ msg_id_ping,
+ boost::bind(binding_callback, &po, _1,_2));
+ po = &ping_o;
+
+ //subscribe pong msg
+ msg_chan::in pong_i(chan, msg_id_pong, boost::bind(msg_handler,
+ boost::ref(ping_o), _1,_2));
+
+ //register msg type for marshaling/demarshaling
+ msg_chan::text_marshaler_registry mar_reg;
+ mar_reg.register_default_msg_marshaler<pingpong_msg>();
+
+ //create asio connectors and connect to remote channel
+ asio_connector_async connector(io_service);
+ /*
+ connector.async_accept(8888, // channel address
+ boost::bind(asio_bind_sock_chan<msg_chan, chat_chan::text_marshaler_registry>(),
+ boost::ref(chan), boost::ref(mar_reg), _1, _2, _3));
+ */
+ connector.async_connect("localhost", "9999", //remote channel address
+ boost::bind(asio_bind_sock_chan<msg_chan, msg_chan::text_marshaler_registry>(),
+ boost::ref(chan), boost::ref(mar_reg), _1, _2, _3));
+
+ io_service.run();
+ }
+ catch (boost::system::error_code& e)
+ {
+ std::cerr << e << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ cout << "... ping exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/ping_pong/pingpong_defs.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/ping_pong/pingpong_defs.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,43 @@
+//
+// pingpong_defs.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef PINGPONG_DEFS_HPP
+#define PINGPONG_DEFS_HPP
+
+#include <boost/channel/channel.hpp>
+
+using namespace std;
+using namespace boost::channel;
+
+//instantiate event channel type
+typedef channel<int> msg_chan;
+
+//define sys ids
+DEFINE_INT_SYS_IDS
+
+//sample msg ids
+int msg_id_base = msg_chan::app_msg_begin;
+int msg_id_ping = msg_id_base+1;
+int msg_id_pong = msg_id_ping+1;
+
+//a simple struct for ping-pong msg
+struct pingpong_msg {
+ int count_;
+ char dd[1024*1024]; //for checking mem-leak during msg passing
+ pingpong_msg(int cnt) : count_(cnt) {}
+ pingpong_msg() {} //have to define this for marshaling to work
+ //serialization function for pingpong_msg
+ template <typename Archive>
+ void serialize(Archive & ar, const unsigned int version)
+ {
+ ar & count_;
+ }
+};
+
+#endif

Added: sandbox/channel/libs/channel/example/ping_pong/pong.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/ping_pong/pong.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,77 @@
+//
+// pong.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/channel/streams/asio_stream_async.hpp>
+#include "./pingpong_defs.hpp"
+
+//msg handler; print out data
+void msg_handler(msg_chan::out & pong_o, int id, boost::shared_ptr<void> p)
+{
+ pingpong_msg *msg = (pingpong_msg *) p.get();
+ cout << "Pong recv count = " << msg->count_ << endl;
+ pong_o.send(new pingpong_msg(msg->count_+1));
+}
+
+void binding_callback(msg_chan::out ** pong_o, msg_chan::name *n, msg_chan::name::binding_event e) {
+ if (n->type_ == msg_chan::name::member_remote && e == msg_chan::name::bind_ev) {
+ (*pong_o)->send(new pingpong_msg(0));
+ }
+}
+
+int main(int, char **) {
+ try {
+ //create asio io_service
+ boost::asio::io_service io_service;
+ //create local channel and bind local event source/sink
+ msg_chan chan;
+
+ //publish pong msg
+ msg_chan::out *po = NULL;
+ msg_chan::out pong_o(chan,
+ msg_id_pong,
+ boost::bind(binding_callback, &po, _1,_2));
+ po = &pong_o;
+
+ //subscribe ping msg
+ msg_chan::in ping_i(chan, msg_id_ping, boost::bind(msg_handler,
+ boost::ref(pong_o), _1,_2));
+
+ //register msg type for marshaling/demarshaling
+ msg_chan::text_marshaler_registry mar_reg;
+ mar_reg.register_default_msg_marshaler<pingpong_msg>();
+
+ //create asio connectors and connect to remote channel
+ asio_connector_async connector(io_service);
+ connector.async_accept(9999, // channel address
+ boost::bind(asio_bind_sock_chan<msg_chan, msg_chan::text_marshaler_registry>(),
+ boost::ref(chan), boost::ref(mar_reg), _1, _2, _3));
+ /*
+ connector.async_connect("localhost", "8888", //remote channel address
+ boost::bind(asio_bind_sock_chan<msg_chan, msg_chan::text_marshaler_registry>(),
+ boost::ref(chan), boost::ref(mar_reg), _1, _2, _3));
+ */
+ io_service.run();
+ }
+ catch (boost::system::error_code& e)
+ {
+ std::cerr << e << "\n";
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ cout << "... pong exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/example/prime_sieve/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/prime_sieve/Jamfile.v2 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,16 @@
+#//
+#// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+#//
+#// Distributed under the Boost Software License, Version 1.0. (See accompanying
+#// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#//
+
+project
+ : requirements
+ <library>/boost/thread//boost_thread
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ ;
+
+obj prime_sieve.obj : prime_sieve.cpp ;
+exe prime_sieve : prime_sieve.obj ;

Added: sandbox/channel/libs/channel/example/prime_sieve/prime_sieve.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/prime_sieve/prime_sieve.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,113 @@
+//
+// prime_sieve.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+///* Copyright (c) 2005 Russ Cox, MIT; see COPYRIGHT */
+
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/channel/channel.hpp>
+#include <boost/channel/executors/thread_pool_executor.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/xtime.hpp>
+
+using namespace std;
+using namespace boost::channel;
+
+//define executor
+typedef thread_pool_executor<mt_synch<boost_platform> > exec_type;
+
+//define port type
+typedef port<exec_type> port_type;
+typedef port_type::choice_async choice_type;
+
+static int task_no = 0;
+
+//define task type: comprise of 3 parts:
+//1> a port to recv msgs
+//2> a run() method to process msgs
+//3> a executor to execute run()
+class prime_task {
+private:
+ //app data
+ int my_prime_;
+ int my_no_;
+ prime_task *next_;
+
+public:
+ //task main data
+ port_type port_;
+ choice_type choice_;
+ exec_type *exe_;
+
+ prime_task(exec_type *e) :
+ my_prime_(-1), next_(NULL),
+ port_(e), choice_(e), exe_(e)
+ {
+ my_no_ = task_no++;
+ choice_.bind(port_, boost::bind(&prime_task::run, this, _1));
+ }
+ ~prime_task() {
+ if (next_ != NULL) delete next_;
+ //cout << "prime_task [" << my_no_ << "] destroy " << endl;
+ }
+ void run(boost::shared_ptr<void> p)
+ {
+ int val = *(int *)p.get();
+ if (my_prime_ == -1) { //first time
+ my_prime_ = val;
+ cout << "------ prime_task [" << my_no_ << "] found prime = " << val << endl;
+ next_ = new prime_task(exe_); //create the next task
+ }
+ else {
+ if (val % my_prime_) { //not my multiples
+ next_->port_.send(p);
+ } else { //my multiples
+ cout << "prime_task [" << my_no_ << "] drop " << val << endl;
+ }
+ }
+ }
+};
+
+void thread_sleep(int sec) {
+ boost::xtime xt;
+ boost::xtime_get(&xt, boost::TIME_UTC);
+ xt.sec += sec;
+ boost::thread::sleep(xt);
+}
+
+int main(int argc, char **argv) {
+ //create executor with two threads
+ exec_type exec(2);
+
+ int max_num;
+ if (argc > 1)
+ max_num = atoi(argv[1]);
+ else
+ max_num = 1000;
+
+ cout << "find primes in range [2-" << max_num << "]" << endl;
+
+ //create prime_task0
+ prime_task first_task(&exec);
+
+ for(int i=2; i<=max_num; i++) {
+ int *data = new int;
+ *data = i;
+ first_task.port_.send(data);
+ //sleep 1 sec, to avoid jam executor queue & better show diff tasks running
+ thread_sleep(1);
+ }
+
+ exec.wait(); //wait async tasks finish
+ exec.shut_down_wait(); //wait threads exit
+
+ return 0;
+
+ //when main() exit, first_task goes out of scope, it will delete itself and all chained tasks
+}

Added: sandbox/channel/libs/channel/example/prime_sieve/sample12_text.html
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/prime_sieve/sample12_text.html 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,205 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+</head>
+<body style="color: rgb(0, 0, 0);" alink="#ee0000" link="#0000ee"
+ vlink="#551a8b">
+<h2>Sample 12.&nbsp; port and signal: unnamed point
+of tightly-coupled local interactions&nbsp;<br>
+</h2>
+Channel's name space and binding thru name-matching provide a loosely
+coupled model for asynchronous distributed message passing. However
+setting up name space and designing name assignment scheme could be too
+much trouble for applications based on tightly coupled message passing
+inside a single address space. This tutorial explains 3 samples showing
+how Channel's port and signal classes can help build these kind of
+applications.<br>
+<br>
+The 1st sample is using a pipeline of asynchronous tasks to generate
+all primes
+less than a thousand. For the original design and considerations,
+please refer to Russ Cox's essay <a
+ href="http://swtch.com/%7Ersc/thread/">"Bell Labs and CSP Threads"</a>.&nbsp;
+The original code is
+based on tasks(coroutines) and synchronous
+communication channels. In this sample, the code is changed to&nbsp; be
+based on port and asynchronous tasks executed by thread pool executor.
+Here is the complete source code<span
+ style="text-decoration: underline;"> </span>prime_sieve.cpp.&nbsp;
+Let's walk thru the code.<br>
+<br>
+First we define the type of thread pool executor to run the
+asynchronous tasks. Also we instantiate port template class to define
+port type and its related choice arbiter type. <br>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">typedef
+port&lt;exec_type&gt; port_type;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">typedef
+port_type::choice_async choice_type;</span><br>
+</div>
+A port can be used as a message queue and allow applications put data
+into it and get data from it. However mostly ports are used with
+choice/join arbiters.<br>
+<br>
+Next we define a class for the asynchronous tasks which will do the
+real job of finding primes. A task consists of 3 main parts: &lt;1&gt;
+a port to receive messages; &lt;2&gt; a run() method to define task's
+functionality; &lt;3&gt; a executor to execute run() method. Please
+notice that in constructor the choice arbiter bind the port to run()
+method, so that each incoming message will create an asynchronous task
+which will execute run()'s code in a thread from thread pool.<br>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; void
+run(boost::shared_ptr&lt;void&gt; p)</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+int val = *(int *)p.get();</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+if (my_prime_ == -1) { //first time</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+my_prime_ = val;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+cout &lt;&lt; "------ prime_task [" &lt;&lt; my_no_ &lt;&lt; "] found
+prime = " &lt;&lt; val &lt;&lt; endl;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+next_ = new prime_task(exe_); //create the next task</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+} </span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+else {</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+if (val % my_prime_) { //not my multiples</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+next_-&gt;port_.send(p);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+} else { //my multiples</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+cout &lt;&lt; "prime_task [" &lt;&lt; my_no_ &lt;&lt; "] drop "
+&lt;&lt; val &lt;&lt; endl;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+}</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+}</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; }</span><br>
+</div>
+The method run() takes a single argument of pointer to message data
+which it received from port. If it is the 1st time this task receives a
+message, the received integer will be a prime and it is saved, and the
+next asynchronous task will be created. If it is not the 1st message,
+it will be compared with the prime saved by this task and dropped if it
+is a multiple of the saved prime; otherwise the message is sent to the
+port of the next task.<br>
+<br>
+The main() function is simple. First we create the thread pool executor
+and create the 1st task. Then we start feeding integers (2-1000) to the
+port of the 1st task. Before exit, we'll wait for the graceful exit of
+all thread pool threads.<br>
+<br>
+The 2nd example demos the signal class and its associated slot type. It
+is a modification of tutorial 1. Instead of using channel, named_out
+and named_in, this sample uses signal and slot to set up event
+dispatching system without the hassle of choosing id and assigning
+names. Here is the complete source gui_evt3.cpp
+.<br>
+<br>
+The 3rd sample demos how "unnamed" port can be used together with names
+/ ids in the same choice arbiter. Here is the complete source
+code&nbsp; chat_join_timer.cpp.&nbsp;
+This sample is based on sample 6 with the addition of a timer sending
+events to a port. Let's walk thru code.<br>
+<br>
+First port type is defined based on channel type.<br>
+&nbsp;&nbsp;&nbsp; <span
+ style="color: rgb(153, 0, 0); font-style: italic;">typedef
+chat_chan::port port_t;</span><br>
+<br>
+Next my_timer class is defined, which uses asio's deadline_timer and
+set timeout period to 5 seconds. When timeout happens, a null_event
+message is sent to a port.<br>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">class my_timer</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">{</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">public:</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+my_timer(boost::asio::io_service&amp; io, port_t &amp;p)</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+: timer_(io, boost::posix_time::seconds(5)),</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+port_(p)</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+timer_.async_wait(boost::bind(&amp;my_timer::timeout, this));</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; }</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; void
+timeout()</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+port_.send(new null_event); //send timeout notifications</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(5));</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+timer_.async_wait(boost::bind(&amp;my_timer::timeout, this));</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; }</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">private:</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+boost::asio::deadline_timer timer_;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp; port_t
+&amp;port_;</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">};</span><br>
+</div>
+<br>
+In main(), most code is similar to sample 6, except the following code
+for timer and port.<br>
+First, timer and port are created and a new thread is spawn to run asio.<br>
+<div
+ style="margin-left: 40px; font-style: italic; color: rgb(153, 0, 0);">&nbsp;
+boost::asio::io_service io;<br>
+&nbsp; port_t timeout_port;<br>
+&nbsp; my_timer(io,timeout_port);<br>
+&nbsp; //spawn a thread to run timer<br>
+&nbsp; boost::thread t(boost::bind(&amp;boost::asio::io_service::run,
+&amp;io));&nbsp; <br>
+</div>
+<br>
+Next, add the timeout_port to the choice arbiter and bind it with a
+timeout handler which simply prints a message.<br>
+<div style="margin-left: 40px;"><span style="color: rgb(153, 0, 0);">&nbsp;<span
+ style="font-style: italic;">choice.bind(timeout_port, timeout_hdlr);</span><br>
+</span></div>
+Notice the same choice arbiter handles both "names/ids" and the
+timeout_port objects.<br>
+<br>
+During testing, we should see the timeout message every 5 seconds.<br>
+<br>
+<br>
+</body>
+</html>

Added: sandbox/channel/libs/channel/example/sample_dispatcher/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/sample_dispatcher/Jamfile.v2 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,15 @@
+#//
+#// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+#//
+#// Distributed under the Boost Software License, Version 1.0. (See accompanying
+#// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#//
+project
+ : requirements
+ <library>/boost/thread//boost_thread
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ ;
+
+obj sync_send_recv.obj : sync_send_recv.cpp ;
+exe sync_send_recv : sync_send_recv.obj ;

Added: sandbox/channel/libs/channel/example/sample_dispatcher/dispatcher_text.html
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/sample_dispatcher/dispatcher_text.html 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,528 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+ <meta content="text/html; charset=ISO-8859-1"
+ http-equiv="content-type">
+ <title>dispatcher_text.html</title>
+</head>
+<body style="color: rgb(0, 0, 0);" alink="#ee0000" link="#0000ee"
+ vlink="#551a8b">
+<h2>Implementation of Sample Pull Dispatcher<br>
+</h2>
+The following is the description of implementation of a simple pull
+dispatcher.&nbsp; Its full source is <a
+ href="pull_dispatcher_sample.hpp">here...</a><br>
+<br>
+Each dispatcher has 2 parts: sending algorithm and receiving algorithm.
+They are defined as 2 separate nested template classes. With this
+dispatcher, sending thread buffers messages in queues at sending side,
+notifies the receivers and returns right away, receiving threads are
+blocked waiting at receiving side and unblocked when messages are
+available.<br>
+<br>
+Let's look at the sending class at first. Because it is a pull
+dispatcher, the messages will be buffered inside channel at sending
+side. A queue will be part of sending class. Queue type is one of
+template parameter of sender class to allow customization. We set the
+sender class inherit from queue class so that queue's methods are
+exposed to allow clients code to provision the queue's settings such as
+size or blocking timeout.<br>
+<br>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+template &lt;typename name_space, typename platform, template
+&lt;class,class,class&gt; class msg_queue_type&gt;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+struct pull_sender_sample : </span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; public
+msg_queue_type&lt;boost::shared_ptr&lt;message&lt;typename
+name_space::id_type&gt; &gt;,</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; typename
+name_space::synch_policy,</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; platform&gt; {<br>
+<br>
+</span></span></div>
+Next, we define a few data types associated with sending class:<br>
+<div style="margin-left: 40px;"><span style="color: rgb(153, 0, 0);"><span
+ style="color: rgb(0, 0, 0);"></span></span></div>
+<div style="text-align: left;">
+<div style="margin-left: 40px;"><span style="color: rgb(153, 0, 0);"><span
+ style="font-style: italic;">&nbsp;&nbsp;&nbsp; typedef typename
+name_space::id_type id_type;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+typedef typename name_space::synch_policy synch_policy;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+typedef typename name_space::executor executor;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+typedef name&lt;id_type,executor,synch_policy&gt; name_type;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+typedef message&lt;id_type&gt; msg_type;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+typedef typename name_type::binding_set_type binding_set_type;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+typedef msg_queue_type&lt;boost::shared_ptr&lt;msg_type&gt;,
+synch_policy,</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; platform&gt; que_type;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+typedef pull_recver_sample&lt;name_space, platform,msg_queue_type&gt;
+recver_type;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+typedef named_in&lt;name_space, recver_type&gt; named_in_type;</span></span><br>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"></span></span></div>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"><br>
+Then constructor is defined.<br>
+</span></span>
+<div style="margin-left: 40px;"><span style="color: rgb(153, 0, 0);"><span
+ style="font-style: italic;">&nbsp;&nbsp;&nbsp; name_type * name_;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+pull_sender_sample(name_type *n, executor *) : que_type(), name_(n) { }</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+~pull_sender_sample() {}</span></span><br>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"></span></span></div>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"><br>
+Next, the most important method in sending class is defined. Since this
+is a pull dispatcher, the message is not pushed directly to receivers.
+Instead, the message is stored in queue first, then bound receivers are
+notified that a message is available and receiving threads are
+unblocked. Notice the binding_set (set of bound receivers) are
+retrieved from associated name object.<br>
+</span></span>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+void notify(boost::shared_ptr&lt;msg_type&gt; msg) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; //first store msg in que</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; put(msg);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; //notify recevers</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; typename synch_policy::scoped_lock
+lock(this-&gt;name_-&gt;bind_lock_);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; binding_set_type &amp;bindings = this-&gt;name_-&gt;bindings_;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; if (!bindings.empty()) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; bool cont = true;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; for(typename binding_set_type::iterator iter =
+bindings.begin();</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; iter != bindings.end() &amp;&amp; cont; iter++) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; named_in_type *named_in = (named_in_type
+*)(*iter);</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; recver_type *recver = (recver_type
+*)named_in;</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //for pull dispatchers, only send msgs
+to local receviers</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (named_in-&gt;type_ ==
+named_in_type::member_local)</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; cont = recver-&gt;notify(msg-&gt;id_);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; }</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; }</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+}</span><br>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"></span></span></div>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"><br>
+After receiving notification, the 1st notified receiver will
+pull/retrieve message from sender's queue.<br>
+</span></span>
+<div style="margin-left: 40px;"><span style="color: rgb(153, 0, 0);"><span
+ style="font-style: italic;">&nbsp;&nbsp;&nbsp; int
+pull(boost::shared_ptr&lt;msg_type&gt; &amp; msg) {</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp; if (!this-&gt;empty()) {</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; get(msg);</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; return 1;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp; }</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp; return 0;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+}</span></span><br>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"></span></span></div>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"><br>
+The following methods are various "send()" which are the API of this
+class. One basic rule is that message data are passed in as pointers,
+and this data will be owned by channel and released by channel after
+nobody refers to it anymore. To change this default behaviour (such as
+passing data on stack as message), invoker of "send()" can pass in
+proper deleter together with data pointer or pass in proper share_ptr
+initialized with proprt deleter.<br>
+</span></span>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+//after sending, channel becomes owner</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+template &lt;typename user_msg_type&gt;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+void send(user_msg_type *msg) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; boost::shared_ptr&lt;void&gt; m0(msg);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; boost::shared_ptr&lt;msg_type&gt; m(new msg_type(name_-&gt;id_,
+m0));</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; notify (m);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+}</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);"></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+//after sending: 1&gt; channel becomes owner, if deleter does real
+deletion</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+// 2&gt; sender still owns msg, if deleter does nothing</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+template &lt;typename user_msg_type, typename deleter&gt;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+void send(user_msg_type *msg, deleter deler) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; boost::shared_ptr&lt;void&gt; m0(msg, deler);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; boost::shared_ptr&lt;msg_type&gt; m(new msg_type(name_-&gt;id_,
+m0));</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; notify (m);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+}</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);"></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+//user_msg is already smarter pointer, channel becomes owner</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+template &lt;typename user_msg_type&gt;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+void send(boost::shared_ptr&lt;user_msg_type&gt; msg) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; boost::shared_ptr&lt;void&gt; m0(msg);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; boost::shared_ptr&lt;msg_type&gt; m(new msg_type(name_-&gt;id_,
+m0));</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; notify (m);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+}</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);"></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+//for channel internal use on wildcard named_out</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+template &lt;typename user_msg_type&gt;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+void send(id_type id, boost::shared_ptr&lt;user_msg_type&gt; msg) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; boost::shared_ptr&lt;void&gt; m0(msg);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; boost::shared_ptr&lt;msg_type&gt; m(new msg_type(id, m0));</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; notify (m);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+}</span><br>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"></span></span></div>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"><br>
+The following is about the implementation of receiving class.<br>
+<br>
+It has the same template parameters as sending class.<br>
+</span></span>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+template &lt;typename name_space, typename platform, template
+&lt;class,class,class&gt; class msg_que_type&gt;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+struct pull_recver_sample {<br>
+</span><span style="color: rgb(153, 0, 0);"><span
+ style="color: rgb(0, 0, 0);"></span></span></div>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);">Similarly,
+associated types are defined.<br>
+</span></span>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+typedef typename name_space::id_type id_type;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+typedef typename name_space::synch_policy synch_policy;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+typedef typename name_space::executor executor;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+typedef name&lt;id_type,executor,synch_policy&gt; name_type;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+typedef message&lt;id_type&gt; msg_type;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+typedef pull_sender_sample&lt;name_space, platform, msg_que_type&gt;
+sender_type;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+typedef named_out&lt;name_space, sender_type&gt; named_out_type;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+typedef typename name_type::binding_set_type binding_set_type;</span><br>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"></span></span></div>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"><br>
+Some synchronization variables and constructor.<br>
+</span></span>
+<div style="margin-left: 40px;"><span style="color: rgb(153, 0, 0);"><span
+ style="font-style: italic;">&nbsp;&nbsp;&nbsp; name_type * name_;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+typename synch_policy::mutex mutex_;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+typename synch_policy::condition cond_;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+int num_waiting_;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+pull_recver_sample(name_type *n) : </span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+&nbsp; name_(n), num_waiting_(0) {}</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+~pull_recver_sample() {}</span></span><br style="font-style: italic;">
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"></span></span></div>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"><br>
+Here comes the "main" function of receiving threads. Recving thread
+will block here and wait for notifications from senders. And then
+messages will be pulled/retrieved from sending queue and processed.<br>
+</span></span>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+void recv(id_type &amp; id, boost::shared_ptr&lt;void&gt; &amp; msg) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; int st;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; boost::shared_ptr&lt;msg_type&gt; mesg;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; typename synch_policy::scoped_lock lock(mutex_);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; while(1) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; st = pull(mesg);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; if (st != 0) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id = mesg-&gt;id_;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; msg = mesg-&gt;data_;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; }</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; num_waiting_++;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; cond_.wait(lock);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; num_waiting_--;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; }&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+}</span><br>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"></span></span></div>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"><br>
+Sending thread will call this method to wake up blocked receiving
+threads.<br>
+</span></span>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+bool notify(id_type id) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; typename synch_policy::scoped_lock lock(mutex_);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; if (num_waiting_ &gt; 0) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; cond_.notify_one();</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; return false;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; } </span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; else</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; return true;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+}</span><br>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"></span></span></div>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"><br>
+Since a receiver can be bound to multiple senders, the following pull
+method try to retrieve data from any bound senders.<br>
+</span></span>
+<div style="margin-left: 40px;"><span
+ style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+int pull(boost::shared_ptr&lt;msg_type&gt; &amp; msg) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; int st = 0;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; //go-thru binding_set to pull from senders</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; typename synch_policy::scoped_lock lock(name_-&gt;bind_lock_);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; binding_set_type &amp;bindings = name_-&gt;bindings_;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; if (!bindings.empty()) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; for(typename binding_set_type::iterator iter =
+bindings.begin();</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; iter != bindings.end() &amp;&amp; st == 0; iter++) {</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; named_out_type *named_out =
+(named_out_type *)(*iter);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sender_type *sender = (sender_type
+*)(named_out);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; st = sender-&gt;pull(msg);</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;&nbsp; }</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; }</span><br style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+&nbsp; return st;</span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="font-style: italic; color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;
+}</span><br>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"></span></span></div>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"><br>
+Finally, a dispatcher template class wraps these sending class and
+receiving class together.<br>
+</span></span>
+<div style="margin-left: 40px;"><span style="color: rgb(153, 0, 0);"><span
+ style="font-style: italic;">&nbsp;&nbsp;&nbsp; template &lt;typename
+name_space, typename platform, template &lt;class,class,class&gt; class
+queue_type = unbounded_que&gt;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+struct pull_dispatcher_sample {</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+typedef
+detail::pull_sender_sample&lt;name_space,platform,queue_type&gt; sender;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+typedef
+detail::pull_recver_sample&lt;name_space,platform,queue_type&gt; recver;</span></span><br
+ style="font-style: italic; color: rgb(153, 0, 0);">
+<span style="color: rgb(153, 0, 0);"><span style="font-style: italic;">&nbsp;&nbsp;&nbsp;
+};</span></span><br>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"></span></span></div>
+<span style="color: rgb(153, 0, 0);"><span style="color: rgb(0, 0, 0);"><br>
+Here is <a href="sync_send_recv.cpp">a
+simple program demos usage of this dispatcher</a>.<br>
+<br>
+</span></span><span style="color: rgb(153, 0, 0); font-style: italic;"></span></div>
+</body>
+</html>

Added: sandbox/channel/libs/channel/example/sample_dispatcher/pull_dispatcher_sample.hpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/sample_dispatcher/pull_dispatcher_sample.hpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,193 @@
+//
+// pull_dispatcher_sample.hpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef PULL_DISPATCHER_SAMPLE_HPP
+#define PULL_DISPATCHER_SAMPLE_HPP
+
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+#include <boost/channel/channel.hpp>
+
+namespace boost {
+ namespace channel {
+
+ namespace detail {
+
+ template<class,class,template<class,class,class>class> class pull_recver_sample;
+
+ template <typename name_space, typename platform, template <class,class,class> class msg_queue_type>
+ struct pull_sender_sample :
+ public msg_queue_type<boost::shared_ptr<message<typename name_space::id_type> >,
+ typename name_space::synch_policy,
+ platform> {
+ typedef typename name_space::id_type id_type;
+ typedef typename name_space::synch_policy synch_policy;
+ typedef typename name_space::executor executor;
+ typedef name<id_type,executor,synch_policy> name_type;
+ typedef message<id_type> msg_type;
+ typedef typename name_type::binding_set_type binding_set_type;
+ typedef msg_queue_type<boost::shared_ptr<msg_type>, synch_policy,
+ platform> que_type;
+ typedef pull_recver_sample<name_space, platform,msg_queue_type> recver_type;
+ typedef named_in<name_space, recver_type> named_in_type;
+
+ name_type * name_;
+
+ pull_sender_sample(name_type *n, executor *) : que_type(), name_(n) { }
+ ~pull_sender_sample() {}
+
+ //assuming msgs contained inside shared_ptr
+ void notify(boost::shared_ptr<msg_type> msg) {
+ //first store msg in que
+ put(msg);
+ //notify recevers
+ typename synch_policy::scoped_lock lock(this->name_->bind_lock_);
+ binding_set_type &bindings = this->name_->bindings_;
+ if (!bindings.empty()) {
+ bool cont = true;
+ for(typename binding_set_type::iterator iter = bindings.begin();
+ iter != bindings.end() && cont; iter++) {
+ named_in_type *named_in = (named_in_type *)(*iter);
+ recver_type *recver = (recver_type *)named_in;
+ //for pull dispatchers, only send msgs to local receviers
+ if (named_in->type_ == named_in_type::member_local)
+ cont = recver->notify(msg->id_);
+ }
+ }
+ }
+
+ //recvers will call this to retrv/pull data
+ int pull(boost::shared_ptr<msg_type> & msg) {
+ if (!this->empty()) {
+ this->get(msg);
+ return 1;
+ }
+ return 0;
+ }
+
+ //--- api interface ---
+ //after sending, channel becomes owner
+ template <typename user_msg_type>
+ void send(user_msg_type *msg) {
+ boost::shared_ptr<void> m0(msg);
+ boost::shared_ptr<msg_type> m(new msg_type(name_->id_, m0));
+ notify (m);
+ }
+
+ //after sending: 1> channel becomes owner, if deleter does real deletion
+ // 2> sender still owns msg, if deleter does nothing
+ template <typename user_msg_type, typename deleter>
+ void send(user_msg_type *msg, deleter deler) {
+ boost::shared_ptr<void> m0(msg, deler);
+ boost::shared_ptr<msg_type> m(new msg_type(name_->id_, m0));
+ notify (m);
+ }
+
+ //user_msg is already smarter pointer, channel becomes owner
+ template <typename user_msg_type>
+ void send(boost::shared_ptr<user_msg_type> msg) {
+ boost::shared_ptr<void> m0(msg);
+ boost::shared_ptr<msg_type> m(new msg_type(name_->id_, m0));
+ notify (m);
+ }
+
+ //for channel internal use on wildcard named_out
+ template <typename user_msg_type>
+ void send(id_type id, boost::shared_ptr<user_msg_type> msg) {
+ boost::shared_ptr<void> m0(msg);
+ boost::shared_ptr<msg_type> m(new msg_type(id, m0));
+ notify (m);
+ }
+
+ };
+
+ //synchronous/blocking pull_recver
+ template <typename name_space, typename platform, template <class,class,class> class msg_que_type>
+ struct pull_recver_sample {
+ typedef typename name_space::id_type id_type;
+ typedef typename name_space::synch_policy synch_policy;
+ typedef typename name_space::executor executor;
+ typedef name<id_type,executor,synch_policy> name_type;
+ typedef message<id_type> msg_type;
+ typedef pull_sender_sample<name_space, platform, msg_que_type> sender_type;
+ typedef named_out<name_space, sender_type> named_out_type;
+ typedef typename name_type::binding_set_type binding_set_type;
+
+ name_type * name_;
+ typename synch_policy::mutex mutex_;
+ typename synch_policy::condition cond_;
+ int num_waiting_;
+
+ pull_recver_sample(name_type *n) :
+ name_(n), num_waiting_(0) {}
+
+ ~pull_recver_sample() {}
+
+ //recving thread will block here and wait for notify from senders
+ void recv(id_type & id, boost::shared_ptr<void> & msg) {
+ int st;
+ boost::shared_ptr<msg_type> mesg;
+ typename synch_policy::scoped_lock lock(mutex_);
+ while(1) {
+ st = pull(mesg);
+ if (st != 0) {
+ id = mesg->id_;
+ msg = mesg->data_;
+ return;
+ }
+ num_waiting_++;
+ cond_.wait(lock);
+ num_waiting_--;
+ }
+ }
+
+ //if any thread block waiting here
+ bool notify(id_type id) {
+ typename synch_policy::scoped_lock lock(mutex_);
+ if (num_waiting_ > 0) {
+ cond_.notify_one();
+ return false;
+ }
+ else
+ return true;
+ }
+
+ //pull data from sender
+ int pull(boost::shared_ptr<msg_type> & msg) {
+ int st = 0;
+ //go-thru binding_set to pull from senders
+ typename synch_policy::scoped_lock lock(name_->bind_lock_);
+ binding_set_type &bindings = name_->bindings_;
+ if (!bindings.empty()) {
+ for(typename binding_set_type::iterator iter = bindings.begin();
+ iter != bindings.end() && st == 0; iter++) {
+ named_out_type *named_out = (named_out_type *)(*iter);
+ sender_type *sender = (sender_type *)(named_out);
+ st = sender->pull(msg);
+ }
+ }
+ return st;
+ }
+ };
+
+ }
+
+ template <typename name_space, typename platform, template <class,class,class> class queue_type = unbounded_que>
+ struct pull_dispatcher_sample {
+ typedef detail::pull_sender_sample<name_space,platform,queue_type> sender;
+ typedef detail::pull_recver_sample<name_space,platform,queue_type> recver;
+ };
+
+ }
+}
+
+#endif

Added: sandbox/channel/libs/channel/example/sample_dispatcher/sync_send_recv.cpp
==============================================================================
--- (empty file)
+++ sandbox/channel/libs/channel/example/sample_dispatcher/sync_send_recv.cpp 2009-08-09 21:59:15 EDT (Sun, 09 Aug 2009)
@@ -0,0 +1,85 @@
+//
+// sync_send_recv.cpp
+//
+// Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+//
+// demo of sample buffered synchronous dispatcher: ie. recver is blocking waiting for data to arrive
+//
+
+#include <iostream>
+#include <string>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/channel/channel.hpp>
+#include "./pull_dispatcher_sample.hpp"
+
+using namespace std;
+using namespace boost::channel;
+
+//instantiate event channel type, using string as id_type
+typedef linear_name_space<string,
+ abstract_executor,
+ mt_synch<boost_platform> > ns_type;
+typedef channel<
+ string,
+ boost_platform,
+ mt_synch<boost_platform>,
+ abstract_executor,
+ ns_type,
+ pull_dispatcher_sample<ns_type, boost_platform>
+> evt_chan;
+
+//define sys ids
+DEFINE_STRING_SYS_IDS
+
+//event ids in name_space
+//sample events for sending text
+string evt_id = "_simple_event_to_send_text_";
+
+//a simple struct for event data
+struct evt_data {
+ string data_;
+ evt_data(const char *d) : data_(d) {}
+};
+
+//entry point function for recving thread; print out data
+void evt_recv(evt_chan::in & recver)
+{
+ string id;
+ boost::shared_ptr<void> p;
+ while (1) {
+ recver.recv(id, p);
+ cout << "recv event [id=" << id << "], [data=" << ((evt_data*)p.get())->data_ << "]\n";
+ }
+}
+
+int main(int, char **) {
+ //create event channel
+ evt_chan chan;
+
+ //bind event source to channel
+ evt_chan::out sender(chan, evt_id);
+
+ //bind event sink to channel
+ evt_chan::in recver(chan, evt_id);
+
+ //a separate thread to run recver
+ boost::thread t(boost::bind(evt_recv, boost::ref(recver)));
+
+ //main thread fire events
+ char msg[1024];
+ bool cont = true;
+ while (cont) {
+ cin.getline(msg, 1024);
+ sender.send(new evt_data(msg));
+ }
+
+ cout << "... exit ...\n";
+ return 0;
+}
+

Added: sandbox/channel/libs/channel/index.html
==============================================================================


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk