Lesson 4: Using the Local Tuplespace

Each mote has its own independent tuple space. Agilla provides 6 instructions for accessing the local tuple space. They are:

  1. out -- insert a tuple into the local tuple space
  2. inp -- remove a tuple from the local tuple space, do not block if no match is present
  3. rdp -- copy a tuple from the local tuple space, do not block if no match is present
  4. in -- remove a tuple from the local tuple space, block if no match is present
  5. rd -- copy a tuple from the local tuple space, block if no match is present
  6. tcount -- count the number of tuples in the local tuple space matching a particular template
  7. regrxn -- register a reaction
  8. deregrxn -- deregister a reaction

Agilla agents use a stack architecture. Tuples and templates are created by pushing their values onto the stack, followed by the number of fields. The order of the values on the stack represents the order they appear in the tuple. For example, suppose you want to create a tuple <int:1, int:2, string:"abc", loc:(1,1)>, and insert it into the local tuple space. Here's the code:

Note that you push the last field of the tuple first. Note also that despite the fact that the agent dies immediately after performing the OUT instruction, the tuple it inserted in the local tuple space remains.

The maximum number of fields a tuple can have is limited by the maximum size of the tuple, which is by default 25 bytes as defined by AGILLA_MAX_TUPLE_SIZE within <agilla>/types/TupleSpace.h. This value was chosen to ensure a tuple can fit within a single 36 byte TinyOS message. The size of a tuple or template's field is the size of the variable within the field + 1. Variables sizes are given here. The extra byte within every field is used to indicate the variable type. For example, the tuple in the example above would contains 3+3+3+5=14 bytes.

To retrieve a tuple from the local tuple space, you need to supply a template that matches the tuple. A template is the same as a tuple except some of its fields may contain types (also known as wild cards). A match occurs when the template and tuple have the same number of fields, and each field within the tuple matches that of a template. If the template's field is a non-type variable, the tuple's field must match exactly. This form of matching is called "match by value." However, if the template's field is a type variable, then the tuple's field must simply be of the same type. This form of matching is called "match by type." Note that a type-variable may match "ANY" other type, in which case a match always occurs. The template may contain any mix of match-by-value and match-by-type fields. For example, all of the following templates match the tuple above:

The following template is the exact same as the tuple, it matches by value in all fields. If this agent executes on the same node as the agent above, the green LED will light up.

The following template matches every field by value. If this agent executes on the same node as the agent above, the green LED will light up.

The following template matches some fields by value and others by type. If this agent executes on the same node as the agent above, the green LED will light up.

The following template does NOT match the tuple since it's first field does not match.

An agent can also register reactions on its local tuple space. A reaction allows an agent to immediately respond to the presence of a tuple in the local tuple space and helps prevent the agent from having to poll for a tuple. Reactions consist of a template and an address. When a tuple matching the template appears, the middleware immediately jumps the agent to the specified address in its instruction memory. The tuple and return address are stored on top of the stack. To register a reaction, the agent first pushes a template, then an address, onto the stack. It then calls regrxn to register the reaction. Here's an example.

The "reaction" agent above registers a reaction using template <type:value> and address BLINKRED. Thus, whenever a tuple containing a single value appears in the local tuple space, it will jump to BLINKRED and toggle the red LED. The agent is programmed to continuously blink the green LED, and only blink the RED led when its reaction fires. The reaction's code is on lines 10-14, as denoted by BLINKRED. Note that the first two instruction on lines 10-11 are both pop. This is necessary because the tuple that caused the reaction to fire is stored on the agent's stack. The top of the stack is a value that indicates the number of fields in the tuple which in this case it 1. The second variable in the stack is the value field within the tuple.

The following "instigator" agent can be used to cause the above agent's reaction to fire, assuming the above agent is injected onto node (1,1).

If the instigator agent is injected onto node (0,0), while the reaction agent is injected onto node (1,1), the reaction agent will react to the tuple and toggle its red LED.

Unlike tuples in a tuple space, reactions belong to the agent that registered it and remains with the agent across strong migrations and clones. Reactions can be explicitly deregistered using the deregrxn instruction, which takes in the template of the reaction that should be deregistered.

Note: One limitation of Agilla's reaction mechanism is that an agent can only register one reaction per template. That is, it can only register multiple reactions when the reactions contain different templates.

 

This work is supported by the ONR MURI Project CONTESSA and the NSF under grant number CCR-9970939.