Update more 4.5 api
authorMarek Safar <marek.safar@gmail.com>
Fri, 8 Jun 2012 10:44:55 +0000 (11:44 +0100)
committerMarek Safar <marek.safar@gmail.com>
Fri, 8 Jun 2012 10:44:55 +0000 (11:44 +0100)
mcs/class/System.Core/System.Threading/ReaderWriterLockSlim.cs
mcs/class/System.Threading.Tasks.Dataflow/System.Threading.Tasks.Dataflow.dll.sources
mcs/class/System.Threading.Tasks.Dataflow/System.Threading.Tasks.Dataflow_test.dll.sources
mcs/class/System.Threading.Tasks.Dataflow/System.Threading.Tasks/ConcurrentExclusiveSchedulerPair.cs [deleted file]
mcs/class/System.Threading.Tasks.Dataflow/Test/System.Threading.Tasks/ConcurrentExclusiveSchedulerPairTest.cs [deleted file]
mcs/class/System.XML/System.Xml.Serialization/XmlRootAttribute.cs
mcs/class/System.XML/System.Xml.Xsl/XslTransform.cs
mcs/class/corlib/System.Threading.Tasks/ConcurrentExclusiveSchedulerPair.cs [new file with mode: 0644]
mcs/class/corlib/Test/System.Threading.Tasks/ConcurrentExclusiveSchedulerPairTest.cs [new file with mode: 0644]
mcs/class/corlib/corlib.dll.sources
mcs/class/corlib/corlib_test.dll.sources

index d5447eb335b5fc1a328a332c8c8b807a7e49cf82..74320c1e42911011fdee896d90bcf9adf1417faa 100644 (file)
@@ -128,7 +128,7 @@ namespace System.Threading {
                        return TryEnterReadLock (millisecondsTimeout, ref dummy);
                }
 
