Imported Upstream version 4.2.0.179

Former-commit-id: 4610231f55806d2a05ed69e5ff3faa7336cc1479
This commit is contained in:
Xamarin Public Jenkins
2015-08-26 07:17:56 -04:00
committed by Jo Shields
parent aa7da660d6
commit c042cd0c52
7507 changed files with 90259 additions and 657307 deletions

View File

@@ -43,8 +43,7 @@ namespace System
[StructLayout (LayoutKind.Sequential)]
public abstract class MulticastDelegate : Delegate
{
MulticastDelegate prev;
MulticastDelegate kpm_next;
Delegate[] delegates;
protected MulticastDelegate (object target, string method)
: base (target, method)
@@ -61,13 +60,18 @@ namespace System
base.GetObjectData (info, context);
}
protected sealed override object DynamicInvokeImpl (object[] args)
{
if (prev != null)
prev.DynamicInvokeImpl (args);
return base.DynamicInvokeImpl (args);
if (delegates == null) {
return base.DynamicInvokeImpl (args);
} else {
object r;
int i = 0, len = delegates.Length;
do {
r = delegates [i].DynamicInvoke (args);
} while (++i < len);
return r;
}
}
// <remarks>
@@ -83,19 +87,21 @@ namespace System
if (d == null)
return false;
MulticastDelegate this_prev = this.prev;
MulticastDelegate obj_prev = d.prev;
do {
if (this_prev == null)
return obj_prev == null;
if (!this_prev.Compare (obj_prev))
if (delegates == null && d.delegates == null) {
return true;
} else if (delegates == null ^ d.delegates == null) {
return false;
} else {
if (delegates.Length != d.delegates.Length)
return false;
this_prev = this_prev.prev;
obj_prev = obj_prev.prev;
} while (true);
for (int i = 0; i < delegates.Length; ++i) {
if (!delegates [i].Equals (d.delegates [i]))
return false;
}
return true;
}
}
//
@@ -112,27 +118,10 @@ namespace System
// </summary>
public sealed override Delegate[] GetInvocationList ()
{
MulticastDelegate d;
d = (MulticastDelegate) this.Clone ();
for (d.kpm_next = null; d.prev != null; d = d.prev)
d.prev.kpm_next = d;
if (d.kpm_next == null) {
MulticastDelegate other = (MulticastDelegate) d.Clone ();
other.prev = null;
other.kpm_next = null;
return new Delegate [1] { other };
}
var list = new List<Delegate> ();
for (; d != null; d = d.kpm_next) {
MulticastDelegate other = (MulticastDelegate) d.Clone ();
other.prev = null;
other.kpm_next = null;
list.Add (other);
}
return list.ToArray ();
if (delegates != null)
return (Delegate[]) delegates.Clone ();
else
return new Delegate[1] { this };
}
// <summary>
@@ -146,91 +135,30 @@ namespace System
if (follow == null)
return this;
MulticastDelegate combined, orig, clone;
MulticastDelegate other = (MulticastDelegate) follow;
if (this.GetType() != follow.GetType ())
throw new ArgumentException (Locale.GetText ("Incompatible Delegate Types. First is {0} second is {1}.", this.GetType ().FullName, follow.GetType ().FullName));
MulticastDelegate ret = AllocDelegateLike_internal (this);
combined = (MulticastDelegate)follow.Clone ();
combined.SetMulticastInvoke ();
if (delegates == null && other.delegates == null) {
ret.delegates = new Delegate [2] { this, other };
} else if (delegates == null) {
ret.delegates = new Delegate [1 + other.delegates.Length];
for (clone = combined, orig = ((MulticastDelegate)follow).prev; orig != null; orig = orig.prev) {
clone.prev = (MulticastDelegate)orig.Clone ();
clone = clone.prev;
ret.delegates [0] = this;
Array.Copy (other.delegates, 0, ret.delegates, 1, other.delegates.Length);
} else if (other.delegates == null) {
ret.delegates = new Delegate [delegates.Length + 1];
Array.Copy (delegates, 0, ret.delegates, 0, delegates.Length);
ret.delegates [ret.delegates.Length - 1] = other;
} else {
ret.delegates = new Delegate [delegates.Length + other.delegates.Length];
Array.Copy (delegates, 0, ret.delegates, 0, delegates.Length);
Array.Copy (other.delegates, 0, ret.delegates, delegates.Length, other.delegates.Length);
}
clone.SetMulticastInvoke ();
clone.prev = (MulticastDelegate)this.Clone ();
for (clone = clone.prev, orig = this.prev; orig != null; orig = orig.prev) {
clone.prev = (MulticastDelegate)orig.Clone ();
clone = clone.prev;
}
return combined;
}
private bool BaseEquals (MulticastDelegate value)
{
return base.Equals (value);
}
/*
* Perform a slightly crippled version of
* Knuth-Pratt-Morris over MulticastDelegate chains.
* Border values are set as pointers in kpm_next;
* Generally, KPM border arrays are length n+1 for
* strings of n. This one works with length n at the
* expense of a few additional comparisions.
*/
private static MulticastDelegate KPM (MulticastDelegate needle, MulticastDelegate haystack,
out MulticastDelegate tail)
{
MulticastDelegate nx, hx;
// preprocess
hx = needle;
nx = needle.kpm_next = null;
do {
while ((nx != null) && (!nx.BaseEquals (hx)))
nx = nx.kpm_next;
hx = hx.prev;
if (hx == null)
break;
nx = nx == null ? needle : nx.prev;
if (hx.BaseEquals (nx))
hx.kpm_next = nx.kpm_next;
else
hx.kpm_next = nx;
} while (true);
// match
MulticastDelegate match = haystack;
nx = needle;
hx = haystack;
do {
while (nx != null && !nx.BaseEquals (hx)) {
nx = nx.kpm_next;
match = match.prev;
}
nx = nx == null ? needle : nx.prev;
if (nx == null) {
// bingo
tail = hx.prev;
return match;
}
hx = hx.prev;
} while (hx != null);
tail = null;
return null;
return ret;
}
protected sealed override Delegate RemoveImpl (Delegate value)
@@ -238,41 +166,87 @@ namespace System
if (value == null)
return this;
// match this with value
MulticastDelegate head, tail;
head = KPM ((MulticastDelegate)value, this, out tail);
if (head == null)
MulticastDelegate other = (MulticastDelegate) value;
if (delegates == null && other.delegates == null) {
/* if they are not equal and the current one is not
* a multicastdelegate then we cannot delete it */
return this.Equals (other) ? null : this;
} else if (delegates == null) {
foreach (var d in other.delegates) {
if (this.Equals (d))
return null;
}
return this;
} else if (other.delegates == null) {
int idx = Array.LastIndexOf (delegates, other);
if (idx == -1)
return this;
// duplicate chain without head..tail
MulticastDelegate prev = null, retval = null, orig;
for (orig = this; (object)orig != (object)head; orig = orig.prev) {
MulticastDelegate clone = (MulticastDelegate)orig.Clone ();
if (prev != null)
prev.prev = clone;
else
retval = clone;
prev = clone;
}
for (orig = tail; (object)orig != null; orig = orig.prev) {
MulticastDelegate clone = (MulticastDelegate)orig.Clone ();
if (prev != null)
prev.prev = clone;
else
retval = clone;
prev = clone;
}
if (prev != null)
prev.prev = null;
if (delegates.Length <= 1) {
/* delegates.Length should never be equal or
* lower than 1, it should be 2 or greater */
throw new InvalidOperationException ();
}
return retval;
if (delegates.Length == 2)
return delegates [idx == 0 ? 1 : 0];
MulticastDelegate ret = AllocDelegateLike_internal (this);
ret.delegates = new Delegate [delegates.Length - 1];
Array.Copy (delegates, ret.delegates, idx);
Array.Copy (delegates, idx + 1, ret.delegates, idx, delegates.Length - idx - 1);
return ret;
} else {
/* wild case : remove MulticastDelegate from MulticastDelegate
* complexity is O(m * n), with n the number of elements in
* this.delegates and m the number of elements in other.delegates */
MulticastDelegate ret = AllocDelegateLike_internal (this);
ret.delegates = new Delegate [delegates.Length];
/* we should use a set with O(1) lookup complexity
* but HashSet is implemented in System.Core.dll */
List<Delegate> other_delegates = new List<Delegate> ();
for (int i = 0; i < other.delegates.Length; ++i)
other_delegates.Add (other.delegates [i]);
int idx = delegates.Length;
/* we need to remove elements from the end to the beginning, as
* the addition and removal of delegates behaves like a stack */
for (int i = delegates.Length - 1; i >= 0; --i) {
/* if delegates[i] is not in other_delegates,
* then we can safely add it to ret.delegates
* otherwise we remove it from other_delegates */
if (!other_delegates.Remove (delegates [i]))
ret.delegates [--idx] = delegates [i];
}
/* the elements are at the end of the array, we
* need to move them back to the beginning of it */
int count = delegates.Length - idx;
Array.Copy (ret.delegates, idx, ret.delegates, 0, count);
if (count == 0)
return null;
if (count == 1)
return ret.delegates [0];
if (count != delegates.Length)
Array.Resize (ref ret.delegates, count);
return ret;
}
}
public static bool operator == (MulticastDelegate d1, MulticastDelegate d2)
{
if (d1 == null)
return d2 == null;
return d2 == null;
return d1.Equals (d2);
}
@@ -280,7 +254,7 @@ namespace System
{
if (d1 == null)
return d2 != null;
return !d1.Equals (d2);
}
}