May 2nd, 2014

Locked Tight

Meanwhile, back in the wonderful world of Java:

Java allows you to declare classes inside of classes. Those classes have access to the internal protected members of each other, which is a handy way of circumventing the absence of "friend" classes when you've got a group of related classes that actually need access to those protected members. And it allows me to hide away any of those inner classes that I choose so that other classes in and out of the package can't get access to them.

So what's that good for?

Well, enforcing locking of objects, for one thing.

Let's assume an outer object that other classes will want to use. In this example, we'll call it a Thing. The Thing object itself is immutable so that it cannot be changed, but it contains an inner class, Thing.Mutable, that contains all of the methods that can change a Thing. This will be important in a moment.

The Thing object also contains an inner class, Thing.Lock, that can be used to acquire either a read or a write lock on a Thing. Each Thing has a unique ThingID that can be used to look up a Thing when it is passed to the Thing.Lock class, which will provide access to either a Thing or a Thing.Mutable depending on whether the user requested a read lock or a write lock. Internally, a Thing is stored as a Thing.Mutable, but we'll cast the reference to a Thing before handing it to the user if they've gotten a read lock. (Yes, they could cast the Thing back to a Thing.Mutable, but if they do that, then I cannot help them. :) )

The only way to gain access to a Thing is to use the Thing.Lock class to acquire a read or a write lock. Of course, all of those Things need to be stored somewhere. Thus, the Thing class has another inner class, which is the Thing.Catalog and which holds all of the Things. This class is protected so that you can't access it from outside the Thing class.

The Thing.Catalog class is immutable, but -- like the Thing class! -- it contains an inner Thing.Catalog.Mutable class and a Thing.Catalog.Lock class. In this particular implementation, the Thing.Catalog is a singleton, so there's only one instance in the application that holds all of the Things.

So let's add a new Thing to the Thing.Catalog. All we do is create a new Thing and call its catalog() method. Since the catalog() method is internal to Thing, it can access the protected Thing.Catalog and obtain a Thing.Catalog.Lock for writing, giving access to the Thing.Catalog.Mutable. This allows us to add the new entity to the Thing.Catalog without ever exposing the Thing.Catalog to an external user -- because if we did expose the Thing.Catalog, then an external user could look up a Thing without getting a lock on the Thing simultaneously. And that would be bad, even if they did have to use the Thing.Catalog.Lock to do it. :)

The happy news is that these objects can inherit most of the locking code from an abstract base class, so you don't have to write a lot of new code in any given Thing to support this. My Thing class is in a file that's only about 275 lines long (with lots of blank lines for readability, but not yet any Javadocs), despite having five different inner (or inner inner) classes.

And it does what I want it to do, which is also happy news.