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:
- out -- insert a tuple into the local tuple space
- inp -- remove a tuple from the local tuple space, do not block
if no match is present
- rdp -- copy a tuple from the local tuple space, do not block
if no match is present
- in -- remove a tuple from the local tuple space, block if no
match is present
- rd -- copy a tuple from the local tuple space, block if no match
is present
- tcount -- count the number of tuples in the local tuple space
matching a particular template
- regrxn -- register a reaction
- 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.
|