I recently needed to create a set of classes that was the combinatorial
expansion of several implementation flavors of two independent sets of methods. Why I needed
combinatorial expansion is not that interesting but the solution is. What I came
up with is a way of supporting a form of
mixin's in C#.
Lets take the methods,
void Lock();
bool Unlock();
bool Locked { get; }
If you call Lock(), Locked
returns true, until you call Unlock(). Also Unlock()
returns true if the object is now unlocked. There are several
implementations I can think of for these methods, one uses a Boolean value and
doesn't support nested calls to Lock():
I am sure you have already thought of at least one more. Now I have four
possible implementations (including yours), which is the correct one? Unfortunately, that depends
on how the locking is going to be used. If I know I will never need nested
locks, only taking space for a Boolean makes sense. If I know I will need to
support nested locks then the int seems like a
good choice. If it is going to be used in a multi-threaded application I should
probably use the thread-safe version. I now have two choices, pick one
implementation or pass it the implementation as a parameter. Picking one
implementation is easy, just copy of of the above implementation into the class; but how do you efficiently pass an implementation as a
parameter?
From now on I will refer to each implementation as a locking policy. What I
want is an efficient way to pass the locking policy to a set of classes. Most obvious way is to
write a class for each policy and pass the policy
as a parameter to each instance. This might look something like,
Unfortunately, this has, on average, 36 bytes of overhead per instance on
a 32 bit machine (more on 64). This seems a bit much for such a policy and picking just one
implementation, even one too general for the average application, starts
looking like a better alternative. We must be able to do better than this.
Since passing the implementation as a parameter to the instances is
expensive, why not try to pass the implementation to the class instead? In order
to do that we need use a type parameter. What we want is something like,
class LockableObject<LockingPolicy> {
private LockingPolicy _lockingPolicy = new LockingPolicy();
publicvoid Lock() {
_lockingPolicy.Lock();
}
publicbool Unlock() {
return _lockingPolicy.Unlock();
}
publicbool Locked {
get { return _lockingPolicy.Locked; }
}
}
In other words, we need to passing a class and delegate the implementation to
that class. This does not look significantly better than the previous
implementation, however, because we are new'ing up an instance and assigning it
to an instance variable which, as before, consumes a minimum of 36 bytes per
instance. But if LockingPolicy is a struct instead
of a class then it will only add the size of the
struct to the LockableObject instance
size. In other words, we would only be taking space for either a bool
or an int. The size overhead looks good, now how
about the delegation? In order to call methods on LockingPolicy the
LockingPolicystruct must implement
an interface. It cannot be an abstractclass because all structs
are sealed and cannot be inherited from. The interface for the locking policy is fairly straight
forward and looks like,
We now need to add a where clause to the LockableObject
class so we can call the methods provided by the struct's methods. The modified LockableObject
class looks like,
class LockableObject<LockingPolicy>
where LockingPolicy : struct, ILockingPolicy
{
private LockingPolicy _lockingPolicy = new LockingPolicy();
publicvoid Lock() {
_lockingPolicy.Lock();
}
publicbool Unlock() {
return _lockingPolicy.Unlock();
}
publicbool Locked {
get { return _lockingPolicy.Locked; }
}
}
The LockableObject can now be instantiated like,
var lockableObject = new LockableObject<SimpleLockPolicy>();
for a lockable object that uses the Boolean implementation. To use the
counted locking policy you would construct the object like,
var lockableObject = new LockableObject<CountedLockPolicy>();
The space consumption looks good but the delegation looks expensive it call
through an interface which is a virtual. But since we are using
structs, which are sealed, the
call through the interface can be made static
and then be a candidate for inlining. In fact,
this is what happens in retail builds when not debugging. This is not entirely
free however since there the runtime doesn't inline twice. Implementing
Lock() directly instead of through delegation means the Lock()
method can be inlined, removing the call entirely, the delegated version inlines
the delegation but it still generates a call.
This mechanism for C# mixins is not as convenient as languages that support
multiple inheritance, because we have to manually delegate to the policy, but it
is just as efficient as we will see demonstrated more clearly in some of the
next entries.
I did something almost exactly like this recently, except I used a static member for my 'policy' (I called it a 'provider'). This means you only use 36 bytes (assuming class here) per _type_ and nothing per instance.
Thanks for pointing out the use of static fields. I sometimes get caught up in the solutiont that I forget the problem. If you have a case where you don't need per-instance data, using a class static is a good approach. This wouldn't work for my example, however, since I wanted an instance lock, not a class lock.
This is definitly inspired by Alexandrescu's policies.
I have typically seen this pattern used when reference counting some resource. You could imagine a server connection cache implemented using a lock to as a reference count. But, as you intimate, this is rather contrived example. It was intended to demonstrate the technique, not be useful in itself.
C# Mixins - Sort of
I recently needed to create a set of classes that was the combinatorial expansion of several implementation flavors of two independent sets of methods. Why I needed combinatorial expansion is not that interesting but the solution is. What I came up with is a way of supporting a form of mixin's in C#.
Lets take the methods,
If you call
Lock(),Lockedreturnstrue, until you callUnlock(). AlsoUnlock()returnstrueif the object is now unlocked. There are several implementations I can think of for these methods, one uses a Boolean value and doesn't support nested calls toLock():Another uses an integer value to count the number of nested calls to
Lock()and it remains locked until a matching number ofUnlock()calls are made.This isn't thread safe so we could provide a relatively thread-safe version in,
I am sure you have already thought of at least one more. Now I have four possible implementations (including yours), which is the correct one? Unfortunately, that depends on how the locking is going to be used. If I know I will never need nested locks, only taking space for a Boolean makes sense. If I know I will need to support nested locks then the
intseems like a good choice. If it is going to be used in a multi-threaded application I should probably use the thread-safe version. I now have two choices, pick one implementation or pass it the implementation as a parameter. Picking one implementation is easy, just copy of of the above implementation into the class; but how do you efficiently pass an implementation as a parameter?From now on I will refer to each implementation as a locking policy. What I want is an efficient way to pass the locking policy to a set of classes. Most obvious way is to write a class for each policy and pass the policy as a parameter to each instance. This might look something like,
Unfortunately, this has, on average, 36 bytes of overhead per instance on a 32 bit machine (more on 64). This seems a bit much for such a policy and picking just one implementation, even one too general for the average application, starts looking like a better alternative. We must be able to do better than this.
Since passing the implementation as a parameter to the instances is expensive, why not try to pass the implementation to the class instead? In order to do that we need use a type parameter. What we want is something like,
In other words, we need to passing a
classand delegate the implementation to thatclass. This does not look significantly better than the previous implementation, however, because we are new'ing up an instance and assigning it to an instance variable which, as before, consumes a minimum of 36 bytes per instance. But ifLockingPolicyis astructinstead of aclassthen it will only add the size of thestructto theLockableObjectinstance size. In other words, we would only be taking space for either aboolor anint. The size overhead looks good, now how about the delegation? In order to call methods onLockingPolicytheLockingPolicystructmust implement an interface. It cannot be anabstractclassbecause allstructs are sealed and cannot be inherited from. The interface for the locking policy is fairly straight forward and looks like,An implementation of the Boolean locking policy looks like,
The counted locking policy looks like,
We now need to add a
whereclause to theLockableObjectclass so we can call the methods provided by thestruct's methods. The modifiedLockableObjectclass looks like,The
LockableObjectcan now be instantiated like,for a lockable object that uses the Boolean implementation. To use the counted locking policy you would construct the object like,
The space consumption looks good but the delegation looks expensive it call through an interface which is a virtual. But since we are using
structs, which aresealed, the call through theinterfacecan be made static and then be a candidate for inlining. In fact, this is what happens in retail builds when not debugging. This is not entirely free however since there the runtime doesn't inline twice. ImplementingLock()directly instead of through delegation means theLock()method can be inlined, removing the call entirely, the delegated version inlines the delegation but it still generates a call.This mechanism for C# mixins is not as convenient as languages that support multiple inheritance, because we have to manually delegate to the policy, but it is just as efficient as we will see demonstrated more clearly in some of the next entries.
11:42 PM | Comments [4] | #Programming
07/07/2007 9:40 AM
I did something almost exactly like this recently, except I used a static member for my 'policy' (I called it a 'provider'). This means you only use 36 bytes (assuming class here) per _type_ and nothing per instance.Looks like it would work here too.
BrandonFurtwangler | mailto:brandfAT NOSPAMmicrosoft dot com | brandfAT NOSPAMmicrosoft dot com
07/09/2007 2:29 PM
Er... why would you want to use locking in a single-threaded program? I can't come up with a scenario.As for the actual point of the article [grin], it's good to see how Alexandrescu's policies can be (even partially) implemented in C# too.
Marcel Popescu | mailto:mdpopescuAT NOSPAMgmail dot com | mdpopescuAT NOSPAMgmail dot com
07/10/2007 12:39 PM
Brandon,Thanks for pointing out the use of static fields. I sometimes get caught up in the solutiont that I forget the problem. If you have a case where you don't need per-instance data, using a class static is a good approach. This wouldn't work for my example, however, since I wanted an instance lock, not a class lock.
Chuck.
Chuck Jazdzewski | www.removingalldoubt.com | chuckjAT NOSPAMmicrosoft dot com
07/10/2007 12:43 PM
Marcel,This is definitly inspired by Alexandrescu's policies.
I have typically seen this pattern used when reference counting some resource. You could imagine a server connection cache implemented using a lock to as a reference count. But, as you intimate, this is rather contrived example. It was intended to demonstrate the technique, not be useful in itself.
Chuck.
Chuck Jazdzewski | www.removingalldoubt.com | chuckjAT NOSPAMmicrosoft dot com