-               public bool TryEnterReadLock (int millisecondsTimeout, ref bool success)
+               bool TryEnterReadLock (int millisecondsTimeout, ref bool success)
                {
                        ThreadLockState ctstate = CurrentThreadState;
 
index 7b6681155a0cdeb510d95a470f8316cb13faf02c..71e9b7fc6d835a3e029a85cfcf198d8c61df3b30 100644 (file)
@@ -2,7 +2,6 @@
 ../../build/common/Locale.cs
 ../../build/common/MonoTODOAttribute.cs
 Assembly/AssemblyInfo.cs
-System.Threading.Tasks/ConcurrentExclusiveSchedulerPair.cs
 System.Threading.Tasks.Dataflow/ExecutingMessageBox.cs
 System.Threading.Tasks.Dataflow/DataflowBlockOptions.cs
 System.Threading.Tasks.Dataflow/DataflowMessageHeader.cs
index f3d2da7fc4e3e5e0af8cf5c74f56104e7b0ca829..522170cfcd0c4a7d2e33128e7f5562df6260dcb5 100644 (file)
@@ -1,4 +1,3 @@
-System.Threading.Tasks/ConcurrentExclusiveSchedulerPairTest.cs
 System.Threading.Tasks.Dataflow/DataflowMessageHeaderTest.cs
 System.Threading.Tasks.Dataflow/CompletionHelperTest.cs
 ../System.Threading.Tasks.Dataflow/CompletionHelper.cs
diff --git a/mcs/class/System.Threading.Tasks.Dataflow/System.Threading.Tasks/ConcurrentExclusiveSchedulerPair.cs b/mcs/class/System.Threading.Tasks.Dataflow/System.Threading.Tasks/ConcurrentExclusiveSchedulerPair.cs
deleted file mode 100644 (file)
index 5127796..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-// ConcurrentExclusiveSchedulerPair.cs
-//
-// Copyright (c) 2011 Jérémie "garuma" Laval
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-//
-
-using System;
-using System.Threading;
-using System.Collections.Generic;
-using System.Collections.Concurrent;
-
-namespace System.Threading.Tasks
-{
-       public class ConcurrentExclusiveSchedulerPair : IDisposable
-       {
-               readonly int maxConcurrencyLevel;
-               readonly int maxItemsPerTask;
-
-               readonly TaskScheduler target;
-               readonly TaskFactory factory;
-               readonly Action taskHandler;
-
-               readonly ConcurrentQueue<Task> concurrentTasks = new ConcurrentQueue<Task> ();
-               readonly ConcurrentQueue<Task> exclusiveTasks = new ConcurrentQueue<Task> ();
-
-               readonly ReaderWriterLockSlim rwl = new ReaderWriterLockSlim ();
-               readonly TaskCompletionSource<object> completion = new TaskCompletionSource<object> ();
-               readonly InnerTaskScheduler concurrent;
-               readonly InnerTaskScheduler exclusive;
-
-               int numTask;
-
-               class InnerTaskScheduler : TaskScheduler
-               {
-                       readonly ConcurrentExclusiveSchedulerPair scheduler;
-                       readonly ConcurrentQueue<Task> queue;
-
-                       public InnerTaskScheduler (ConcurrentExclusiveSchedulerPair scheduler,
-                                                      ConcurrentQueue<Task> queue)
-                       {
-                               this.scheduler = scheduler;
-                               this.queue = queue;
-                       }
-
-                       public override int MaximumConcurrencyLevel {
-                               get {
-                                       return scheduler.maxConcurrencyLevel;
-                               }
-                       }
-
-                       protected override void QueueTask (Task t)
-                       {
-                               scheduler.DoQueue (t, queue);
-                       }
-
-                       protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
-                       {
-                               if (task.Status != TaskStatus.Created)
-                                       return false;
-
-                               task.RunSynchronously (scheduler.target);
-                               return true;
-                       }
-
-                       public void Execute (Task t)
-                       {
-                               TryExecuteTask (t);
-                       }
-
-                       [MonoTODO ("Only useful for debugger support")]
-                       protected override IEnumerable<Task> GetScheduledTasks ()
-                       {
-                               throw new NotImplementedException ();
-                       }
-               }
-
-               public ConcurrentExclusiveSchedulerPair () : this (TaskScheduler.Current)
-               {
-               }
-
-               public ConcurrentExclusiveSchedulerPair (TaskScheduler taskScheduler) : this (taskScheduler, taskScheduler.MaximumConcurrencyLevel)
-               {
-               }
-
-               public ConcurrentExclusiveSchedulerPair (TaskScheduler taskScheduler, int maxConcurrencyLevel)
-                       : this (taskScheduler, maxConcurrencyLevel, -1)
-               {
-               }
-
-               public ConcurrentExclusiveSchedulerPair (TaskScheduler taskScheduler, int maxConcurrencyLevel, int maxItemsPerTask)
-               {
-                       this.target = taskScheduler;
-                       this.maxConcurrencyLevel = maxConcurrencyLevel;
-                       this.maxItemsPerTask = maxItemsPerTask;
-                       this.factory = new TaskFactory (taskScheduler);
-                       this.taskHandler = InternalTaskProcesser;
-                       this.concurrent = new InnerTaskScheduler (this, concurrentTasks);
-                       this.exclusive = new InnerTaskScheduler (this, exclusiveTasks);
-               }
-
-               public void Complete ()
-               {
-                       completion.SetResult (null);
-               }
-
-               public TaskScheduler ConcurrentScheduler {
-                       get {
-                               return concurrent;
-                       }
-               }
-
-               public TaskScheduler ExclusiveScheduler {
-                       get {
-                               return exclusive;
-                       }
-               }
-
-               public Task Completion {
-                       get {
-                               return completion.Task;
-                       }
-               }
-
-               public void Dispose ()
-               {
-                       Dispose (true);
-               }
-
-               [MonoTODO]
-               protected virtual void Dispose (bool disposing)
-               {
-               }
-
-               void DoQueue (Task task, ConcurrentQueue<Task> queue)
-               {
-                       queue.Enqueue (task);
-                       SpinUpTasks ();
-               }
-
-               void InternalTaskProcesser ()
-               {
-                       Task task;
-                       int times = 0;
-                       const int lockWaitTime = 2;
-
-                       while (!concurrentTasks.IsEmpty || !exclusiveTasks.IsEmpty) {
-                               if (maxItemsPerTask != -1 && ++times == maxItemsPerTask)
-                                       break;
-
-                               bool locked = false;
-
-                               try {
-                                       if (!concurrentTasks.IsEmpty && rwl.TryEnterReadLock (lockWaitTime)) {
-                                               locked = true;
-                                               while (concurrentTasks.TryDequeue (out task)) {
-                                                       RunTask (task);
-                                               }
-                                       }
-                               } finally {
-                                       if (locked) {
-                                               rwl.ExitReadLock ();
-                                               locked = false;
-                                       }
-                               }
-
-                               try {
-                                       if (!exclusiveTasks.IsEmpty && rwl.TryEnterWriteLock (lockWaitTime)) {
-                                               locked = true;
-                                               while (exclusiveTasks.TryDequeue (out task)) {
-                                                       RunTask (task);
-                                               }
-                                       }
-                               } finally {
-                                       if (locked) {
-                                               rwl.ExitWriteLock ();
-                                       }
-                               }
-                       }
-                       // TODO: there's a race here, task adding + spinup check may be done while here
-                       Interlocked.Decrement (ref numTask);
-               }
-
-               void SpinUpTasks ()
-               {
-                       int currentTaskNumber;
-                       do {
-                               currentTaskNumber = numTask;
-                               if (currentTaskNumber >= maxConcurrencyLevel)
-                                       return;
-                       } while (Interlocked.CompareExchange (ref numTask, currentTaskNumber + 1, currentTaskNumber) != currentTaskNumber);
-
-                       factory.StartNew (taskHandler);
-               }
-
-               void RunTask (Task task)
-               {
-                       concurrent.Execute (task);
-               }
-       }
-}
diff --git a/mcs/class/System.Threading.Tasks.Dataflow/Test/System.Threading.Tasks/ConcurrentExclusiveSchedulerPairTest.cs b/mcs/class/System.Threading.Tasks.Dataflow/Test/System.Threading.Tasks/ConcurrentExclusiveSchedulerPairTest.cs
deleted file mode 100644 (file)
index 264095d..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-//
-// ConcurrentExclusiveSchedulerPairTest.cs
-//
-// Author:
-//       Jérémie "garuma" Laval <jeremie.laval@gmail.com>
-//
-// Copyright (c) 2011 Jérémie "garuma" Laval
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-
-using NUnit.Framework;
-
-namespace MonoTests.System.Threading.Tasks
-{
-       [TestFixture]
-       public class ConcurrentExclusiveSchedulerPairTest
-       {
-               ConcurrentExclusiveSchedulerPair schedPair;
-               TaskFactory factory;
-
-               [Test]
-               public void BasicExclusiveUsageTest ()
-               {
-                       schedPair = new ConcurrentExclusiveSchedulerPair (TaskScheduler.Default, 4);
-                       factory = new TaskFactory (schedPair.ExclusiveScheduler);
-
-                       bool launched = false;
-                       factory.StartNew (() => launched = true);
-                       Thread.Sleep (600);
-
-                       Assert.IsTrue (launched);
-               }
-
-               [Test]
-               public void BasicConcurrentUsageTest ()
-               {
-                       schedPair = new ConcurrentExclusiveSchedulerPair (TaskScheduler.Default, 4);
-                       factory = new TaskFactory (schedPair.ConcurrentScheduler);
-
-                       bool launched = false;
-                       factory.StartNew (() => launched = true);
-                       Thread.Sleep (600);
-
-                       Assert.IsTrue (launched);
-               }
-
-               [Test]
-               public void ExclusiveUsageTest ()
-               {
-                       schedPair = new ConcurrentExclusiveSchedulerPair (TaskScheduler.Default, 4);
-                       factory = new TaskFactory (schedPair.ExclusiveScheduler);
-
-                       int count = 0;
-                       ManualResetEventSlim mreFinish = new ManualResetEventSlim (false);
-                       ManualResetEventSlim mreStart = new ManualResetEventSlim (false);
-
-                       factory.StartNew (() => {
-                                       mreStart.Set ();
-                                       Interlocked.Increment (ref count);
-                                       mreFinish.Wait ();
-                               });
-                       mreStart.Wait ();
-                       factory.StartNew (() => Interlocked.Increment (ref count));
-                       Thread.Sleep (100);
-
-                       Assert.AreEqual (1, count);
-                       mreFinish.Set ();
-               }
-
-               [Test]
-               public void ConcurrentUsageTest ()
-               {
-                       schedPair = new ConcurrentExclusiveSchedulerPair (TaskScheduler.Default, 4);
-                       factory = new TaskFactory (schedPair.ConcurrentScheduler);
-
-                       int count = 0;
-                       ManualResetEventSlim mreFinish = new ManualResetEventSlim (false);
-                       CountdownEvent cntd = new CountdownEvent (2);
-
-                       factory.StartNew (() => {
-                                       Interlocked.Increment (ref count);
-                                       cntd.Signal ();
-                                       mreFinish.Wait ();
-                               });
-                       factory.StartNew (() => {
-                                       Interlocked.Increment (ref count);
-                                       cntd.Signal ();
-                                       mreFinish.Wait ();
-                               });
-
-                       cntd.Wait ();
-                       Assert.AreEqual (2, count);
-                       mreFinish.Set ();
-               }
-
-               [Test]
-               public void ConcurrentUsageWithExclusiveExecutingTest ()
-               {
-                       schedPair = new ConcurrentExclusiveSchedulerPair (TaskScheduler.Default, 4);
-                       TaskFactory exclFact = new TaskFactory (schedPair.ExclusiveScheduler);
-                       TaskFactory concFact = new TaskFactory (schedPair.ConcurrentScheduler);
-
-                       int count = 0;
-                       bool exclStarted = false;
-                       ManualResetEventSlim mreStart = new ManualResetEventSlim (false);
-                       ManualResetEventSlim mreFinish = new ManualResetEventSlim (false);
-
-                       exclFact.StartNew (() => {
-                               exclStarted = true;
-                               mreStart.Set ();
-                               mreFinish.Wait ();
-                               exclStarted = false;
-                       });
-
-                       mreStart.Wait ();
-
-                       concFact.StartNew (() => Interlocked.Increment (ref count));
-                       concFact.StartNew (() => Interlocked.Increment (ref count));
-                       Thread.Sleep (100);
-
-                       Assert.IsTrue (exclStarted);
-                       Assert.AreEqual (0, count);
-                       mreFinish.Set ();
-               }
-
-               [Test]
-               public void ExclusiveUsageWithConcurrentExecutingTest ()
-               {
-                       schedPair = new ConcurrentExclusiveSchedulerPair (TaskScheduler.Default, 4);
-                       TaskFactory exclFact = new TaskFactory (schedPair.ExclusiveScheduler);
-                       TaskFactory concFact = new TaskFactory (schedPair.ConcurrentScheduler);
-
-                       int count = 0;
-                       bool started = false;
-                       ManualResetEventSlim mreStart = new ManualResetEventSlim (false);
-                       ManualResetEventSlim mreFinish = new ManualResetEventSlim (false);
-
-                       concFact.StartNew (() => {
-                               started = true;
-                               mreStart.Set ();
-                               mreFinish.Wait ();
-                               started = false;
-                       });
-
-                       mreStart.Wait ();
-
-                       exclFact.StartNew (() => Interlocked.Increment (ref count));
-                       Thread.Sleep (100);
-
-                       Assert.IsTrue (started);
-                       Assert.AreEqual (0, count);
-                       mreFinish.Set ();
-               }
-       }
-}
-
index b9dcde908ef53e7dc9090b994322d44493afc337..61f300cfb85084bb92b211f88b0d3df634dabead 100644 (file)
@@ -43,7 +43,7 @@ namespace System.Xml.Serialization
        {
                private string dataType;
                private string elementName;
-               private bool isNullable = true, isNullableSpecified;
+               private bool isNullable = true;
                private string ns;
 
                public XmlRootAttribute ()
@@ -78,15 +78,10 @@ namespace System.Xml.Serialization
                public bool IsNullable {
                        get { return isNullable; }
                        set {
-                               isNullableSpecified = true;
                                isNullable = value;
                        }
                }
-
-               public bool IsNullableSpecified {
-                       get { return isNullableSpecified; }
-               }
-
+               
                public string Namespace {
                        get { return ns; } 
                        set { ns = value; }
index 2610a90c281cddc688af728263de74cf3527b56c..1d2e0d9f7a6784885e8f6c2b95a87824ffc36c4c 100644 (file)
@@ -64,6 +64,9 @@ namespace System.Xml.Xsl {
                }\r
        }\r
 \r
+#if NET_2_0\r
+       [Obsolete]\r
+#endif\r
        public sealed class XslTransform {\r
 \r
                internal static readonly bool TemplateStackFrameError;\r
diff --git a/mcs/class/corlib/System.Threading.Tasks/ConcurrentExclusiveSchedulerPair.cs b/mcs/class/corlib/System.Threading.Tasks/ConcurrentExclusiveSchedulerPair.cs
new file mode 100644 (file)
index 0000000..8e98958
--- /dev/null
@@ -0,0 +1,273 @@
+// 
+// ConcurrentExclusiveSchedulerPair.cs
+//
+// Authors:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//       Marek Safar <marek.safar@gmail.com>
+// 
+// Copyright (c) 2011 Jérémie "Garuma" Laval
+// Copyright 2012 Xamarin, Inc (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+//
+
+#if NET_4_5
+
+using System;
+using System.Threading;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using System.Diagnostics;
+
+namespace System.Threading.Tasks
+{
+       [DebuggerDisplay ("Concurrent={ConcurrentTaskCount}, Exclusive={ExclusiveTaskCount}")]
+       [DebuggerTypeProxy (typeof (SchedulerDebuggerView))]
+       public class ConcurrentExclusiveSchedulerPair
+       {
+               sealed class SchedulerDebuggerView
+               {
+                       readonly ConcurrentExclusiveSchedulerPair owner;
+                       
+                       public SchedulerDebuggerView (ConcurrentExclusiveSchedulerPair owner)
+                       {
+                               this.owner = owner;
+                       }
+                       
+                       public IEnumerable<Task> ScheduledConcurrent {
+                               get {
+                                       return owner.concurrentTasks;
+                               }
+                       }
+                       
+                       public IEnumerable<Task> ScheduledExclusive {
+                               get {
+                                       return owner.exclusiveTasks;
+                               }
+                       }
+                       
+                       public TaskScheduler TargetScheduler {
+                               get {
+                                       return owner.target;
+                               }
+                       }
+
+               }
+               
+               readonly int maxConcurrencyLevel;
+               readonly int maxItemsPerTask;
+
+               readonly TaskScheduler target;
+               readonly TaskFactory factory;
+               readonly Action taskHandler;
+
+               readonly ConcurrentQueue<Task> concurrentTasks = new ConcurrentQueue<Task> ();
+               readonly ConcurrentQueue<Task> exclusiveTasks = new ConcurrentQueue<Task> ();
+
+               //readonly ReaderWriterLockSlim rwl = new ReaderWriterLockSlim ();
+               readonly TaskCompletionSource<object> completion = new TaskCompletionSource<object> ();
+               readonly InnerTaskScheduler concurrent;
+               readonly InnerTaskScheduler exclusive;
+
+               int numTask;
+
+               class InnerTaskScheduler : TaskScheduler
+               {
+                       readonly ConcurrentExclusiveSchedulerPair scheduler;
+                       readonly ConcurrentQueue<Task> queue;
+
+                       public InnerTaskScheduler (ConcurrentExclusiveSchedulerPair scheduler,
+                                                      ConcurrentQueue<Task> queue)
+                       {
+                               this.scheduler = scheduler;
+                               this.queue = queue;
+                       }
+                       
+                       public int TaskCount {
+                               get {
+                                       return queue.Count;
+                               }
+                       }
+
+                       public override int MaximumConcurrencyLevel {
+                               get {
+                                       return scheduler.maxConcurrencyLevel;
+                               }
+                       }
+
+                       protected internal override void QueueTask (Task t)
+                       {
+                               scheduler.DoQueue (t, queue);
+                       }
+
+                       protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
+                       {
+                               if (task.Status != TaskStatus.Created)
+                                       return false;
+
+                               task.RunSynchronously (scheduler.target);
+                               return true;
+                       }
+
+                       public void Execute (Task t)
+                       {
+                               TryExecuteTask (t);
+                       }
+
+                       [MonoTODO ("Only useful for debugger support")]
+                       protected override IEnumerable<Task> GetScheduledTasks ()
+                       {
+                               throw new NotImplementedException ();
+                       }
+               }
+
+               public ConcurrentExclusiveSchedulerPair () : this (TaskScheduler.Current)
+               {
+               }
+
+               public ConcurrentExclusiveSchedulerPair (TaskScheduler taskScheduler) : this (taskScheduler, taskScheduler.MaximumConcurrencyLevel)
+               {
+               }
+
+               public ConcurrentExclusiveSchedulerPair (TaskScheduler taskScheduler, int maxConcurrencyLevel)
+                       : this (taskScheduler, maxConcurrencyLevel, -1)
+               {
+               }
+
+               public ConcurrentExclusiveSchedulerPair (TaskScheduler taskScheduler, int maxConcurrencyLevel, int maxItemsPerTask)
+               {
+                       this.target = taskScheduler;
+                       this.maxConcurrencyLevel = maxConcurrencyLevel;
+                       this.maxItemsPerTask = maxItemsPerTask;
+                       this.factory = new TaskFactory (taskScheduler);
+                       this.taskHandler = InternalTaskProcesser;
+                       this.concurrent = new InnerTaskScheduler (this, concurrentTasks);
+                       this.exclusive = new InnerTaskScheduler (this, exclusiveTasks);
+               }
+
+               public void Complete ()
+               {
+                       completion.SetResult (null);
+               }
+
+               public TaskScheduler ConcurrentScheduler {
+                       get {
+                               return concurrent;
+                       }
+               }
+               
+               private int ConcurrentTaskCount {
+                       get {
+                               return concurrent.TaskCount;
+                       }
+               }
+
+               public TaskScheduler ExclusiveScheduler {
+                       get {
+                               return exclusive;
+                       }
+               }
+
+               private int ExclusiveTaskCount {
+                       get {
+                               return exclusive.TaskCount;
+                       }
+               }
+
+               public Task Completion {
+                       get {
+                               return completion.Task;
+                       }
+               }
+
+               void DoQueue (Task task, ConcurrentQueue<Task> queue)
+               {
+                       queue.Enqueue (task);
+                       SpinUpTasks ();
+               }
+
+               void InternalTaskProcesser ()
+               {
+                       int times = 0;
+                       const int lockWaitTime = 2;
+
+                       while (!concurrentTasks.IsEmpty || !exclusiveTasks.IsEmpty) {
+                               if (maxItemsPerTask != -1 && ++times == maxItemsPerTask)
+                                       break;
+
+                               throw new NotImplementedException ();
+/*
+                               bool locked = false;
+
+                               try {
+                                       if (!concurrentTasks.IsEmpty && rwl.TryEnterReadLock (lockWaitTime)) {
+                                               locked = true;
+                                               Task task;
+                                               while (concurrentTasks.TryDequeue (out task)) {
+                                                       RunTask (task);
+                                               }
+                                       }
+                               } finally {
+                                       if (locked) {
+                                               rwl.ExitReadLock ();
+                                               locked = false;
+                                       }
+                               }
+
+                               try {
+                                       if (!exclusiveTasks.IsEmpty && rwl.TryEnterWriteLock (lockWaitTime)) {
+                                               locked = true;
+                                               Task task;
+                                               while (exclusiveTasks.TryDequeue (out task)) {
+                                                       RunTask (task);
+                                               }
+                                       }
+                               } finally {
+                                       if (locked) {
+                                               rwl.ExitWriteLock ();
+                                       }
+                               }
+*/
+                       }
+
+                       // TODO: there's a race here, task adding + spinup check may be done while here
+                       Interlocked.Decrement (ref numTask);
+               }
+
+               void SpinUpTasks ()
+               {
+                       int currentTaskNumber;
+                       do {
+                               currentTaskNumber = numTask;
+                               if (currentTaskNumber >= maxConcurrencyLevel)
+                                       return;
+                       } while (Interlocked.CompareExchange (ref numTask, currentTaskNumber + 1, currentTaskNumber) != currentTaskNumber);
+
+                       factory.StartNew (taskHandler);
+               }
+
+               void RunTask (Task task)
+               {
+                       concurrent.Execute (task);
+               }
+       }
+}
+
+#endif
\ No newline at end of file
diff --git a/mcs/class/corlib/Test/System.Threading.Tasks/ConcurrentExclusiveSchedulerPairTest.cs b/mcs/class/corlib/Test/System.Threading.Tasks/ConcurrentExclusiveSchedulerPairTest.cs
new file mode 100644 (file)
index 0000000..ebcab0e
--- /dev/null
@@ -0,0 +1,180 @@
+//
+// ConcurrentExclusiveSchedulerPairTest.cs
+//
+// Author:
+//       Jérémie "garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2011 Jérémie "garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#if NET_4_5
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+using NUnit.Framework;
+
+namespace MonoTests.System.Threading.Tasks
+{
+       [TestFixture]
+       [Ignore ("Not implemented yet")]
+       public class ConcurrentExclusiveSchedulerPairTest
+       {
+               ConcurrentExclusiveSchedulerPair schedPair;
+               TaskFactory factory;
+
+               [Test]
+               public void BasicExclusiveUsageTest ()
+               {
+                       schedPair = new ConcurrentExclusiveSchedulerPair (TaskScheduler.Default, 4);
+                       factory = new TaskFactory (schedPair.ExclusiveScheduler);
+
+                       bool launched = false;
+                       factory.StartNew (() => launched = true);
+                       Thread.Sleep (600);
+
+                       Assert.IsTrue (launched);
+               }
+
+               [Test]
+               public void BasicConcurrentUsageTest ()
+               {
+                       schedPair = new ConcurrentExclusiveSchedulerPair (TaskScheduler.Default, 4);
+                       factory = new TaskFactory (schedPair.ConcurrentScheduler);
+
+                       bool launched = false;
+                       factory.StartNew (() => launched = true);
+                       Thread.Sleep (600);
+
+                       Assert.IsTrue (launched);
+               }
+
+               [Test]
+               public void ExclusiveUsageTest ()
+               {
+                       schedPair = new ConcurrentExclusiveSchedulerPair (TaskScheduler.Default, 4);
+                       factory = new TaskFactory (schedPair.ExclusiveScheduler);
+
+                       int count = 0;
+                       ManualResetEventSlim mreFinish = new ManualResetEventSlim (false);
+                       ManualResetEventSlim mreStart = new ManualResetEventSlim (false);
+
+                       factory.StartNew (() => {
+                                       mreStart.Set ();
+                                       Interlocked.Increment (ref count);
+                                       mreFinish.Wait ();
+                               });
+                       mreStart.Wait ();
+                       factory.StartNew (() => Interlocked.Increment (ref count));
+                       Thread.Sleep (100);
+
+                       Assert.AreEqual (1, count);
+                       mreFinish.Set ();
+               }
+
+               [Test]
+               public void ConcurrentUsageTest ()
+               {
+                       schedPair = new ConcurrentExclusiveSchedulerPair (TaskScheduler.Default, 4);
+                       factory = new TaskFactory (schedPair.ConcurrentScheduler);
+
+                       int count = 0;
+                       ManualResetEventSlim mreFinish = new ManualResetEventSlim (false);
+                       CountdownEvent cntd = new CountdownEvent (2);
+
+                       factory.StartNew (() => {
+                                       Interlocked.Increment (ref count);
+                                       cntd.Signal ();
+                                       mreFinish.Wait ();
+                               });
+                       factory.StartNew (() => {
+                                       Interlocked.Increment (ref count);
+                                       cntd.Signal ();
+                                       mreFinish.Wait ();
+                               });
+
+                       cntd.Wait ();
+                       Assert.AreEqual (2, count);
+                       mreFinish.Set ();
+               }
+
+               [Test]
+               public void ConcurrentUsageWithExclusiveExecutingTest ()
+               {
+                       schedPair = new ConcurrentExclusiveSchedulerPair (TaskScheduler.Default, 4);
+                       TaskFactory exclFact = new TaskFactory (schedPair.ExclusiveScheduler);
+                       TaskFactory concFact = new TaskFactory (schedPair.ConcurrentScheduler);
+
+                       int count = 0;
+                       bool exclStarted = false;
+                       ManualResetEventSlim mreStart = new ManualResetEventSlim (false);
+                       ManualResetEventSlim mreFinish = new ManualResetEventSlim (false);
+
+                       exclFact.StartNew (() => {
+                               exclStarted = true;
+                               mreStart.Set ();
+                               mreFinish.Wait ();
+                               exclStarted = false;
+                       });
+
+                       mreStart.Wait ();
+
+                       concFact.StartNew (() => Interlocked.Increment (ref count));
+                       concFact.StartNew (() => Interlocked.Increment (ref count));
+                       Thread.Sleep (100);
+
+                       Assert.IsTrue (exclStarted);
+                       Assert.AreEqual (0, count);
+                       mreFinish.Set ();
+               }
+
+               [Test]
+               public void ExclusiveUsageWithConcurrentExecutingTest ()
+               {
+                       schedPair = new ConcurrentExclusiveSchedulerPair (TaskScheduler.Default, 4);
+                       TaskFactory exclFact = new TaskFactory (schedPair.ExclusiveScheduler);
+                       TaskFactory concFact = new TaskFactory (schedPair.ConcurrentScheduler);
+
+                       int count = 0;
+                       bool started = false;
+                       ManualResetEventSlim mreStart = new ManualResetEventSlim (false);
+                       ManualResetEventSlim mreFinish = new ManualResetEventSlim (false);
+
+                       concFact.StartNew (() => {
+                               started = true;
+                               mreStart.Set ();
+                               mreFinish.Wait ();
+                               started = false;
+                       });
+
+                       mreStart.Wait ();
+
+                       exclFact.StartNew (() => Interlocked.Increment (ref count));
+                       Thread.Sleep (100);
+
+                       Assert.IsTrue (started);
+                       Assert.AreEqual (0, count);
+                       mreFinish.Set ();
+               }
+       }
+}
+
+#endif
\ No newline at end of file
index 212fd2bb4af23b762dfd7958573730dedd0dc13e..15d3ef043a6ab8306d968952618c2b62d1bc95b1 100644 (file)
@@ -1566,6 +1566,7 @@ System/Converter.cs
 System/Predicate.cs
 System.Collections.Generic/Comparer.cs
 
+System.Threading.Tasks/ConcurrentExclusiveSchedulerPair.cs
 System.Threading.Tasks/TaskFactory.cs
 System.Threading.Tasks/TaskFactory_T.cs
 System.Threading.Tasks/TaskStatus.cs
index 66997062e59d43228a68e279b85edab76e949df9..0d908407a4c03a93fceded2b9fe80982e215a99f 100644 (file)
@@ -444,6 +444,7 @@ System.Threading/ExecutionContextCas.cs
 System.Threading/MutexCas.cs
 System.Threading/ThreadCas.cs
 System.Threading/WaitHandleCas.cs
+System.Threading.Tasks/ConcurrentExclusiveSchedulerPairTest.cs
 System.Threading.Tasks/TaskTest.cs
 System.Threading.Tasks/Task_T_Test.cs
 System.Threading.Tasks/TaskSchedulerTest.cs