ref_send API 2.17
defensive programming in Java

org.ref_send.promise
Class Eventual

java.lang.Object
  extended by org.ref_send.promise.Eventual
All Implemented Interfaces:
java.io.Serializable, Selfless

public class Eventual
extends java.lang.Object
implements Selfless, java.io.Serializable

The eventual operator.

This class decorates an event loop with methods implementing the core eventual control flow statements needed for defensive programming. The primary aim of these new control flow statements is preventing plan interference.

The implementation of a public method can be thought of as a plan in which an object makes a series of state changes based on a list of invocation arguments and the object's own current state. As part of executing this plan, the object may need to notify other objects of the changes in progress. These other objects may have their own plans to execute, based on this notification. Plan interference occurs when execution of these other plans interferes with execution of the original plan.

Plan interference

Interleaving plan execution is vulnerable to many kinds of interference. Each kind of interference is explained below, using the following example code:

 public final class
 Account {

  private int balance;
  private final ArrayList<Receiver<Integer>> observers;

  Account(final int initial) {
      balance = initial;
      observers = new ArrayList<Receiver<Integer>>();
  }

  public void
  observe(final Receiver<Integer> observer) {
      if (null == observer) {
          throw new NullPointerException();
      }
      observers.add(observer);
  }

  public int
  getBalance() { return balance; }

  public void
  setBalance(final int newBalance) {
      balance = newBalance;
      for (final Receiver<Integer> observer : observers) {
          observer.apply(newBalance);
      }
  }
 }
 

Unanticipated termination

A method can terminate execution of its plan by throwing an exception. The plan may be terminated because it would violate one of the object's invariants or because the request is malformed. Unfortunately, throwing an exception may terminate not just the current plan, but also any other currently executing plans. For example, if one of the observers throws a RuntimeException from its apply() implementation, the remaining observers are not notified of the new account balance. These other observers may then continue operating using stale data about the account balance.

Nested execution

When a method implementation invokes a method on another object, it temporarily suspends progress on its own plan to let the called method execute its plan. When the called method returns, the calling method resumes its own plan where it left off. Unfortunately, the called method may have changed the application state in such a way that resuming the original plan no longer makes sense. For example, if one of the observers invokes setBalance() in its apply() implementation, the remaining observers will first be notified of the balance after the update, and then be notified of the balance before the update. Again, these other observers may then continue operating using stale data about the account balance.

Interrupted transition

A called method may also initiate an unanticipated state transition in the calling object, while the current transition is still incomplete. For example, in the default state, an Account is always ready to accept a new observer; however, this constraint is temporarily not met when the observer list is being iterated over. An observer could catch the Account in this transitional state by invoking observe() in its apply() implementation. As a result, a ConcurrentModificationException will be thrown when iteration over the observer list resumes. Again, this exception prevents notification of the remaining observers.

Plan isolation

The above plan interference problems are only possible because execution of one plan is interleaved with execution of another. Interleaving plan execution can be prevented by scheduling other plans for future execution, instead of allowing them to preempt execution of the current plan. This class provides control flow statements for scheduling future execution and receiving its results.

Naming convention

Since the control flow statements defined by this class schedule future execution, instead of immediate execution, they behave differently from the native control flow constructs in the Java language. To make the difference between eventual and immediate execution readily recognized by programmers when scanning code, some naming conventions are proposed. By convention, an instance of Eventual is held in a variable named "_". Additional ways of marking eventual operations with the '_' character are specified in the documentation for the methods defined by this class. All of these conventions make eventual control flow statements distinguishable by the character sequence "_.". Example uses are also shown in the method documentation for this class. The '_' character should only be used to identify eventual operations so that a programmer can readily identify operations that are expected to be eventual by looking for the _. pseudo-operator.

See Also:
Section 13.1 "Sequential Interleaving Hazards" of "Robust Composition: Towards a Unified Approach to Access Control and Concurrency Control", Serialized Form

Field Summary
 Receiver<?> destruct
          destruct the vat
 Log log
          debugging output
 
Constructor Summary
Eventual(Receiver<Promise<?>> enqueue)
          Constructs an instance.
Eventual(Receiver<Promise<?>> enqueue, java.lang.String here, Log log, Receiver<?> destruct)
          Constructs an instance.
 
Method Summary
<T> T
_(T referent)
          Ensures a reference is an eventual reference.
<T extends java.io.Serializable>
void
_(T x)
          Causes a compile error for code that attempts to create an eventual reference of a concrete type.
