next up previous contents
Next: Join Block Continuations Up: Advanced Concurrency Coordination Previous: Advanced Concurrency Coordination


Named Tokens

Chapter 3 has introduced token-passing continuations with the reserved keyword token. In this section, we will focus on the other type of continuations, the named tokens.

Warning: Tokens can ONLY be used as arguments to messages. SALSA 1.1.2 does not allow to use tokens as part of expressions (e.g., x+2) or to be used as return values (e.g., return token).
In SALSA, the return value of an asynchronous message can be declared as a variable of type token. The variable is called a named token. Named tokens are designed to allow more expressibility by allowing explicit definition of continuations. For example, a token-passing continuation statement can be re-written by name token continuations:
 
//line 1 is equivalent to lines 2-3
1. hello() @ standardOutput<-print(token);

2. token x = hello(); 3. standardOutput<-print(x);

Name tokens can be used to construct a non-linear partial order for computation, which cannot be expressed by token-passing continuations. The following example cannot be re-written by token-passing continuations:
 
token x = a<-m();
token y = b<-o();
token z = c<-p();

d<-p(x,y); e<-q(y,z); f<-r(x,z);

The following example uses name tokens to implement the Fibonacci number application:
 
module examples;

behavior Fibonacci { int n;

Fibonacci(int n) { this.n = n;}

int add(int x, int y) {return x + y;}

int compute() { if (n == 0) return 0; else if (n <= 2) return 1; else { Fibonacci fib1 = new Fibonacci(n-1); Fibonacci fib2 = new Fibonacci(n-2); token x = fib1<-compute(); token y = fib2<-compute(); //using name tokens and first-class continuations add(x, y) @ currentContinuation; } }

void act(String args[]) { n = Integer.parseInt(args[0]); //using token passing continuations compute() @ standardOutput<-println(token); } }

Named tokens may be assigned to non-primitive type values, message sending expressions, or other named tokens. Examples are shown as follows:
 
1. token y  = a<-m1();
2.
3. token z = y;
4.
5. y = b<-m2(y);
6. self<-m() @ c<-m3(token, z, y);
 
   
The following example shows how to use named tokens. Lines 1-2 are equivalent to lines 3-5 using fewer token declarations:
 
//lines 1-2 are equivalent to lines 3-5
1. token x  = a<-m1();
2. x = b<-m2(x);

3. token x = a<-m1(); 4. token y = b<-m2(x); 5. x = y;

The following example demonstrates how named tokens are used in loops:
 
1. token x  = a<-m1();
2. for (int i = 0; i < 10; i++) x = b<-m2(x, i);
 
   
The previous example is equivalent to the following example:
 
a<-m1() @ 
b<-m2(token, 0) @ 
b<-m2(token, 1) @ 
b<-m2(token, 2) @ 
b<-m2(token, 3) @ 
b<-m2(token, 4) @ 
b<-m2(token, 5) @ 
b<-m2(token, 6) @ 
b<-m2(token, 7) @ 
b<-m2(token, 8) @ 
token x = b<-m2(token, 9);
 
   
To learn more about named tokens, we use the following example to illustrate how the named token declaration works and to prevent confusion:
 
1.    token x  = a<-m1();
2.
3.    for (int j = 0; j < 10; j++) {
4.        b<-m2(x);
5.        x = c<-m3(x);
6.        d<-m4(x);
7.    }
 
   
The token is updated as soon as the code is processed. In the for loop on lines 3-7, for each iteration of the loop, the value of token x in b<-m2 and c<-m3 is the same. However, the value of token x in d<-m4 is the token returned by c<-m3, and thus equal to the value of token x in the message sends on lines 4 and 5 in the next iteration of the loop.


next up previous contents
Next: Join Block Continuations Up: Advanced Concurrency Coordination Previous: Advanced Concurrency Coordination
Wei-Jen Wang
2007-11-28