Tuesday, February 28, 2012

Synchronicity

In mathematics, functions are beautiful things. They represent lines, curves, surfaces, and things in higher dimensional spaces that defy verbal description. With applications in areas that span from practical statistics to abstruse string theory, no one can argue their importance to daily life.

In programming, functions are just as important (I would have said "if not more important", but that seemed needlessly tautological). Interesting, and sometimes overlooked though, are synchronicity aspects of function invocation in programming. Now that we already have a post on location based services, we can leverage that to make our points here more clearly. So let's embark on this journey.

Most functions in computer science are synchronous. By this we mean, we build a function, we call it with zero, one or more arguments, and it returns a value. The code we write that invokes the function populates the arguments, makes the function invocation, then waits patiently till the function call completes, assigns the returned variable to a program variable, and continues execution. Of course, depending on whether the variables were passed by value or by reference, and whether any global variables were also used, etc, there may be a number of other "side-effects" caused by the function invocation on other aspects of program execution but we blithely ignore these here for sake of simplicity.

Synchronous function execution is thus, the simplest, and most intuitive way that functions, and yes sub-routines, and the like are used. But is that all functions can be used for? Let's study a couple of other models.

Enter the Asynchronous function call
When we look at complex APIs - such as, for example the OSA/Parlay APIs for mobile network application development, these contain function calls where what the function is asked to do cannot be done immediately. It is unreasonable to expect a program to wait for as long as a function might take to return in such cases. A way out of this dilemma might be to embed this function call in a separate thread from the main thread of program execution, and have that thread block on the function while the rest of the program goes on its merry way. An arguably more elegant approach is through the use of asynchronous methods.

So how do these work? Software platforms like CORBA and Java RMI (does anyone still use this anymore?) permit one to invoke a function and register a "call-back". The call-back is a reference to a function in the main program that the called function (typically run across the network on another machine somewhere), can invoke on it. So the logic flow proceeds something like this:

  1. main program A invokes function x on program B, passing along a call-back reference c.
  2. B returns an immediate return value, typically indicating whether the function was well structured and     if it will be executed.
  3. the function x returns synchronously to A the immediate return value from (2) above.
  4. B continues executing the function, and when it has an update for A, passes this value to A by invoking call-back c. c returns immediately (i.e. c is synchronous to B)
  5. at this point, c is either still open, or is closed based on pre-determined call-back protocol design between A and B specified in the API.
All this might seem needlessly complicated. But it can be extremely useful. So we look at an example below.

Using Asynchronous Functions - An Example
Let's say you (an application) want periodic location updates for a mobile handset. You could poll the network for location every 30 seconds or so synchronously, and speed up the poll interval if the handset is traveling faster, and slow down the interval if it is slower-moving. But this puts the burden on the application to keep timers etc., A more elegant way to implement this would be to have the application register a call-back with the underlying network node saying: "here's the terminal whose location I need: 555-555-1111. send it to me every 30 sec at this address http://updatesRUs/5555551111x will you? till I tell you to stop, thanks. and if you think it's not really moving that much, feel free to slow down updates a bit"

And the app can continue about its business and process updates as it receives them. When the user tied to the app decides he has for example, reached his destination and does not need location information anymore, the app can send another message to the network saying "remember my request for 555-555-1111? cancel that now please". And the call-back address specified above disappears, so the network cannot post any more updates. Useful, isn't it?

From callbacks to "recruiting"
An erstwhile colleague of mine (the author thanks A. Sahuguet) once showed me another model called "recruiting" that can be even more useful. The way this works is, A invokes a method on B, B on C, and C gets back directly to A. In other words, B "recruits" C to respond to A's request. Typically, networked software implementations require the request/response flow to be A->B->C->B->A, but this is shortened to A->B->C->A in this scenario. Of course there are issues with security etc, and yes, there are ways to address them, but we do not cover those here. How one might set up asynchronous function calls to support a recruiting model is left as an exercise to the reader.

Hope this made fun reading! 

No comments:

Post a Comment