It’s amazing to me how seemingly complex programming techniques are really not that complex at all if you break them down into their basic Unix CLI equivalence.

Take, for example, Polyphonic C# where they introduce the concept of the asynchronous join pattern,

Continuations, futures, and whatnot - Thoughts on some asynchronous patterns - B# .NET Blog

Join patterns

If you’ve had a rendez-vous with Ada in a previous life, you’ll be familiar with the concept of join patterns (or shorthand joins). Our Microsoft Research department has done quite some work on this field already, as you can read here: http://research.microsoft.com/~crusso/joins/. It’s part of Polyphonic C#, which is by itself part of Cw and based on join calculus. We already got the LINQ inspiration from it, joins might be lurking around the corner too. There actually just two basic concepts to understand here:

* Asynchronous methods: imagine a keyword async as a modifier on methods (which would imply the method is a procedure, hence the void return type becoming redundant for those type of methods). No longer do you need to create separate versions of a method with or without the Async suffix to work around return type overloading limitations imposed by the runtime. You can think of the method as a wrapper around a task scheduling call, wrapping the entire body. Whether or not this spawns a new thread is another matter.
* Join patterns: also known as chords, is a declarative way of a WaitAll style of guard mechanism to enter a method.

Our monk would look like:


    class Monk
    {
         public async RequestCard(string to) { ... }
         public string GetCard() & public async RequestCard(string to) { ... }
    }

Basically requests for cards queue up on the monk’s GetCard operation, ready to get processed when the monk is awake. Actually this sample is convoluted and our monk suffers from some concurrency diseases (think of the cards it would hand out if there are multiple outstanding requests - any ordering guarantees without “ticketing”?) but I won’t get in details for now - it’s just (yet) another way of thinking about asynchronous processing with today’s materials in the room. If you’re inspired by join patterns, check out the Polyphonic C# paper.

Sounds interesting, and extremely cool. And I can’t wait to start playing with this feature if and when it becomes a part of the core C# language specification. But I’m not sure it’s something we haven’t been able to do for *years* already In the mean time, for those that want to begin sinking their teeth into async/concurrent programming techniques, it seems to me this same general idea can be simulated using nothing more than nohup and Unix pipes. For example, take the following function which just does some random piping operation enclosed in a loop, taking an argument passed to it as an identifier as to which operation is currently taking place, prepending a formatted date in front of it, and then piping the result to sed to perform a search and replace operation on the current day of the week,


#!/bin/sh
for number in `seq 1 10`
do
        echo `date "+%a %b %d %Y %T:%N"`_$1_$number | sed "s/`date '+%a'`/Fri/" -
done

Save the above into a file called “do_loop”. Now make that file executable,


chmod +x do_loop

Now create another file called “run_async_join_test” and fill it with,


#!/bin/sh
nohup ./do_loop 1 &
nohup ./do_loop 2 &
nohup ./do_loop 3 &

Now make that same file executable,


chmod +x run_async_join_test

… and then run that script,


./run_async_join_test

So how do we know what happened, and whether or not each call to the do_loop script ran asynchronously?


less nohup.out

… which will produce something similar to,


Fri Jun 03 2008 12:06:34:093829000_3_1
Fri Jun 03 2008 12:06:34:101356000_2_1
Fri Jun 03 2008 12:06:34:108742000_3_2
Fri Jun 03 2008 12:06:34:112851000_2_2
Fri Jun 03 2008 12:06:34:119344000_3_3
Fri Jun 03 2008 12:06:34:099333000_1_1
Fri Jun 03 2008 12:06:34:123482000_2_3
Fri Jun 03 2008 12:06:34:136901000_1_2
Fri Jun 03 2008 12:06:34:140938000_2_4
Fri Jun 03 2008 12:06:34:146709000_1_3
Fri Jun 03 2008 12:06:34:152805000_2_5
Fri Jun 03 2008 12:06:34:132047000_3_4
Fri Jun 03 2008 12:06:34:166683000_2_6
Fri Jun 03 2008 12:06:34:170302000_3_5
Fri Jun 03 2008 12:06:34:174037000_2_7
Fri Jun 03 2008 12:06:34:180902000_3_6
Fri Jun 03 2008 12:06:34:185055000_2_8
Fri Jun 03 2008 12:06:34:165604000_1_4
Fri Jun 03 2008 12:06:34:191628000_3_7
Fri Jun 03 2008 12:06:34:195973000_2_9
Fri Jun 03 2008 12:06:34:199629000_1_5
Fri Jun 03 2008 12:06:34:211291000_2_10
Fri Jun 03 2008 12:06:34:210545000_3_8
Fri Jun 03 2008 12:06:34:220584000_1_6
Fri Jun 03 2008 12:06:34:222941000_3_9
Fri Jun 03 2008 12:06:34:231110000_1_7
Fri Jun 03 2008 12:06:34:235546000_3_10
Fri Jun 03 2008 12:06:34:241966000_1_8
Fri Jun 03 2008 12:06:34:251812000_1_9
Fri Jun 03 2008 12:06:34:261000000_1_10

*SWEET*! The Polymorphic C# Join Pattern in a (Unix) Nutshell! :D (I smell a best seller! ;-)

Update: Before anyone else is left with the impression that I am downplaying the value of Polyphonic C# I should point out that the above is nothing more than a conceptual exercise intended to convey the general ideas behind the call/wait/continue asynchronous/concurrency programming models. In other words, this is intended as an oversimplified way to think about a much more complex topic. In other, other words, it’s a lot easier to learn complex coding techniques when we can break these techniques into byte-sized pieces using concepts we already understand (and more than likely use on a fairly regular basis) as our building blocks to extend from.

Oh, and BTW… If you want a *really* killer tutorial and C# async library to begin playing with immediately, take a look at http://tomasp.net/blog/csharp-async.aspx, a resource I’ve learned a tremendous amount of valuable information from. In fact, in case you find it useful, I extended TomasP’s library slightly, adding the ability to specify the return type of a given async method call by passing in the desired return type as a parameter.

Extended library: http://nuxleus.googlecode.com/svn/trunk/nuxleus/Source/Nuxleus.Extension.Linq/Async.cs

(the extended portions: The ReturnType enum. The additional ReadToEndAsync extension method which takes a ReturnType enum value as a parameter.)

Example usage: http://nuxleus.googlecode.com/svn/trunk/nuxleus/Source/CodeSamples/HttpGetRequestAsyncWorkflow_Test/Program.cs