in progress…

April 3, 2023

… 10 Years Later, lets Mix it up

Filed under: Uncategorized — Mark Falco @ 3:10 am

Yawn, it’s been awhile.

So the other day I was was getting annoyed that Java still doesn’t have mixins (stateful interfaces), so I figured I’d see what I could do about it.

With Java 8’s default methods we get surprisingly close as we can have multiple inheritance of behavior but still not of state. A few times I’ve done quasi-mixins where my “mixin” interface expects help from the class which incorporates it. This is done by having the incorporating class implement some helper method(s) to expose the necessary state. I’ve never felt good about making any of the incorporating classes part of any public API though as exposing the internal state of the mixin felt rather ugly. Things only get worse when you try to incorporate multiple mixins into the same class now you have to add multiple sets of helpers for each class being incorporated and it becomes a bit of a mess.

So the other day I started working to find a pattern with the primary goal being that incorporation of one or more mixins would be trivial. After all the entire point of mixins is to make it easy to provide additional functionality to a class, so the less requirements on the “user” the better. At the same time I wanted to come up with a pattern which was also very easy for the mixin developer to follow. Simply put it should be easy to write mixins and even easier to use them.

I’m revising my blog after a decades long break so clearly I’m rather happy with the end result.

Let’s start from the user’s perspective and see what it looks like to incorporate a mixin. Our example mixin will simply introduce 64 bit identity hash-codes to objects. Let’s call the mixin IdentityMixin and assume it has a single method getIdentity. So what does it look like to incorporate it into a class?

class SomeClass extends Mixin.Base implements IdentityMixin {
}

Well that was quite easy, to “incorporate” a mixin you just declare that you implement the corresponding interface. But clearly there is more going on here, and clearly I kinda cheated by extending a helper class Mixin.Base. Using this helper base class is nice, but sometimes not an option, i.e. when you already extend some class which you don’t own. So lets move onto a more complicated example:

class SomeDerivedClass extends SomeoneElsesBaseClass implements IdentityMixin {
    protected final Mixin.State mixin = Mixin.State.of(this);
    public State mixin() {
        return mixin;
    }
}

And that is as painful as it ever gets for the incorporating class. Regardless of how many mixins they incorporate those four extra lines of copy-paste boiler plate is all that is needed. Let me repeat to make that clear, it isn’t four lines per incorporated mixin, it is just those exact four lines, period. Of course we need some example, so let’s add a FavoriteColorMixin imagining that it has getFavoriteColor and setFavoriteColor methods.

class SomeDerivedClass extends SomeoneElsesBaseClass implements IdentityMixin, FavoriteColorMixin {
    protected final Mixin.State mixin = Mixin.State.of(this);
    public State mixin() {
        return mixin;
    }
}

Nice! after the first incorporation adding more mixins just requires declaring that you implement them.

And of course usage of a class that has incorporated mixins is as you would expect.

SomeDerivedClass derived = new SomeDerivedClass();
long identity = derived.getIdentity();
Color color = derived.getFavoriteColor();
derived.setFavoriteColor(Color.GREEN);

So now that we’ve seen how to incorporate mixins, what does it look like to write one. Well lets write the two example ones from above.

interface IdentityMixin extends Mixin {
    default long getIdentity() {
        return mixin(State.class).identity;
    }

    final class State extends Mixin.State {
        private static final AtomicLong COUNTER = new AtomicLong();
        private final long identity = COUNTER.incrementAndGet();
    }
}
interface FavoriteColorMixin extends Mixin {
    default Color getFavoriteColor() {
        return mixin(State.class).favorite;
    }

    default void setFavoriteColor(Color color) {
        mixin(State.class).favorite = color;
    }

    final class State extends Mixin.State {
        private Color favorite;
    }
}

It should be easy enough to follow what is going on here. Each mixin class extends my base Mixin interface and has an inner class named State which extends my Mixin.State base class. For each instance of a class which incorporates these mixins there will be State objects (one for each mixin) and those can be obtained via mixin(Class<? extends State> clzState) which itself is a default method on the base Mixin interface.

Note that while these State classes are public, their contents can/should be private, thus even if externally obtained they are useless to all but their corresponding mixin.

State classes aren’t special in any way other then that they extend from Mixin.State. So all the normal Java facilities are of course there, i.e. finals, volatiles, statics, methods… they are just classes.

Also note that the State classes are declared as final, this is not technically a requirement but extending of a mixin’s State class is ill-advised and introduces the classic “diamond problem”. That is not to say that one mixin cannot extend another, they just each need to have their own independent State class.

Lets extend FavoriteColorMixin adding in a shade.

interface ShadeMixin extends FavoriteColorMixin {
    default Shade getShade() {
        return mixin(State.class).shade;
    }

    default void setShade(Shade shade) {
        return mixin(State.class).shade = shade;
    }

    default String describe() {
        return getShade() + " " + getColor();
    }

    final class State extends Mixin.State {
        private Shade shade;
    }
}

Ok, so you get the idea. It should be clear that it is trivial to incorporate mixins, and easy enough to author new ones. Now how does this work, i.e. where are all those states stored? Obviously the key is the single field and method which an incorporating class must include, but how does that work, and specifically how does it work when you incorporate multiple mixins?

It really all comes down to the Mixin.State.of(Mixin target) method, i.e. the method used to initialize that one helper field. What this static helper method does is inspect target.getClass(), reflect to find all the interfaces it directly or indirectly implements which extend Mixin, and then for each of those interfaces it reflects to find their inner class which extends Mixin.State. It then builds a “plan” for how to represent such a mixin and stores this all in a ClassValue key’d on target.getClass()‘s type. So all that reflection is a once per incorporating class cost. Then when Mixin.State.of(this) is run it just allocates a Mixin.State according to its “plan”.

