Ambient References

Tom Van Cutsem

ambientrefs.jpg

Ambient references are a novel type of remote object references. Remote object references are “pointers across the network” and are a frequently recurring abstraction in both distributed OO languages and distributed middleware. Ambient references are designed to refer to objects in mobile networks. What exactly constitutes a mobile network and how it differs from traditional, stationary networks is described elsewhere.

Motivation

One may wonder why new referencing abstractions are required for mobile networks. In order to motivate the need for new referencing abstractions at the language level, we list a number of desirable properties of remote references for mobile networks which current remote referencing abstractions do not offer:

  1. Intensional Naming: in mobile networks, one does not always know the identity or the exact number of the services one requires. Hence, rather than having to extensionally specify the services to bind to, one would like to refer to remote objects intensionally, based on the kind of services they provide.
  2. Resilience to Partial Failure: remote references for mobile networks should be able to tolerate network disconnections because transient network partitions are more commonplace in these types of networks.
  3. Roaming: remote references in mobile networks should bind to (point to) objects based on what services that object provides, rather than based on a low-level UID, object-id, IP address or MAC address. Such low-level IDs preclude the reference from reconfiguring itself by rebinding to a different object providing the same or equally matching services. In other words, we want object references for MANETs to integrally support roaming by being able to opportunistically bind to whatever proximate matching service is available, regardless of its identity.
  4. Broadcasting: in mobile networks, one often wants to communicate with an entire group of proximate objects. To this end, remote references should be introduced that can automatically broadcast messages to a set of (proximate) objects.

Design

Ambient references have undergone several design iterations. We summarize here the latest design in AmbientTalk/2, as it is fully described in my PhD dissertation.

Ambient references unify two concepts: they are both a peer-to-peer discovery channel and an asynchronous communication channel to a remote object. In AmbientTalk/2, they are represented as a special kind of far references. This implies that ambient references, like far references, are object references that can only carry asynchronously sent messages.

An ambient reference is initialized with a type tag: a network-wide name that describes a service known to the distributed peers. At any point in time, an ambient reference designates the set of proximate services whose type matches its type tag. For example:

def printers := ambient: Printer;

The variable printers refers to an ambient reference which, at any point in time, designates all nearby Printer objects. An ambient reference designates a volatile set of proximate objects: the set may grow or shrink as devices are moving in and out of wireless communication range.

It is possible to restrict the set of service objects which an ambient reference may designate even further, by using so-called filter queries. For example, suppose one only wants to send documents to a printer that supports a resolution greater than 400 dpi. This can be expressed as:

def printers := ambient: Printer where: { |p| p.dpi > 400 };
Message Passing Styles

An ambient reference can be used in two modes: as a point-to-point communication channel to any object in its designated set, or as a one-to-many communication channel to all objects in its designated set.

Point-to-point

Here is how to send a point-to-point message to any matching printer:

printers<-print(document)@One;

The syntax denotes an asynchronous message send in AmbientTalk/2. The @ syntax is used to annotate an asynchronous message with additional metadata. In the above code, the @One annotation signifies to the ambient reference that the print message should be sent to only one of the nearby Printer services.

AmbientTalk/2 supports future-type message passing, which basically allows the programmer to access the return value of the print method via a future. Futures are a very well known concept that unify asynchronous message passing with return values. More specifically, the futures employed in AmbientTalk/2 are based on the non-blocking futures of the E programming language. For more details, we refer to the papers below, but as a teaser, here's how one can notify the user when the print job has been sent:

def answer := printers<-print(document)@One;
when: answer becomes: { |ack|
  system.println("document successfully transmitted");
}

Ambient references seamlessly support roaming via point-to-point messaging: multiple messages sent to the same ambient reference may be delivered to different printing services. The programmer need not to worry about rebinding or reassigning the pointer to another Printer once the previously used Printer has moved out of range.

We will discuss later what happens if there are no matching Printer services at the time the message is sent.

One-to-many

The following piece of code illustrates how to broadcast a receiveTextMessage message to all proximate ChatPeer objects in a virtual chat room:

def peers := ambient: ChatPeer;
...
peers<-receiveTextMessage("hello world")@All;

Note the use of the @All annotation to signify to the ambient reference that the message should be broadcast to all nearby chat peers, not just to one of them.

Ambient references extend AmbientTalk/2's support for futures such that they can be used for broadcast messages. The issue with broadcast messages is that they may be received by more than one receiver object. As a result, they may return more than one return value. To deal with this, we introduce multifutures: futures that may be resolved multiple times. Multifutures have their own kind of listeners that can be used to observe state changes in the multifuture. For example, to gather replies to a text message, one may write:

def multifuture := peers<-receiveTextMessage("hello world")@All;
whenEach: multifuture becomes: { |reply|
  // process the reply
}

The above block closure { |reply| … } is applied for each return value sent back to the multifuture associated with the broadcast receiveTextMessage message.

Disconnected Operation and Timeouts

Ambient references have been designed for Mobile ad hoc networks in which transient network partitions are commonplace. Hence, ambient references support a form of message passing which is resilient to temporary network failures.

Any message sent to an ambient reference may be annotated with @Expires(timeout). The timeout parameter is a time period that describes how long the message will remain available for reception by proximate objects. We refer to it as the message's expiration period. When a message is sent to an ambient reference whose designated set of objects is empty, the message is not necessarily “lost”. The message will remain buffered within the ambient reference for its expiration period.

When an ambient reference discovers a receiver for its buffered messages in the ad hoc network, the messages are forwarded to the receiver(s). At this point, the message's remaining expiration period serves as a timeout for the outgoing message: if no reply to the message is received within the remaining timeout period, the message's associated future is ruined with a TimeoutException. Here is a modified version of the Printer example that deals with disconnected operation and failures:

def reply := printers<-print(document)@[One,Expires(minutes(2))];
when: reply becomes: { |ack|
  system.println("document successfully transmitted");
catch: TimeoutException using: { |e|
  system.println("request timed out");
}

If there are no matching Printer service objects at the time the print message is sent, the message will be buffered for at least 2 minutes within the ambient reference. If the message could not be sent to any printer, or it was sent to a printer but no reply was received within the 2 minute expiration period, the future associated with the message is ruined with a TimeoutException.

Conclusion

What is important to recall is that an ambient reference is a remote object reference that allows programmers to intensionally designate a volatile set of proximate objects. Ambient references support asynchronous point-to-point or one-to-many communication styles. Programmers can tweak a message's expiration period to make message delivery more resilient to temporary failures, and to perform failure handling.

Further Reading

Also see the Posters section for a poster describing ambient references graphically.