_AN ASYNCHRONOUS DESIGN PATTERN_ by Allan Vermeulen Listing One /* File: IOUCallback.java */ /** * An object to be run when an IOU is closed. Each Escrow has a list * of these objects. They get fired when the IOU's escrow is closed. * * @see IOU, Escrow * * @author: alvis, 1/26/96 */ package iou; public interface IOUCallback { public void run(Object o); }; Listing Two /* File: IOU.java */ package iou; /** * An IOU is a token that you can later redeem for an actual object. * IOUs are typically returned from functions that build their results * asynchronously. * * An IOU refers to an Escrow object. The Escrow is responsible for * obtaining and holding on to the object referred to by the IOU. * * @author Alvis, 2/7/96 */ public class IOU extends Object { private Escrow escrow_; /** * Check if the IOU can be immediately redeemed. If this returns * true, then none of IOUs member functions will block. If it * returns false then standBy and redeem will likely block. */ public boolean closed() {return escrow_.closed();} /** * Wait until the object is ready. This will cause this thread of * execution to block. * @exception InterruptedException When the thread is interupted before * the IOU is enabled. */ public void standBy() throws InterruptedException {escrow_.standBy();} /** * Get the object promised by the IOU. * This will block if the IOU has not been enabled yet. * @exception InterruptedException When the thread is interupted before * the IOU is enabled. */ public Object redeem() throws InterruptedException {return escrow_.redeem();} /** * The run(Object) object interface in the IOUCallback * will be invoked when the IOU is enabled. The object passed * as a parameter to the callback is the IOU's value. * The callback is normally run in the same thread in which the * escrow is enabled. * If the IOU is already enabled, then it will be run immediately. */ public void addCallback(IOUCallback callback) { escrow_.addCallback(callback); } /** * Remove a callback that was previously added. If the callback * is not on the callback list it is ignored. */ public void removeCallback(IOUCallback callback) { escrow_.removeCallback(callback); } /** * Normally, you receive IOUs as return values from functions, you * don't build them yourself. If you are giving out IOUs, you should * obtain them from Escrow.iou. */ public IOU(Escrow e) {escrow_ = e;} } Listing Three /* File: Escrow.java */ package iou; /** * Escrow mediates the transaction between someone with an IOU, and * the party that gave out the IOU. Before you can give out an * IOU, you must create an Escrow. The IOU will refer to the Escrow * for all of its functionality. You must (eventually) enable the * Escrow before any IOU which refer to this Escrow can be redeemed. * * This is an abstract base class. The mechanism used to wait until * the Escrow is enabled is implemented by overriding the function * block(). The default mechanism for holding the object is to * keep a copy in a variable in the Escrow. It is expected that * some subclasses will override enabled(), value(), enable(), and * block() to change this policy. * * @see IOU * @author Alvis, 1/25/96 and 3/19/96 */ public abstract class Escrow extends Object { private boolean closed_; //can IOUs be redeemed without blocking? private java.util.Vector callbackList;//fire when ready /** * Constructor. */ public Escrow() { closed_ = false; callbackList = new java.util.Vector(); } /** * Return an IOU which refers to this Escrow. * The normal method of using an Escrow is to create the Escrow, and * then use this method to give out IOUs. */ public IOU iou() {return new IOU(this);} /** * Close the IOU. Once this is called, then redeem() and standBy() * must return without blocking. * Closing the IOU will run any callbacks which have been queued up. * Closing escrow more than once has no effect. * There can only be one first time. */ synchronized protected void close() { closed_ = true; Object value = redeemAfterClose(); // Fire the callbacks in the order they were provided. // The callback list has no elements if we have already closed escrow. for(int i=0; i