You've already forked linux-packaging-mono
Imported Upstream version 4.2.2.29
Former-commit-id: f069081cc0821095435a845c961ae61cbbc95121
This commit is contained in:
@@ -170,6 +170,32 @@ namespace System
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Based on the Boyer–Moore string search algorithm */
|
||||
int LastIndexOf (Delegate[] haystack, Delegate[] needle)
|
||||
{
|
||||
if (haystack.Length < needle.Length)
|
||||
return -1;
|
||||
|
||||
if (haystack.Length == needle.Length) {
|
||||
for (int i = 0; i < haystack.Length; ++i)
|
||||
if (!haystack [i].Equals (needle [i]))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = haystack.Length - needle.Length, j; i >= 0;) {
|
||||
for (j = 0; needle [j].Equals (haystack [i]); ++i, ++j) {
|
||||
if (j == needle.Length - 1)
|
||||
return i - j;
|
||||
}
|
||||
|
||||
i -= j + 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected sealed override Delegate RemoveImpl (Delegate value)
|
||||
{
|
||||
if (value == null)
|
||||
@@ -210,42 +236,23 @@ namespace System
|
||||
return ret;
|
||||
} else {
|
||||
/* wild case : remove MulticastDelegate from MulticastDelegate
|
||||
* complexity is O(m * n), with n the number of elements in
|
||||
* 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;
|
||||
if (delegates.Equals (other.delegates))
|
||||
return null;
|
||||
|
||||
/* 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];
|
||||
}
|
||||
int idx = LastIndexOf (delegates, other.delegates);
|
||||
if (idx == -1)
|
||||
return this;
|
||||
|
||||
/* 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);
|
||||
MulticastDelegate ret = AllocDelegateLike_internal (this);
|
||||
ret.delegates = new Delegate [delegates.Length - other.delegates.Length];
|
||||
|
||||
if (count == 0)
|
||||
return null;
|
||||
|
||||
if (count == 1)
|
||||
return ret.delegates [0];
|
||||
|
||||
if (count != delegates.Length)
|
||||
Array.Resize (ref ret.delegates, count);
|
||||
Array.Copy (delegates, ret.delegates, idx);
|
||||
Array.Copy (delegates, idx + other.delegates.Length, ret.delegates, idx, delegates.Length - idx - other.delegates.Length);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@@ -35,6 +35,25 @@ namespace MonoTests.System.Threading
|
||||
[TestFixture]
|
||||
public class ThreadPoolTests
|
||||
{
|
||||
int minWorkerThreads;
|
||||
int minCompletionPortThreads;
|
||||
int maxWorkerThreads;
|
||||
int maxCompletionPortThreads;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp ()
|
||||
{
|
||||
ThreadPool.GetMinThreads (out minWorkerThreads, out minCompletionPortThreads);
|
||||
ThreadPool.GetMaxThreads (out maxWorkerThreads, out maxCompletionPortThreads);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown ()
|
||||
{
|
||||
ThreadPool.SetMinThreads (minWorkerThreads, minCompletionPortThreads);
|
||||
ThreadPool.SetMaxThreads (maxWorkerThreads, maxCompletionPortThreads);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RegisterWaitForSingleObject_InvalidArguments ()
|
||||
{
|
||||
@@ -99,5 +118,85 @@ namespace MonoTests.System.Threading
|
||||
Assert.IsTrue (ev.Wait (3000));
|
||||
}
|
||||
#endif
|
||||
|
||||
[Test]
|
||||
public void SetAndGetMinThreads ()
|
||||
{
|
||||
int workerThreads, completionPortThreads;
|
||||
int workerThreads_new, completionPortThreads_new;
|
||||
|
||||
ThreadPool.GetMinThreads (out workerThreads, out completionPortThreads);
|
||||
Assert.IsTrue (workerThreads > 0, "#1");
|
||||
Assert.IsTrue (completionPortThreads > 0, "#2");
|
||||
|
||||
workerThreads_new = workerThreads == 1 ? 2 : 1;
|
||||
completionPortThreads_new = completionPortThreads == 1 ? 2 : 1;
|
||||
ThreadPool.SetMinThreads (workerThreads_new, completionPortThreads_new);
|
||||
|
||||
ThreadPool.GetMinThreads (out workerThreads, out completionPortThreads);
|
||||
Assert.IsTrue (workerThreads == workerThreads_new, "#3");
|
||||
Assert.IsTrue (completionPortThreads == completionPortThreads_new, "#4");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetAndGetMaxThreads ()
|
||||
{
|
||||
int cpuCount = Environment.ProcessorCount;
|
||||
int workerThreads, completionPortThreads;
|
||||
int workerThreads_new, completionPortThreads_new;
|
||||
|
||||
ThreadPool.GetMaxThreads (out workerThreads, out completionPortThreads);
|
||||
Assert.IsTrue (workerThreads > 0, "#1");
|
||||
Assert.IsTrue (completionPortThreads > 0, "#2");
|
||||
|
||||
workerThreads_new = workerThreads == cpuCount ? cpuCount + 1 : cpuCount;
|
||||
completionPortThreads_new = completionPortThreads == cpuCount ? cpuCount + 1 : cpuCount;
|
||||
ThreadPool.SetMaxThreads (workerThreads_new, completionPortThreads_new);
|
||||
|
||||
ThreadPool.GetMaxThreads (out workerThreads, out completionPortThreads);
|
||||
Assert.IsTrue (workerThreads == workerThreads_new, "#3");
|
||||
Assert.IsTrue (completionPortThreads == completionPortThreads_new, "#4");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetAvailableThreads ()
|
||||
{
|
||||
ManualResetEvent mre = new ManualResetEvent (false);
|
||||
DateTime start = DateTime.Now;
|
||||
int i, workerThreads, completionPortThreads;
|
||||
|
||||
try {
|
||||
Assert.IsTrue (ThreadPool.SetMaxThreads (Environment.ProcessorCount, Environment.ProcessorCount));
|
||||
|
||||
while (true) {
|
||||
ThreadPool.GetAvailableThreads (out workerThreads, out completionPortThreads);
|
||||
if (workerThreads == 0)
|
||||
break;
|
||||
|
||||
if ((DateTime.Now - start).TotalSeconds >= 10)
|
||||
Assert.Fail ("did not reach 0 available threads");
|
||||
|
||||
ThreadPool.QueueUserWorkItem (GetAvailableThreads_Callback, mre);
|
||||
Thread.Sleep (1);
|
||||
}
|
||||
} finally {
|
||||
mre.Set ();
|
||||
}
|
||||
}
|
||||
|
||||
void GetAvailableThreads_Callback (object state)
|
||||
{
|
||||
ManualResetEvent mre = (ManualResetEvent) state;
|
||||
|
||||
if (mre.WaitOne (0))
|
||||
return;
|
||||
|
||||
ThreadPool.QueueUserWorkItem (GetAvailableThreads_Callback, mre);
|
||||
ThreadPool.QueueUserWorkItem (GetAvailableThreads_Callback, mre);
|
||||
ThreadPool.QueueUserWorkItem (GetAvailableThreads_Callback, mre);
|
||||
ThreadPool.QueueUserWorkItem (GetAvailableThreads_Callback, mre);
|
||||
|
||||
mre.WaitOne ();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user