Software Transactional Memory and F#

Since I have a rather long commute to and from work, I have the opportunity to get caught up on all sorts of podcasts and such.  Very recently, I listened to the DotNetRocks Episode 310 with Simon Peyton Jones on Haskell and Functional Programming.  It seems that Carl and Richard are definitely on a functional programming trip, and I think Scott Hanselman has joined the group as well with his shows on Hanselminutes.  Since I've been learning F# and such I thought this show was well worth a listen, and I was right.

Simon Peyton Jones is currently working on a few things including the a Haskell compiler, Glasgow Haskell Compiler (GHC) and C--

Haskell

If you're not familiar with Haskell, it is a purely functional programming language, unlike F# which allows for imperative and functional programming in the same language.  The GHC is one of the more popular Haskell compilers out there today.  Much like every other language out there today, there are a couple, although inactive, Haskell .NET compilers out there including Hugs98 for .NET using the Hugs98 compiler, and Modrian using the GHC.

Let's walk through a simple example of computing a factorial in one line:

fac n = if n > 0 then n * fac (n-1) else 1

As you can see from the above line, we create a function that keeps recursing itself until it hits 1. 

Now, let's look at a simple version in the Hugs98 for .NET for a simple console application:

main = do
  obj <- new "System.Object"
  x   <- obj # invoke "GetHashCode" ()
  print ("The hash code is: " ++ show (x::Int))

Pretty slick actually...  Too bad they aren't being maintained anymore, especially with .NET 2.0 and beyond goodness.  But, if you're looking for more tutorials and such, go here for a brief demo from Simon himself.

Software Transactional Memory (STM)

One of the more interesting aspects of Simon's visit to DNR was talking about Software Transactional Memory (STM).  This has been one of Simon's projects at Microsoft Research and an interesting one at that.  STM originally came about back in the '80s, but only more practical now as many times it has failed in the past.  Think of STM being analogous to database transactions, but in shared memory for concurrent running programs.  The GHC has actually implemented this functionality and is pretty interesting.

So, what does this offer us?  Well, with this scheme proposed in their paper, you can take two operations and combine them to be atomic.  In the past, it was unclear when and how they should attempt to re-execute the transaction should it fail.  So, in turn, Simon's group put in a retry keyword which uses a transaction log that determines the memory that was read and then automatically retries it and changes that piece of memory.  They also implemented the orElse keyword which brings an alternative in should the transaction fail the first time, then the alternative is run.

You can read more about Simon's group's research paper here.

STM in F#?

So, this is really cool stuff, but can we have this in .NET?  Greg Neverov has indeed written a library called Software Transactional Memory for F# which is available on hubFS.  What's interesting is that the low level goo for the STM is actually written in C# using the Monitor class with method calls to Enter, Wait, Exit and PulseAll.  So, I guess you could call this library from C# as well to do concurrent programming, but that's more of F#'s gig.

Here's a simple example using this:

let enqueue queue item =
  stm { let! used = readTVar queue.used
        return! if used < queue.len
                then stm { let! head = readTVar queue.head
                           do! writeTVar queue.a.[(head+used) % queue.len] item
                           return! writeTVar queue.used (used+1) }
                else retry () }

So, download it today and check it out.  There may be performance implications of using this code instead of just the standard Monitor.Enter and so on, but I've yet to check that out.

Conclusion

I barely scratched the surface once again on this and the possibilities.  You could easily imagine using this in heavy concurrent applications touching static data and shared memory.  A lot of these things give me the idea about the strength and power of F# and .NET languages as a whole.  .NET is rapidly evolving before our eyes and the possibilities of so many years ago with many languages using the same platform is really solidifying and each language has its purpose...

Until next time...

kick it on DotNetKicks.com

2 Comments

  • It is certainly possible to use the low-level STM library from C#. However it is a bit clunky to use from C# because you have to explicitly pass around the transaction state. The above example written in C# would be

    void Enqueue(T item, TLog trans)
    {
    int used = trans.ReadTVar(usedRef);
    if (used < len)
    {
    int head = trans.ReadTVar(headRef);
    trans.WriteTVar(a[(head + used) % len], item);
    trans.WriteTVar(usedRef, used + 1);
    }
    else trans.Retry();
    }


    In F#, computation expressions (aka monads) will implicitly pass the transaction log around for you so that it is completely hidden from the programmer.

    In general monads allow you to thread state through a sequence of related computational elements (in this case, the transaction log through a sequence of transacted memory read/writes) without exposing this state to the programmer.

  • Greg.

    First off, thanks for reading and thank you for the comments.

    I knew it was going to be clunky hence why I said that it was not the best approach for it. To do concurrent shared memory programming isn't C#'s strength and more plays to F#.

    Exactly on point with that code, and it's very clean. Good stuff!

    Matt

Comments have been disabled for this content.