Saturday, June 30, 2012

Synchronized (promise) queues in Clojure

I've mentioned to a few people at work recently that my favourite built in library in python is the queue. The reasons being that the idea is simple, the interface is simple, and you can do all sorts of amazing things with it. We use it as the basis for turning our asynchronous automation interface into a synchronous one and it essentially provides the entire basis for our regression test suite.

In fact, I like it so much I've decided to write it in clojure

sync-q

There's instructions there about how to use it in your own applications

The idea started back when I was reading Clojure Programming and discovered promises that came in with clojure 1.3.0.

Promises are essentially empty boxes for you to put stuff in. When you want to read from a promise you will block until the promise has a value

(def p (promise))

@p ;; This will block until we have a value

(deliver p :hello)

@p
:hello

(realized? p) ;; has the promise got a value? 
true 

From this point on that promise isn't available for delivering to as it already has a value.

This makes it very easy to implement python's queue class. You just need something that behaves like a queue and fill it with promises.

creating a new queue becomes creating a queue with one promise in it.

putting an item onto the queue becomes delivering to the item at the front of the queue then adding a new promise to the end.

getting is just as simple as getting the item at the front of the queue.

The downside is you need special functions to get the size of the queue and emptiness as you only count promises that have been realised

The first version took a couple of hours and was fun, it will be great to know if anyone makes use of it.

2 comments:

  1. 'promise' is a feature of clojure I wasn't aware of. Thanks for bringing it to my attention. As a recent user of Python queues, I can see how this will be useful to the clojure community. Good work!

    ReplyDelete
  2. Hi Matty

    just want to say, that I added your blog to Planet Clojure. Please, continue to use 'clojure' label in future, so your posts will be translated to Planet automatically

    ReplyDelete