Introduction to Polyphonic C#

Page: Prev 1, 2, 3 Next

Example: Asynchronous Remote Service Requests

Many applications make requests to services which take a long time to respond, such as disk IO on a local machine, accessing a database on a LAN or calling a web service across  the Internet. To mitigate the effects of latency, these requests should be made asynchronously - the caller should not block until the request completes, but should instead send a one-way message to the service, continue with other useful work and then later receive another one-way message containing a response or acknowledgement. Asynchronous programming is (even in the absence of failure) rather more complex than synchronous RPC-style communication because it is essentially more concurrent and because the correspondence between a particular request and a particular response must be handled explicitly by the programmer. Polyphonic C# does, however, make it easier to program a wide range of asynchronous programming patterns.

The basic idiom is that a service exposes an asynchronous method which takes some parameters and somewhere to put the result. This might be a buffer, like that in the earlier examples, or an asynchronous delegate:


delegate async IntCB(int v); 

class Service {
   public async request(String arg, IntCB callback) {
      int result;
   

   // do something interesting...
      callback(result);
   }
}

One common pattern on the client side involves making several requests to one or more services, continuing with useful work and then waiting until all of the responses have come back. The following code illustrates how this may be implemented in Polyphonic C# :


class Join2 {
   void wait(out int i, out int j)
   & async first(int r1)
   & async second(int r2) {
      i = r1; j = r2; return;
   }
}

// client code:
int i,j;
Join2 x = new Join2();
service1.request(arg1, new IntCB(x.first));
service2.request(arg2, new IntCB(x.second));
// do something useful
// now wait until both results have come back
x.wait(i,j);
// do something with i and j

The client creates a Join2 object x and then makes asynchronous requests to the services, passing delegates to the two asynchronous methods first and second on x. A later call to x.wait() will block until/unless both the responses have come back, at which point it assigns the results to the two reference parameters passed to wait() and continues.

Alternatively, one might make several requests to (often functionally equivalent) services and then later wait until at least one of them has returned a result. The code for this is a mild variation of the above:


class Select {
   int wait()
   & async reply(int r) {
      return r;
   }
}

// client code:
int i;
Select x = new Select();
service1.request(arg1, new IntCB(x.reply));
service2.request(arg2, new IntCB(x.reply));
// do something useful
// now wait until one result has come back
i = x.wait();
// do something with i

More discussion and examples can be found in the papers.

Page: Prev 1, 2, 3 Next