static
<T> T
cast(java.lang.Class<?> type, Promise<T> promise)
          Casts a promise to a specified type.
<T> Deferred<T>
defer()
          Creates a promise in the unresolved state.
 boolean equals(java.lang.Object x)
           
 int hashCode()
           
static
<T> T
near(Promise<T> promise)
          Gets a corresponding immediate reference.
static
<T> T
near(T reference)
          Gets a corresponding immediate reference.
static
<T> Promise<T>
ref(T referent)
          Gets a corresponding promise.
static
<T> Promise<T>
reject(java.lang.Exception reason)
          Constructs a rejected promise.
<R> Vat<R>
spawn(java.lang.String label, java.lang.Class<?> maker, java.lang.Object... optional)
          Creates a sub-vat.
<P,R> R
when(P reference, Do<P,R> conditional)
          Does an eventual conditional operation on an eventual reference.
<P,R> R
when(Promise<P> promise, Do<P,R> conditional)
          Does an eventual conditional operation on a promise.
 
Methods inherited from class java.lang.Object
getClass, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

log

public final Log log
debugging output


destruct

public final Receiver<?> destruct
destruct the vat

call like: destruct.apply(null)

Constructor Detail

Eventual

public Eventual(Receiver<Promise<?>> enqueue,
                java.lang.String here,
                Log log,
                Receiver<?> destruct)
Constructs an instance.

Parameters:
enqueue - raw event loop
here - URI for the event loop
log - log
destruct - destruct

Eventual

public Eventual(Receiver<Promise<?>> enqueue)
Constructs an instance.

Parameters:
enqueue - raw event loop
Method Detail

hashCode

public int hashCode()
Specified by:
hashCode in interface Selfless
Overrides:
hashCode in class java.lang.Object

equals

public boolean equals(java.lang.Object x)
Overrides:
equals in class java.lang.Object

when

public final <P,R> R when(Promise<P> promise,
                          Do<P,R> conditional)
Does an eventual conditional operation on a promise.

The conditional code block will be notified of the promise's state at most once, in a future event loop turn. If there is no referent, the conditional's reject method will be called with the reason; otherwise, the fulfill method will be called with either an immediate reference for a local referent, or an eventual reference for a remote referent. For example:

 import static org.ref_send.promise.Eventual.ref;
 …
 final Promise<Account> mine = …
 final Promise<Integer> balance =
     _.when(mine, new Do<Account,Promise<Integer>>() {
         public Promise<Integer>
         fulfill(final Account x) { return ref(x.getBalance()); }
     });
 

A null promise argument is treated like a rejected promise with a reason of NullPointerException.

The conditional in successive calls to this method with the same promise will be notified in the same order as the calls were made.

This method will not throw an Exception. Neither the promise, nor the conditional, argument will be given the opportunity to execute in the current event loop turn.

Type Parameters:
P - parameter type
R - return type
Parameters:
promise - observed promise
conditional - conditional code block, MUST NOT be null
Returns:
promise, or eventual reference, for the conditional's return, or null if the conditional's return type is Void

when

public final <P,R> R when(P reference,
                          Do<P,R> conditional)
Does an eventual conditional operation on an eventual reference.

The implementation behavior is the same as that documented for the promise based when statement.

Type Parameters:
P - parameter type
R - return type
Parameters:
reference - observed reference
conditional - conditional code block, MUST NOT be null
Returns:
promise, or eventual reference, for the conditional's return, or null if the conditional's return type is Void

defer

public final <T> Deferred<T> defer()
Creates a promise in the unresolved state.

The return from this method is a ( promise, resolver ) pair. The promise is initially in the unresolved state and can only be resolved by the resolver once. If the promise is fulfilled, the promise will forever refer to the provided referent. If the promise, is rejected, the promise will forever be in the rejected state, with the provided reason. If the promise is resolved, the promise will forever be in the same state as the provided promise. After this initial state transition, all subsequent invocations of either fulfill, reject or resolve are silently ignored. Any observer registered on the promise will only be notified after the promise is either fulfilled or rejected.

Type Parameters:
T - referent type
Returns:
( promise, resolver )

_

public final <T> T _(T referent)
Ensures a reference is an eventual reference.

An eventual reference queues invocations, instead of processing them immediately. Each queued invocation will be processed, in order, in a future event loop turn.

