Proposed Asynchronous Control Flow Operators

From Erights

Revision as of 17:49, 20 November 2007 by Const (Talk)
Jump to: navigation, search

TODO possibly there should be per-operator pages.

This page describes some not implemented asynchronous control flow operators that could simplify creation of asynchronous application. The intial set of operators is based on experience of implementing the AsyncObjects framework and Sebyla project design.

Contents

Later

This is an extremely simple construct. But is useful when it is requited to execute code in this or other vat at some later time. In AsyncObjects this constructs is implemented using AsyncAction class, and it was used quite a lot in applications.

	“later” ( “(” <vatHandle> “)” )? “->” “{“ 
		<code>
	“}”

When code is executed in other vat, the runtime checks that code closes only over deep frozen or bass by copy objects. If vat is not specified, the code is scheduled to be executed at later turn in this vat. The vatHandle is an expression that evaluates to capability of executing actions on the vat.

Using

This is a very simple construct that helps with resource management. The syntax is like the following:

	“using” “(“ ( (“def” <varName> “:=” )? <eventualOpenExpression> )+ “)” “->” “{“
		<statements>
	“}”

The operator is executed as the following:

  1. All resources are opened in the specified order. If expression returns promise, the next expression is not executed before first one complete. If <varName> is specified for resource, the resolved resource is assigned to it and it can be used in subsequent expressions and <statements>.
  2. If opening of some resource fails, the proposed result of operator is that failure.
  3. Statements are executed, the proposed result of operator is value of last expression. If the result is promise, the operator waits until it is resolved.
  4. All opened connections are closed, in reverse order. It includes connections that has not been named. If some close operations fail, the most top level one is returned.

Example:

using(def r1 := factory1<-openConnection,  def r2 := factory2<-openConnection, lock<-lockEnter()) -> {
	doSomething(r1,r1); // assuming that lock is being held
}

The constructs expands to the following:

when(def r1 := factory1<-openConnection()) {
	when(def r2:= factory2<-openConnection()) {
		when( def tmpVar := lock<-lockEnter()) {
			doSomething(r1,r1); 	
		} finally {
			tmpVar<-close();			
		}
	} finally {
		r2<-close();
	}
} finally {
	r1<-close();
}

Seq

The are several form of seq operator. The basis form is the following.

	“seq” (“def” <varName> “:=”)? “{“
		<statements-1>
 	“}”  ( “then” (“def” <varName> “:=”)? “{“
		<statements-i>
 	“}” ) * ( “catch” “(“ <exceptionVar> “)” “{“ 
		<catchStatements>
	“}” )?  (“finally” “{“ 
		<finallyStatements> 
	“}”)?

The code is executed like the following:

  1. The code in <statements-i> is executed sequentially. The next code block is executed only if promise returned from previous code block is resolved. If the block yields near value, the next block is executed on the same turn.
  2. The result of operator is the value of the last block.
  3. If some of blocks fails, the next blocks are not executed, and control is passed to the catch section and the result of operator will be the result of executing catch statement. If there is no catchSection, the operator fails with expression.
  4. If there is a finally statement, it is executed after last block or after catch statement. If it fails, the entire seq expression fails with the same exception.

Example:

	seq def a := {
		doA()
	} then {
		doSomething(a)
	} catch(e) {
		print(e)
		throw e
	} finally {
		cleanup()
	}

Example is expanded as the following:

	when(someTempResolvedPromise) {
		def aVow := {
			doA();
		}
		when (def a := aVow) {
			doSomething(a);
		}
	}  catch(e) {
		print(e)
		throw e
	} finally {
		cleanup() 
	}

There is also a short form:

	“seq” “(“  (“def” <varName> “:=” )? <eventualExpression> ( “,” (“def” <varName> “:=” )? <eventualExpression> )* “)”

The comma separated expressions are executed in sequence. The named values are available at later expressions. The are three loops forms:

	“seq” “do” “{“
		<statements>
 	“}”  “while” “(“ <eventualExpressions> “)”

	“seq” “while” “(“ <eventualExpressions> “)” “{“
		<statements>
 	“}”  

	“seq” “for” <pattern> “in” <collection> “{“
		<statements>
 	“}”  

The semantics is the same as for normal loops. The next iteration starts only after previous completed. TODO it might be useful to keep intermediate results of previous iteration and to make them available in the body of the loop and conditions. On other hand, it is quite easy to use basic seq operator to achieve the same result. TODO “seq for” needs support for eventual iterators.

All

This operator allows execution of eventual expressions in parallel. The basic form is the following:

“all” “{“ 
	<expression>
“}” ( “and” “{“
	<expression>
“}” )+

The short form is the following:

“all” “(“ <expression> ( “,” <expression> )+ “)”

Semantics is the following:

  1. All expressions starts to be executed.
  2. If all expressions completed successfully, a list of results is returned.
  3. If at least one expression fails, an exception that contains generated results and failures is generated.

Example:

all {
	first()
} and {
	second()
} 

It is translated like the following:

when(someResolvedPromise) -> {
	var wereFaults = false;
	var results = makeFlexList();
	results.setSize(2)
	var faults = makeFlexList();
	faults.setSize(2)
	def vow1 := seq def r: = {
		first()
	} then {
		results[0] := r
	} catch(e) {
		wereFaults = true
		faults[0] := e
		null
	}
	def vow2 := seq def r: = {
		second()
	} then {
		results[1] := r
	} catch(e) {
		wereFaults = true
		faults[1] := e
		null
	}
	when (def v1:=vow1, def v2:=vow2) {
		if(wereFaults) {
			throw makeAllFault(results,faults)
		} else {
			results.toConsList()
		}
	}
}

There is also a loop form that returns conslist of results.

“all” “for” <pattern> “in” <collection> “ “{“ 
	<expression>
“}” 
Personal tools
more tools