Ok, there was a lot in that paragraph. A couple of key questions need to be answered, what is this “plan”, and how do we make use of it. I’ll answer the second question first.

The Mixin interface has two methods Mixin.State mixin() which as seen above is normally implemented by the incorporating class and simply returns the helper field which was allocated by Mixin.State.of(this). There is a second method on Mixin which then uses the first method in order to lookup the proper state for a given mixin.

default <S extends Mixin.State> mixin(Class<S> clzState) {
    return mixin().of(clzState);
}

Umm, ok, so we use the user defined mixin() helper to call an of(Class<State> clzState) method defined on Mixin.State. This is feeling rather cyclical. Don’t worry we’re almost done. So what we’ve done here ask the state to provide the state, or more precisely we’ve asked incorpratingClass.mixin to provide the state for one of the potentially many Mixins it incorporates. And what is the default implementation of Mixin.State.of(Class<State> clzState)?

<S extends State> S of(Class<S> clzState) {
    return (S) this;
}

Umm again, it just returns itself? Yes, but like I said that is the default implementation, i.e. the one which is used when a class only incorporates a single mixin. Simply put when a class incorporates one mixin that mixin’s State object is stored directly in the helper Mixin.State field on the incorporating class.

Things get more interesting when multiple classes are incorporated. In that case we need need to map clzState to the proper derived State. When we allocated our state in the first place we’d used a plan based on the incorporating class’s type and if the class had incorporated multiple mixins then the plan would output a Mixin.State which is internally backed by a HashMap<Class<Mixin.State>, Mixin.State>, allowing us to lookup the desired state as follows:

<S extends State> S of(Class<S> clzState) {
    return (S) map.get(clzState);
}

And that is pretty much it. The map is fully populated when the incorporating class instance is constructed it is then read-only, and hence thread-safe for the remainder of the life of the incorporating object and we’re done.

Ok we’re not done, that last bit of code is a dramatic oversimplification of what I actually do, but it is equivalent to what I do.

There are a few problems with the map approach. While the lookup is O(1), it is perhaps overly costly when the number of incorporations is small (the expected case), and also a bit memory hungry as each incorporating object would have an embedded HashMap which intern has a Map.Entry[] (which is larger then the number of incorporations) as well as a Map.Entry for each incorporation.

Since I clearly like describing things in reverse order, let’s tackle the HashMap per incorporating object solution first. Rather than having a HashMap<Class<State>, State> per object, I instead maintain an HashMap<Class<State>, Integer> per incorporating class. That is, in our earlier example SomeDerivedClass is maintaining (via a ClassValue) a static read-only HashMap which can be used by all instances of that class. The value portion of that map is an Integer which is used as an index into an Mixin.State[] which is allocated on a per object basis, and that array’s size exactly matches the number of mixins incorporated for that class. So the real of(Class<S> clzState) is actually:

public <S extends State> S of(Class<S> clzState) {
    return (S) states[indexMap.get(clzState)];
}

Here states is the Mixin.State[] referencing a per object array, and indexMap references a per class HashMap. This approach lowers the memory overhead to just a small (perfectly sized) array per object rather than paying the cost of the full on map. The map just serves as a way to lookup the appropriate index within the array. Oh and those Integers are shared as well as they will all be smallish values and come from the JVM’s Integer.valueOf pool.

Ok, almost done. The last problem to address is with regards to the cost of calling indexMap.get. While O(1) and quite cheap, it will still be overkill for the common case of classes which only incorporate a small number of mixins. As we’ve seen when we only incorporate a single mixin we avoid the map entirely, but we can actually so something similar when we incorporate a small number of mixins as well. Basically it would be cheaper to just scan over the array then to use the indexMap when we have say less then eight incorporations. So then we could forgo the indexMap lookup and just do:

public <S extends State> S of(Class<S> clzState) {
    for (S state : states) {
        if (clzState == state.getClass()) {
            return (S) state;
        }
    }
    throw new IllegalArgumentException();
}

Performance testing does show that this is faster than a map lookup for sizes 2..8, and shortly after that it becomes more expensive. But once again this isn’t the actual implementation, I go a bit further and optimize out the array as well. Hey, why not save an extra object, as well as the corresponding bounds checks. The real non-map 2..8 mixin solution looks like:

protected <S extends State> S of(Class<S> clzState) {                                       
    return (S) (clzState == class0 ? state0 
               : clzState == class1 ? state1 
               : clzState == class2 ? state2 
               : clzState == class3 ? state3 
               : clzState == class4 ? state4 
               : clzState == class5 ? state5 
               : clzState == class6 ? state6 
               :                      state7);
}                                       

Yup, that is faster than the indexMap, and as least as fast as the array, and doesn’t add any garbage. Note that I have two sets of fields here, classN and stateN, rather then checking clzState == classN I could have just checked clzState == stateN.getClass(), which would save me some fields but that would also mean that as I scanned over the pseudo-array I’d have to navigate into each stateN object and each of those would risk a cache miss in a real system, so I’m willing to inflate the size of my anchor Mixin.State object a bit for speed. Actually, I’m not that willing, thus when creating the “plans” I produce something like the above with state counts of 2, 4, and 8, so the actual waste is minimized further while still maintaining the speed.

Ok, I think that’s it. I think I’ve got a easy to use pattern with some helpers that makes it efficient both in terms of CPU and memory šŸ™‚

You can download the full implementation here: https://github.com/xtclang/jmixin

That was fun, see you again in 2033.

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.