Groovy dynamic stateful mixins

My last post was dedicated to Groovy dynamic stateless mixins. Today I want to talk about stateful ones, which are now presented in Groovy trunk.
The main difference is obvious – additionally to providing new method stateful mixins can also keep state.

Here is non-trivial sample. First of all let us use EMC to add convinient method to JDK class ReentrantLock.

ReentrantLock.metaClass {
  withLock { Closure operation ->
     lock ()
     try {
        operation ()
     }
     finally {
       unlock ()
     }
  }
}

Now we are able to implement Groovy ConcurrentQueue like this


class ConcurrentQueue {
   private LinkedList list = new LinkedList ()
   private ReentrantLock lock = new ReentrantLock ()

   def get () {
      lock.withLock () {
        list.removeFirst ()
      }
   }

   void put (def obj) {
      lock.withLock () {
         list.addLast (obj)
      }
   }
}

So far, we didn’t use any mixins. Let us rewrite last sample using ones


class ConcurrentQueue {
   static {
     ConcurrentQueue.metaClass.mixin LinkedList, ReentrantLock
   }

   def get () {
      withLock {
        removeFirst ()
      }
   }

   void put (def obj) {
      withLock {
         addLast (obj)
      }
   }
}

What we did is we replace private fields with mixins, which we assign in static initialization of the class. Of course, this sample is a little bit artificial because what we do is emulating compile time mixins with static initializer. I will discuss compile time mixins separately but now let us modify our sample to be more dynamic.


        def queue = new Object ()
        queue.metaClass {
            mixin LinkedList, ReentrantLock

            get { ->
               withLock {
                 removeFirst ()
               }
            }

            put { obj ->
               withLock {
                  addLast (obj)
               }
            }
        }

Instead of creating special class for our concurrent queue we use combination of mixin and per instance meta class to create what we need. Isn’t it lovely?

Now you may wish to ask me several interesting question, which I try to answer below.

How to access instance of mixed-in object if needed? Well, it is very easy. Let us add one more method to implementation of our queue, which will demonstrate how to do that.


        queue.metaClass {
            duplicateEachElement {
               withLock {
                  LinkedList newList = new LinkedList ()
                  mixedIn[LinkedList].each {
                     newList << it
                     newList << it
                  }
                  mixedIn[LinkedList] = newList
               }
            }
        }

How to access owner object from mixed-in instance if needed? This is a little bit more tricky. To understand why is it so we need to understand how mixins are implemented. Obviously, where is no magic here – mixed in references kept separately from objects in weakly referenced map. It means that if mixed in instance keeps reference to owner, then owner has zero chances to be collected. So in the perfect world mixed in instance should never keep reference for owner. But in pragmatic world it might make sense to do it time to time. Here is example how to do that


class NoDuplicateCollection {
    void put (def obj) {
        def clone = (mixinOwner as Collection).find {
            it == obj
        }

        if (!clone)
          mixinOwner.add obj
    }
}

def list = new Object ()
list.metaClass.mixin NoDuplicateCollection, LinkedList

list.put 1
list.put 1
list.put 2
list.put 2
list.put 3
list.put 3

assertEquals (3, list.size ())
assertEquals 1, list [0]
assertEquals 2, list [1]
assertEquals 3, list [2]

NoDuplicateCollection class designed to be used with any JDK Collection as owner. In example above we use it with LinkedList but any other Set or List will work as well. Property ‘mixinOwner’ is magically (via delegating per instance meta class) inserted in to instance of NoDuplicateCollection and… Voila! Of course, internally mixedOwner is week reference so it will not prevent owner from being collected.

One more interesting thing to notice is ‘as operator’ used to cast our object to Collection. Yes, it is true – we cast instance of Object to Collection. Again, there is no magic here – if our object can’t be casted itself we try mixed-ins. Simple as that.

Enjoy it in the Groovy 1.6 trunk

About these ads

One Response to Groovy dynamic stateful mixins

  1. [...] – bookmarked by 5 members originally found by Rstyle44 on 2008-10-24 Groovy dynamic stateful mixins http://groovyland.wordpress.com/2008/07/09/groovy-dynamic-stateful-mixins/ – bookmarked by 6 [...]

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: