You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by sy...@apache.org on 2015/03/01 23:32:02 UTC

[1/3] lucenenet git commit: Fix for TestDirectoryReaderReopen.TestThreadSafety

Repository: lucenenet
Updated Branches:
  refs/heads/master bdf4ec7b0 -> 9ff490365


Fix for TestDirectoryReaderReopen.TestThreadSafety

The java version uses a concurrent hash map so I updated VirtualMethod to use that.
After that change, we no longer needed the lock on the Reap() function.
Next the Get() needed to use a tryGet() and return the default if there was nothing in the collection.


Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/9b57fca6
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/9b57fca6
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/9b57fca6

Branch: refs/heads/master
Commit: 9b57fca6a6961905204f41bef1b5fe784741a58b
Parents: ac8fa48
Author: Chand2048 <Ch...@Microsoft.com>
Authored: Wed Feb 25 14:21:16 2015 -0800
Committer: Chand2048 <Ch...@Microsoft.com>
Committed: Wed Feb 25 14:21:16 2015 -0800

----------------------------------------------------------------------
 src/Lucene.Net.Core/Util/VirtualMethod.cs   |  2 +-
 src/Lucene.Net.Core/Util/WeakIdentityMap.cs | 33 +++++++++++++-----------
 2 files changed, 19 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9b57fca6/src/Lucene.Net.Core/Util/VirtualMethod.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Util/VirtualMethod.cs b/src/Lucene.Net.Core/Util/VirtualMethod.cs
index faa5a70..e21c253 100644
--- a/src/Lucene.Net.Core/Util/VirtualMethod.cs
+++ b/src/Lucene.Net.Core/Util/VirtualMethod.cs
@@ -64,7 +64,7 @@ namespace Lucene.Net.Util
         private readonly Type BaseClass;
         private readonly string Method;
         private readonly Type[] Parameters;
-        private readonly WeakIdentityMap<Type, int> Cache = WeakIdentityMap<Type, int>.NewHashMap(false);
+        private readonly WeakIdentityMap<Type, int> Cache = WeakIdentityMap<Type, int>.NewConcurrentHashMap(false);
 
         /// <summary>
         /// Creates a new instance for the given {@code baseClass} and method declaration. </summary>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9b57fca6/src/Lucene.Net.Core/Util/WeakIdentityMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Util/WeakIdentityMap.cs b/src/Lucene.Net.Core/Util/WeakIdentityMap.cs
index ee792be..e556a28 100644
--- a/src/Lucene.Net.Core/Util/WeakIdentityMap.cs
+++ b/src/Lucene.Net.Core/Util/WeakIdentityMap.cs
@@ -135,7 +135,16 @@ namespace Lucene.Net.Util
             {
                 Reap();
             }
-            return BackingStore[new IdentityWeakReference(key)];
+
+            V val;
+            if (BackingStore.TryGetValue(new IdentityWeakReference(key), out val))
+            {
+                return val;
+            }
+            else
+            {
+                return default(V);
+            }
         }
 
         /// <summary>
@@ -329,25 +338,19 @@ namespace Lucene.Net.Util
         /// <seealso cref= <a href="#reapInfo">Information about the <code>reapOnRead</code> setting</a> </seealso>
         public void Reap()
         {
-            lock (BackingStore)
+            List<IdentityWeakReference> keysToRemove = new List<IdentityWeakReference>();
+            foreach (IdentityWeakReference zombie in BackingStore.Keys)
             {
-                List<IdentityWeakReference> keysToRemove = new List<IdentityWeakReference>();
-
-                foreach (IdentityWeakReference zombie in BackingStore.Keys)
+                if (!zombie.IsAlive)
                 {
-                    if (!zombie.IsAlive)
-                        keysToRemove.Add(zombie);
-                }
-
-                foreach (var key in keysToRemove)
-                {
-                    BackingStore.Remove(key);
+                    keysToRemove.Add(zombie);
                 }
             }
-            /*while ((zombie = queue.poll()) != null)
+
+            foreach (var key in keysToRemove)
             {
-              BackingStore.Remove(zombie);
-            }*/
+                BackingStore.Remove(key);
+            }
         }
 
         // we keep a hard reference to our NULL key, so map supports null keys that never get GCed:


[2/3] lucenenet git commit: Merge remote-tracking branch 'guidotag/TestThreadSafety2'

Posted by sy...@apache.org.
Merge remote-tracking branch 'guidotag/TestThreadSafety2'


Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/3d092609
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/3d092609
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/3d092609

Branch: refs/heads/master
Commit: 3d0926099390acd908d6ab3f79c4434431792294
Parents: bdf4ec7 9b57fca
Author: Itamar Syn-Hershko <it...@code972.com>
Authored: Mon Mar 2 00:21:47 2015 +0200
Committer: Itamar Syn-Hershko <it...@code972.com>
Committed: Mon Mar 2 00:21:47 2015 +0200

----------------------------------------------------------------------
 src/Lucene.Net.Core/Util/VirtualMethod.cs   |  2 +-
 src/Lucene.Net.Core/Util/WeakIdentityMap.cs | 33 +++++++++++++-----------
 2 files changed, 19 insertions(+), 16 deletions(-)
----------------------------------------------------------------------



[3/3] lucenenet git commit: Moving some unused stuff around

Posted by sy...@apache.org.
Moving some unused stuff around


Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/9ff49036
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/9ff49036
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/9ff49036

Branch: refs/heads/master
Commit: 9ff4903653b6ca6dec0383eb09213758bd40764d
Parents: 3d09260
Author: Itamar Syn-Hershko <it...@code972.com>
Authored: Mon Mar 2 00:31:31 2015 +0200
Committer: Itamar Syn-Hershko <it...@code972.com>
Committed: Mon Mar 2 00:31:31 2015 +0200

----------------------------------------------------------------------
 src/Lucene.Net.Core/Lucene.Net.csproj           |   1 -
 src/Lucene.Net.Core/Util/VirtualMethod.cs       | 165 -------------------
 src/Lucene.Net.Core/Util/WeakIdentityMap.cs     |   2 +
 .../Lucene.Net.TestFramework.csproj             |   1 +
 .../Util/VirtualMethod.cs                       | 164 ++++++++++++++++++
 5 files changed, 167 insertions(+), 166 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9ff49036/src/Lucene.Net.Core/Lucene.Net.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Lucene.Net.csproj b/src/Lucene.Net.Core/Lucene.Net.csproj
index 41e5b32..5cfcce9 100644
--- a/src/Lucene.Net.Core/Lucene.Net.csproj
+++ b/src/Lucene.Net.Core/Lucene.Net.csproj
@@ -854,7 +854,6 @@
     <Compile Include="Util\ToStringUtils.cs" />
     <Compile Include="Util\UnicodeUtil.cs" />
     <Compile Include="Util\LuceneVersion.cs" />
-    <Compile Include="Util\VirtualMethod.cs" />
     <Compile Include="Util\WAH8DocIdSet.cs" />
     <Compile Include="Util\WeakIdentityMap.cs" />
   </ItemGroup>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9ff49036/src/Lucene.Net.Core/Util/VirtualMethod.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Util/VirtualMethod.cs b/src/Lucene.Net.Core/Util/VirtualMethod.cs