Use this method to vet received arguments. For example:

 import static org.joe_e.ConstArray.array;

 public final class
 Account {

     private final Eventual _;
     private int balance;
     private ConstArray<Receiver<Integer>> observer_s;

     public
     Account(final Eventual _, final int initial) {
         this._ = _;
         balance = initial;
         observer_s = array();
     }

     public void
     observe(final Receiver<Integer> observer) {
         // Vet the received arguments.
         final Receiver<Integer> observer_ = _._(observer);

         // Use the vetted arguments.
         observer_s = observer_s.with(observer_);
     }

     public int
     getBalance() { return balance; }

     public void
     setBalance(final int newBalance) {
          balance = newBalance;
          for (final Receiver<Integer> observer_ : observer_s) {
              // Schedule future execution of notification.
              observer_.apply(newBalance);
          }
     }
 }
 

By convention, the return from this method is held in a variable whose name is suffixed with an '_' character. The main part of the variable name should use Java's camelCaseConvention. A list of eventual references is suffixed with "_s". This naming convention creates the appearance of a new operator in the Java language, the eventual operator: "_.".

If this method returns successfully, the returned eventual reference will not throw an Exception on invocation of any of the methods defined by its type, provided the invoked method's return type is either void, an allowed proxy type or assignable from Promise. Invocations on the eventual reference will not give the referent, nor any of the invocation arguments, an opportunity to execute in the current event loop turn.

Invocations of methods defined by Object are not queued, and so can cause plan interference, or throw an exception.

Type Parameters:
T - referent type, MUST be an allowed proxy type
Parameters:
referent - immediate or eventual reference, MUST be non-null
Returns:
corresponding eventual reference
Throws:
java.lang.NullPointerException - null referent
java.lang.ClassCastException - T not an allowed proxy type

_

public final <T extends java.io.Serializable> void _(T x)
Causes a compile error for code that attempts to create an eventual reference of a concrete type.

If you encounter a compile error because your code is linking to this method, insert an explicit cast to the allowed proxy type. For example,

_._(this).apply(null);

becomes:

_._((Receiver<?>)this).apply(null);

Parameters:
x - ignored
Throws:
java.lang.AssertionError - always thrown

cast

public static <T> T cast(java.lang.Class<?> type,
                         Promise<T> promise)
              throws java.lang.ClassCastException
Casts a promise to a specified type.

For example,

  final Channel<Receiver<Integer>> x = _.defer();
  final Receiver<Integer> r_ = cast(Receiver.class, x.promise);
 

Type Parameters:
T - referent type to implement
Parameters:
type - referent type to implement
promise - promise for the referent
Returns:
reference of corresponding type
Throws:
java.lang.ClassCastException - no cast to type

ref

public static <T> Promise<T> ref(T referent)
Gets a corresponding promise.

This method is the inverse of cast; it gets the corresponding promise for a given reference.

This method will not throw an Exception.

Type Parameters:
T - referent type
Parameters:
referent - immediate or eventual reference

near

public static <T> T near(T reference)
Gets a corresponding immediate reference.

This method should only be used when the application knows the provided reference refers to a local object. Any other condition is treated as a fatal error. Use the call method to check the status of a promise.

This method will not throw an Exception.

Type Parameters:
T - referent type
Parameters:
reference - possibly eventual reference for a local referent
Returns:
corresponding immediate reference

near

public static <T> T near(Promise<T> promise)
Gets a corresponding immediate reference.

This method should only be used when the application knows the provided promise refers to a local object. Any other condition is treated as a fatal error. Use the call method to check the status of a promise.

This method will not throw an Exception.

Type Parameters:
T - referent type
Parameters:
promise - a promise
Returns:
corresponding reference

reject

public static <T> Promise<T> reject(java.lang.Exception reason)
Constructs a rejected promise.

Type Parameters:
T - referent type
Parameters:
reason - rejection reason

spawn

public <R> Vat<R> spawn(java.lang.String label,
                        java.lang.Class<?> maker,
                        java.lang.Object... optional)
Creates a sub-vat.

All created vats will be destructed when this vat is destructed.

The maker MUST be a public Joe-E class with a method of signature:

 static public R
 make(Eventual _, …)
 

The ellipsis means the method can have any number of additional arguments. The Eventual parameter, if present, MUST be the first parameter.

This method will not throw an Exception. None of the arguments will be given the opportunity to execute in the current event loop turn.

Type Parameters:
R - return type, MUST be either an interface, or a Promise
Parameters:
label - optional vat label, if null a label will be generated
maker - constructor class
optional - more arguments for maker's make method
Returns:
sub-vat permissions, including a promise for the object returned by the maker

ref_send API 2.17
defensive programming in Java

Submit a bug or feature, or get help

Copyright 1998-2009 Waterken Inc. under the terms of the MIT X license.