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