deleted file mode 100644
index e21c253..0000000
--- a/src/Lucene.Net.Core/Util/VirtualMethod.cs
+++ /dev/null
@@ -1,165 +0,0 @@
-using System.Linq;
-using Lucene.Net.Support;
-using System;
-using System.Collections.Generic;
-using System.Reflection;
-
-namespace Lucene.Net.Util
-{
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-    /// <summary>
-    /// A utility for keeping backwards compatibility on previously abstract methods
-    /// (or similar replacements).
-    /// <p>Before the replacement method can be made abstract, the old method must kept deprecated.
-    /// If somebody still overrides the deprecated method in a non-final class,
-    /// you must keep track, of this and maybe delegate to the old method in the subclass.
-    /// The cost of reflection is minimized by the following usage of this class:</p>
-    /// <p>Define <strong>static final</strong> fields in the base class ({@code BaseClass}),
-    /// where the old and new method are declared:</p>
-    /// <pre class="prettyprint">
-    ///  static final VirtualMethod&lt;BaseClass&gt; newMethod =
-    ///   new VirtualMethod&lt;BaseClass&gt;(BaseClass.class, "newName", parameters...);
-    ///  static final VirtualMethod&lt;BaseClass&gt; oldMethod =
-    ///   new VirtualMethod&lt;BaseClass&gt;(BaseClass.class, "oldName", parameters...);
-    /// </pre>
-    /// <p>this enforces the singleton status of these objects, as the maintenance of the cache would be too costly else.
-    /// If you try to create a second instance of for the same method/{@code baseClass} combination, an exception is thrown.</p>
-    /// <p>To detect if e.g. the old method was overridden by a more far subclass on the inheritance path to the current
-    /// instance's class, use a <strong>non-static</strong> field:</p>
-    /// <pre class="prettyprint">
-    ///  final boolean isDeprecatedMethodOverridden =
-    ///   oldMethod.getImplementationDistance(this.getClass()) > newMethod.getImplementationDistance(this.getClass());
-    ///
-    ///  <em>// alternatively (more readable):</em>
-    ///  final boolean isDeprecatedMethodOverridden =
-    ///   VirtualMethod.compareImplementationDistance(this.getClass(), oldMethod, newMethod) > 0
-    /// </pre>
-    /// <p><seealso cref="getImplementationDistance"/> returns the distance of the subclass that overrides this method.
-    /// The one with the larger distance should be used preferable.
-    /// this way also more complicated method rename scenarios can be handled
-    /// (think of 2.9 {@code TokenStream} deprecations).</p>
-    ///
-    /// @lucene.internal
-    /// </summary>
-    public sealed class VirtualMethod<C>
-    {
-        private static readonly ISet<MethodInfo> SingletonSet = new ConcurrentHashSet<MethodInfo>(new HashSet<MethodInfo>());
-
-        private readonly Type BaseClass;
-        private readonly string Method;
-        private readonly Type[] Parameters;
-        private readonly WeakIdentityMap<Type, int> Cache = WeakIdentityMap<Type, int>.NewConcurrentHashMap(false);
-
-        /// <summary>
-        /// Creates a new instance for the given {@code baseClass} and method declaration. </summary>
-        /// <exception cref="UnsupportedOperationException"> if you create a second instance of the same
-        ///  {@code baseClass} and method declaration combination. this enforces the singleton status. </exception>
-        /// <exception cref="IllegalArgumentException"> if {@code baseClass} does not declare the given method. </exception>
-        public VirtualMethod(Type baseClass, string method, params Type[] parameters)
-        {
-            this.BaseClass = baseClass;
-            this.Method = method;
-            this.Parameters = parameters;
-            try
-            {
-                MethodInfo mi = baseClass.GetMethod(method, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, parameters, null);
-                if (mi == null)
-                {
-                    throw new System.ArgumentException(baseClass.Name + " has no such method.");
-                }
-                else if (!SingletonSet.Add(mi))
-                {
-                    throw new System.NotSupportedException("VirtualMethod instances must be singletons and therefore " + "assigned to static final members in the same class, they use as baseClass ctor param.");
-                }
-            }
-            catch (NotSupportedException nsme)
-            {
-                throw new System.ArgumentException(baseClass.Name + " has no such method: " + nsme.Message);
-            }
-        }
-
-        /// <summary>
-        /// Returns the distance from the {@code baseClass} in which this method is overridden/implemented
-        /// in the inheritance path between {@code baseClass} and the given subclass {@code subclazz}. </summary>
-        /// <returns> 0 iff not overridden, else the distance to the base class </returns>
-        public int GetImplementationDistance(Type subclazz)
-        {
-            int distance = Cache.Get(subclazz);
-            if (distance == default(int))
-            {
-                // we have the slight chance that another thread may do the same, but who cares?
-                Cache.Put(subclazz, distance = Convert.ToInt32(ReflectImplementationDistance(subclazz)));
-            }
-            return (int)distance;
-        }
-
-        /// <summary>
-        /// Returns, if this method is overridden/implemented in the inheritance path between
-        /// {@code baseClass} and the given subclass {@code subclazz}.
-        /// <p>You can use this method to detect if a method that should normally be final was overridden
-        /// by the given instance's class. </summary>
-        /// <returns> {@code false} iff not overridden </returns>
-        public bool IsOverriddenAsOf(Type subclazz)
-        {
-            return GetImplementationDistance(subclazz) > 0;
-        }
-
-        private int ReflectImplementationDistance(Type subclazz)
-        {
-            if (!BaseClass.IsAssignableFrom(subclazz))
-            {
-                throw new System.ArgumentException(subclazz.Name + " is not a subclass of " + BaseClass.Name);
-            }
-            bool overridden = false;
-            int distance = 0;
-            for (Type clazz = subclazz; clazz != BaseClass && clazz != null; clazz = clazz.BaseType)
-            {
-                // lookup method, if success mark as overridden
-                if (!overridden)
-                {
-                    MethodInfo mi = clazz.GetMethod(Method, 
-                        BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly, 
-                        null, Parameters, null);
-
-                    if (mi != null)
-                        overridden = true;
-                }
-
-                // increment distance if overridden
-                if (overridden)
-                {
-                    distance++;
-                }
-            }
-            return distance;
-        }
-
-        /// <summary>
-        /// Utility method that compares the implementation/override distance of two methods. </summary>
-        /// <returns> <ul>
-        ///  <li>&gt; 1, iff {@code m1} is overridden/implemented in a subclass of the class overriding/declaring {@code m2}
-        ///  <li>&lt; 1, iff {@code m2} is overridden in a subclass of the class overriding/declaring {@code m1}
-        ///  <li>0, iff both methods are overridden in the same class (or are not overridden at all)
-        /// </ul> </returns>
-        public static int compareImplementationDistance<C>(Type clazz, VirtualMethod<C> m1, VirtualMethod<C> m2)
-        {
-            return Convert.ToInt32(m1.GetImplementationDistance(clazz)).CompareTo(m2.GetImplementationDistance(clazz));
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9ff49036/src/Lucene.Net.Core/Util/WeakIdentityMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Util/WeakIdentityMap.cs b/src/Lucene.Net.Core/Util/WeakIdentityMap.cs
index e556a28..aa4e1a8 100644
--- a/src/Lucene.Net.Core/Util/WeakIdentityMap.cs
+++ b/src/Lucene.Net.Core/Util/WeakIdentityMap.cs
@@ -61,6 +61,8 @@ namespace Lucene.Net.Util
     public sealed class WeakIdentityMap<K, V>
         where K : class
     {
+        // LUCENENET TODO Make this class internal as it isn't required anywhere; need to have it exposed to tests though
+
         //private readonly ReferenceQueue<object> queue = new ReferenceQueue<object>();
         private readonly IDictionary<IdentityWeakReference, V> BackingStore;
 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9ff49036/src/Lucene.Net.TestFramework/Lucene.Net.TestFramework.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Lucene.Net.TestFramework.csproj b/src/Lucene.Net.TestFramework/Lucene.Net.TestFramework.csproj
index 84c6bb1..778659d 100644
--- a/src/Lucene.Net.TestFramework/Lucene.Net.TestFramework.csproj
+++ b/src/Lucene.Net.TestFramework/Lucene.Net.TestFramework.csproj
@@ -469,6 +469,7 @@
     <Compile Include="JavaCompatibility\LuceneTestCase.cs" />
     <Compile Include="JavaCompatibility\LuceneTypesHelpers.cs" />
     <Compile Include="JavaCompatibility\SystemTypesHelpers.cs" />
+    <Compile Include="Util\VirtualMethod.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\Lucene.Net.Core\Lucene.Net.csproj">

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/9ff49036/src/Lucene.Net.TestFramework/Util/VirtualMethod.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.TestFramework/Util/VirtualMethod.cs b/src/Lucene.Net.TestFramework/Util/VirtualMethod.cs
new file mode 100644
index 0000000..319efaa
--- /dev/null
+++ b/src/Lucene.Net.TestFramework/Util/VirtualMethod.cs
@@ -0,0 +1,164 @@
+using Lucene.Net.Support;
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Lucene.Net.Util
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// A utility for keeping backwards compatibility on previously abstract methods
+    /// (or similar replacements).
+    /// <p>Before the replacement method can be made abstract, the old method must kept deprecated.
+    /// If somebody still overrides the deprecated method in a non-final class,
+    /// you must keep track, of this and maybe delegate to the old method in the subclass.
+    /// The cost of reflection is minimized by the following usage of this class:</p>
+    /// <p>Define <strong>static final</strong> fields in the base class ({@code BaseClass}),
+    /// where the old and new method are declared:</p>
+    /// <pre class="prettyprint">
+    ///  static final VirtualMethod&lt;BaseClass&gt; newMethod =
+    ///   new VirtualMethod&lt;BaseClass&gt;(BaseClass.class, "newName", parameters...);
+    ///  static final VirtualMethod&lt;BaseClass&gt; oldMethod =
+    ///   new VirtualMethod&lt;BaseClass&gt;(BaseClass.class, "oldName", parameters...);
+    /// </pre>
+    /// <p>this enforces the singleton status of these objects, as the maintenance of the cache would be too costly else.
+    /// If you try to create a second instance of for the same method/{@code baseClass} combination, an exception is thrown.</p>
+    /// <p>To detect if e.g. the old method was overridden by a more far subclass on the inheritance path to the current
+    /// instance's class, use a <strong>non-static</strong> field:</p>
+    /// <pre class="prettyprint">
+    ///  final boolean isDeprecatedMethodOverridden =
+    ///   oldMethod.getImplementationDistance(this.getClass()) > newMethod.getImplementationDistance(this.getClass());
+    ///
+    ///  <em>// alternatively (more readable):</em>
+    ///  final boolean isDeprecatedMethodOverridden =
+    ///   VirtualMethod.compareImplementationDistance(this.getClass(), oldMethod, newMethod) > 0
+    /// </pre>
+    /// <p><seealso cref="getImplementationDistance"/> returns the distance of the subclass that overrides this method.
+    /// The one with the larger distance should be used preferable.
+    /// this way also more complicated method rename scenarios can be handled
+    /// (think of 2.9 {@code TokenStream} deprecations).</p>
+    ///
+    /// @lucene.internal
+    /// </summary>
+    public sealed class VirtualMethod<C>
+    {
+        private static readonly ISet<MethodInfo> SingletonSet = new ConcurrentHashSet<MethodInfo>(new HashSet<MethodInfo>());
+
+        private readonly Type BaseClass;
+        private readonly string Method;
+        private readonly Type[] Parameters;
+        private readonly WeakIdentityMap<Type, int> Cache = WeakIdentityMap<Type, int>.NewConcurrentHashMap(false);
+
+        /// <summary>
+        /// Creates a new instance for the given {@code baseClass} and method declaration. </summary>
+        /// <exception cref="UnsupportedOperationException"> if you create a second instance of the same
+        ///  {@code baseClass} and method declaration combination. this enforces the singleton status. </exception>
+        /// <exception cref="IllegalArgumentException"> if {@code baseClass} does not declare the given method. </exception>
+        public VirtualMethod(Type baseClass, string method, params Type[] parameters)
+        {
+            this.BaseClass = baseClass;
+            this.Method = method;
+            this.Parameters = parameters;
+            try
+            {
+                MethodInfo mi = baseClass.GetMethod(method, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, parameters, null);
+                if (mi == null)
+                {
+                    throw new System.ArgumentException(baseClass.Name + " has no such method.");
+                }
+                else if (!SingletonSet.Add(mi))
+                {
+                    throw new System.NotSupportedException("VirtualMethod instances must be singletons and therefore " + "assigned to static final members in the same class, they use as baseClass ctor param.");
+                }
+            }
+            catch (NotSupportedException nsme)
+            {
+                throw new System.ArgumentException(baseClass.Name + " has no such method: " + nsme.Message);
+            }
+        }
+
+        /// <summary>
+        /// Returns the distance from the {@code baseClass} in which this method is overridden/implemented
+        /// in the inheritance path between {@code baseClass} and the given subclass {@code subclazz}. </summary>
+        /// <returns> 0 iff not overridden, else the distance to the base class </returns>
+        public int GetImplementationDistance(Type subclazz)
+        {
+            int distance = Cache.Get(subclazz);
+            if (distance == default(int))
+            {
+                // we have the slight chance that another thread may do the same, but who cares?
+                Cache.Put(subclazz, distance = Convert.ToInt32(ReflectImplementationDistance(subclazz)));
+            }
+            return (int)distance;
+        }
+
+        /// <summary>
+        /// Returns, if this method is overridden/implemented in the inheritance path between
+        /// {@code baseClass} and the given subclass {@code subclazz}.
+        /// <p>You can use this method to detect if a method that should normally be final was overridden
+        /// by the given instance's class. </summary>
+        /// <returns> {@code false} iff not overridden </returns>
+        public bool IsOverriddenAsOf(Type subclazz)
+        {
+            return GetImplementationDistance(subclazz) > 0;
+        }
+
+        private int ReflectImplementationDistance(Type subclazz)
+        {
+            if (!BaseClass.IsAssignableFrom(subclazz))
+            {
+                throw new System.ArgumentException(subclazz.Name + " is not a subclass of " + BaseClass.Name);
+            }
+            bool overridden = false;
+            int distance = 0;
+            for (Type clazz = subclazz; clazz != BaseClass && clazz != null; clazz = clazz.BaseType)
+            {
+                // lookup method, if success mark as overridden
+                if (!overridden)
+                {
+                    MethodInfo mi = clazz.GetMethod(Method, 
+                        BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly, 
+                        null, Parameters, null);
+
+                    if (mi != null)
+                        overridden = true;
+                }
+
+                // increment distance if overridden
+                if (overridden)
+                {
+                    distance++;
+                }
+            }
+            return distance;
+        }
+
+        /// <summary>
+        /// Utility method that compares the implementation/override distance of two methods. </summary>
+        /// <returns> <ul>
+        ///  <li>&gt; 1, iff {@code m1} is overridden/implemented in a subclass of the class overriding/declaring {@code m2}
+        ///  <li>&lt; 1, iff {@code m2} is overridden in a subclass of the class overriding/declaring {@code m1}
+        ///  <li>0, iff both methods are overridden in the same class (or are not overridden at all)
+        /// </ul> </returns>
+        public static int compareImplementationDistance<C>(Type clazz, VirtualMethod<C> m1, VirtualMethod<C> m2)
+        {
+            return Convert.ToInt32(m1.GetImplementationDistance(clazz)).CompareTo(m2.GetImplementationDistance(clazz));
+        }
+    }
+}
\ No newline at end of file