Sample 10.  channel using Linda-style associative lookup

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.

Lets walk thru the code.

All name space related types are defined in chat_defs.hpp.

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 simple design doc for more details. Boost.Tuple is used for tuple implementation, so <boost/tuple.hpp> is included.

For this sample, we use the following tuple type with 4 fields:
typedef boost::tuple<string, string, int, int> tuple_type;
typedef tuple_id<tuple_type> id_type;
These 4 fields are used to identify a person:
 *  string - first name
 *  string - last name
 *  int    - male(0), female(1)
 *  int    - department: math(0), physics(1), art(2)...
Next we instantiate the channel type. A associative name space is implemented as a linear namespace with associative  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.
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
  > chat_chan;

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:
Ids for specific persons:
A person with name "robin smith", male and in department of "art"
id_type robin_s_id(tuple_type(
                "robin",
                "smith",
                0,
                2));
A person with name "adam smith", male and in department of "math"
id_type adam_s_id(tuple_type(
                "adam",
                "smith",
                0,
                0));
A person with name "tina su", female and in department of "physics"
id_type tina_s_id(tuple_type(
                "tina",
                "su",
                1,
                1));
Ids for categories:
Id for all people with last name "smith"
id_type smith_r_id(tuple_type(
                field_trait<string>::wildcard,
                "smith",
                field_trait<int>::wildcard,
                field_trait<int>::wildcard));
Id for all people in "math" department
id_type math_r_id(tuple_type(
                field_trait<string>::wildcard,
                field_trait<string>::wildcard,
                field_trait<int>::wildcard,
                0));
Id for all female
id_type female_r_id(tuple_type(
                field_trait<string>::wildcard,
                field_trait<string>::wildcard,
                1,
                field_trait<int>::wildcard));

Next we define a simple structure for message data:
struct chat_msg {
  string source_;
  string data_;
  chat_msg(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_;
  }
};

As a last step, we need to add the following macro to define the system internal messages (ugly):
DEFINE_ASSOC_SYS_IDS(tuple_type)

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 "smith_r_id", it will receive messages for both "robin smith" and "adam smith".

Complete source code listing:
chat_defs.hpp
chat1.cpp
chat2.cpp