The SHWi1dPathSorter class defines the "normal" way of routing BMessages under SockHop. Whenever a new SockHop node is created, an SHWi1dPathSorter object is automatically added to its available sorter list, and is made the default sorter for all BMessages that the node handles.
Wi1dPath Routing Semantics
The SHWi1dPathSorter implements a BMessage routing mechanism based on filesystem-like "path strings" through SockHop's virtual network tree. Because it is so simple and powerful, and because SockHop relies on it internally, it is automatically created and made the default SHSorter for any new node that SockHop creates.
The SHWi1dPathSorter bases all its message-forwarding decisions on one field in the BMessages: SH_NAME_TO (aka "shTo", but it's better style to use the symbol defined in <sockhop/SockHopConstants.h>). This field, if present, should contain an array of one or more "path strings" that dictate what paths through the tree the BMessage should take.
Each path string is interpreted by the SHWi1dPathSorter as a "virtual tree pathname" that specifies a set of nodes who are to receive this BMessage ("receiving" the BMessage means that the BMessage is posted to all SHWorkers living on that node, if they are interested in it). When there is one string is found in the SH_NAME_TO array, then the union of all the nodes specified by all strings in in the array will receive this BMessage.
If no SH_NAME_TO strings are present in the BMessage, on the other hand, then the BMessage is considered to be a "broadcast" message, and is sent to every node in the tree (so remember to add an appropriate SH_NAME_TO field to all your BMessages if you don't want them to go everywhere!!!).
The format of each string should be familiar to anyone who has used any shell under BeOS or UNIX--it is a pathname with the same conventions as any filesystem pathname. If you imagine SockHop's virtual network tree to be a tree of directories in a filesystem, and the node that the BMessage is posted to to be the "current directory", then you have the right idea.
Some Examples of SHWi1dPathSorter Routing
Let's say your SockHop program has created the following virtual network
tree:
As you can see, the root node of the tree is name "/". The root node is the one returned by the call to SHCreateRootNode(), and it is always named "/". No exceptions!
The root node has spawned three children, named "Red", "Green", and
"Blue". "Red", in turn, has two children named "Pink" and "Mauve";
"Green" has one child name "Puce"; and "Blue" has two children named "Cyan"
and "Navy". Each of these nodes has a unique absolute pathname, generated
by concatenating node names while traversing the path from the root to
the node:
Node Name | Absolute Node Path |
"/" | "/" |
"Red" | "/Red" |
"Green" | "/Green" |
"Blue" | "/Blue" |
"Pink" | "/Red/Pink" |
"Mauve" | "/Red/Mauve" |
"Puce" | "/Green/Puce" |
"Cyan" | "/Blue/Cyan" |
"Navy" | "/Blue/Navy" |
And sending a BMessage to a list of nodes is just as easy, you don't even have to call PostMessage() multiple times:
Even better, you can use regular expressions (a.k.a. wildcarding) to implicitly specify complex sets of nodes. For example, this code will send a BMessage to every grandchild in the tree (that is, to "Pink", "Mauve", "Puce", "Cyan", and "Navy"):
And feel free to mix different methods together; since the BMessage is delivered to the union of the nodes specified by each path string, you don't have to worry that specifying a node more than once will cause it to receive more than one copy of the BMessage:
Another feature that the SHWi1dPathSorter shares with the BeOS filesystems is the abilitity to use relative pathnames. If you do not specify the leading slash in your path string, then the message will be delivered to nodes relative to the "current node"--that is, the node to which the BMessage was directly posted.
As an example, consider this code, that is running within an SHComponent (that is, either an SHSorter or an SHWorker) on one of the nodes in the tree:
If the SHComponent posting this message is running on "Blue", then the BMessage will be delivered to both "Cyan" and "Navy", since they are both children of "Blue" and have the letter "a" in their node name. But if this code were executed from within an SHComponent running on "Red", then only "Mauve" would receive the BMessage, as "Pink" has no "a" in it.
BMessages posted by the main user program (that is, the code that called SHCreateRootNode() to create the SockHop network) are always posted starting at the root of the tree, and thus generally propagate down the tree. Code running on nodes within the tree, however, may want to send BMessages back up the tree. Once again, the syntax for doing this comes straight from filesystem parlance:
This, of course, sends the BMessage to the parent node of the node this code's SHComponent is running on. Other permutations, such as "../.." (go up two levels in the tree), or "../Blue" (go up one to our node's parent, then down to its child named "Blue"), etc, will also work as expected.
If a BMessage posted from an SHComponent in the virtual network tree uses an absolute pathname (i.e., one with a leading slash), then the BMessage will be sent all the way up to the root node of the tree before propagating back down to their destination. This can be inefficient (lots of message hops!), so you may prefer to have your SHComponents use relative pathnames wherever possible.
But what if an SHComponent wants to send a BMessage back to the main user program? The main program does not have a node on the tree to identify it; so what pathname should be given? The short answer is: to send a BMessage back to the main program, use the magical pathname "/.."
Well, actually that pathname isn't really magical. It works because your main user program's target BLooper (the one you specified in your call to SHCreateRootNode()) is considered to be living "above" the root node of the SockHop tree. Thus, the pathname "/.." does two things--the slash takes the BMessage to the root node (following the rule for absolute pathnames described above) and from there, the ".." raises it one more level, out the top of the tree and back your target BLooper. You could also send the BMessage back to the main user program by specifying a pathname like "../../../../..", where the number of ".."'s in the pathname is greater than or equal to your posting component's node's depth in the tree.
Lastly, the node name "." can be used to refer to the current node, just like the "current directory" in a filesystem.
Specifying which SHWorkers the BMessage should go to
Once your BMessage has arrived at its destination node(s), you may want to further specify which of the SHWorkers on those nodes should get the BMessage. By default, every interested SHWorker on a destination node is given a copy of the BMessage. To specify just a subset of SHWorkers, however, you can specify them by name in the SH_NAME_TOWORKERS field of your BMessage. This field takes one or more strings, each of which may be the name of an SHWorker (as returned by the SHWorker's GetName() method), or a regular expression to specify multiple SHWorkers. The BMessage will be routed to the union of the workers specified in the SH_NAME_TOWORKERS field. For example:
myMessage.AddString(SH_NAME_TOWORKERS,
"Fred"); // give Fred a copy
myMessage.AddString(SH_NAME_TOWORKERS,
"G*"); // also give George, Gary, and Gracy a copy