Add [Category ("NotWorking")] to failing test.
[mono.git] / mcs / class / corlib / System.Threading / CancellationTokenSource.cs
index b6668313257f441cc1d86ad94bf7345c49ca1c5f..b82e49f59bfb751b810a4406af15003b593f7152 100644 (file)
@@ -26,7 +26,7 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#if NET_4_0 || MOBILE
+#if NET_4_0
 using System.Collections.Generic;
 using System.Collections.Concurrent;
 
@@ -126,6 +126,8 @@ namespace System.Threading
                        canceled = true;
                        
                        handle.Set ();
+                       if (linkedTokens != null)
+                               UnregisterLinkedTokens ();
                        
                        List<Exception> exceptions = null;
                        
@@ -158,6 +160,17 @@ namespace System.Threading
                                throw new AggregateException (exceptions);
                }
 
+               /* This is the callback registered on linked tokens
+                * so that they don't throw an ODE if the callback
+                * is called concurrently with a Dispose
+                */
+               void SafeLinkedCancel ()
+               {
+                       try {
+                               Cancel ();
+                       } catch (ObjectDisposedException) {}
+               }
+
 #if NET_4_5
                public void CancelAfter (TimeSpan delay)
                {
@@ -199,7 +212,7 @@ namespace System.Threading
                                throw new ArgumentException ("Empty tokens array");
 
                        CancellationTokenSource src = new CancellationTokenSource ();
-                       Action action = src.Cancel;
+                       Action action = src.SafeLinkedCancel;
                        var registrations = new List<CancellationTokenRegistration> (tokens.Length);
 
                        foreach (CancellationToken token in tokens) {
@@ -255,11 +268,11 @@ namespace System.Threading
 
                void UnregisterLinkedTokens ()
                {
-                       if (linkedTokens == null)
+                       var registrations = Interlocked.Exchange (ref linkedTokens, null);
+                       if (registrations == null)
                                return;
-                       foreach (var linked in linkedTokens)
+                       foreach (var linked in registrations)
                                linked.Dispose ();
-                       linkedTokens = null;
                }
                
                internal CancellationTokenRegistration Register (Action callback, bool useSynchronizationContext)