Merge pull request #93 from konrad-kruczynski/dispatcher_timer_fix
[mono.git] / mcs / class / corlib / System.Threading / CancellationToken.cs
index f54c0b29ff288cff4819c70cc157d666f8c0cd58..87dabbeea292fc8c7b8f2274915bed13486851cd 100644 (file)
@@ -1,22 +1,21 @@
-#if NET_4_0
-// 
+//
 // CancellationToken.cs
-//  
+//
 // Author:
 //       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
-// 
+//
 // Copyright (c) 2009 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
 
 using System;
 using System.Threading;
-using System.Collections.Generic;
 
+#if NET_4_0 || MOBILE
 namespace System.Threading
 {
+       [System.Diagnostics.DebuggerDisplay ("IsCancellationRequested = {IsCancellationRequested}")]
        public struct CancellationToken
        {
+               bool canBeCanceled;
+               bool initialized;
+               CancellationTokenSource source;
+
                public CancellationToken (bool canceled)
+                       : this ()
                {
-                       // dummy, this is actually set by CancellationTokenSource when the token is created
-                       Source = null;
+                       initialized = true;
+                       canBeCanceled = canceled;
+                       // This is correctly set later if token originates from a Source
+                       source = canceled ? CancellationTokenSource.CanceledSource : CancellationTokenSource.NoneSource;
+               }
+
+               public static CancellationToken None {
+                       get {
+                               return CancellationTokenSource.NoneSource.Token;
+                       }
                }
-               
+
                public CancellationTokenRegistration Register (Action callback)
                {
                        return Register (callback, false);
                }
-               
-               public CancellationTokenRegistration Register (ICancelableOperation cancelable)
-               {
-                       return Register (cancelable, false);
-               }
-               
+
                public CancellationTokenRegistration Register (Action callback, bool useSynchronizationContext)
                {
                        if (callback == null)
                                throw new ArgumentNullException ("callback");
-                       
+
                        return Source.Register (callback, useSynchronizationContext);
                }
-               
+
                public CancellationTokenRegistration Register (Action<object> callback, object state)
                {
                        return Register (callback, state, false);
                }
-               
-               public CancellationTokenRegistration Register (ICancelableOperation cancelable, bool useSynchronizationContext)
-               {
-                       if (cancelable == null)
-                               throw new ArgumentNullException ("cancelable");
-                       
-                       return Register (() => cancelable.Cancel (), useSynchronizationContext);
-               }
-               
+
                public CancellationTokenRegistration Register (Action<object> callback, object state, bool useSynchronizationContext)
                {
                        if (callback == null)
                                throw new ArgumentNullException ("callback");
-                       
+
                        return Register (() => callback (state), useSynchronizationContext);
                }
 
+               public void ThrowIfCancellationRequested ()
+               {
+                       if (initialized && Source.IsCancellationRequested)
+                               throw new OperationCanceledException (this);
+               }
+
                public bool Equals (CancellationToken other)
                {
                        return this.Source == other.Source;
                }
-               
-               public override bool Equals (object obj)
+
+               public override bool Equals (object other)
                {
-                       return (obj is CancellationToken) ? Equals ((CancellationToken)obj) : false;
+                       return (other is CancellationToken) ? Equals ((CancellationToken)other) : false;
                }
-               
+
                public override int GetHashCode ()
                {
                        return Source.GetHashCode ();
                }
-               
-               public static bool operator == (CancellationToken lhs, CancellationToken rhs)
+
+               public static bool operator == (CancellationToken left, CancellationToken right)
                {
-                       return lhs.Equals (rhs);
+                       return left.Equals (right);
                }
-               
-               public static bool operator != (CancellationToken lhs, CancellationToken rhs)
+
+               public static bool operator != (CancellationToken left, CancellationToken right)
                {
-                       return !lhs.Equals (rhs);
+                       return !left.Equals (right);
                }
-               
+
                public bool CanBeCanceled {
                        get {
-                               return true;
+                               return canBeCanceled;
                        }
                }
-               
+
                public bool IsCancellationRequested {
                        get {
-                               return Source.IsCancellationRequested;
+                               return initialized && Source.IsCancellationRequested;
                        }
                }
-               
+
                public WaitHandle WaitHandle {
                        get {
                                return Source.WaitHandle;
                        }
                }
-               
+
                internal CancellationTokenSource Source {
-                       get;
-                       set;
+                       get {
+                               if (!initialized)
+                                       CorrectlyInitialize ();
+                               return source;
+                       }
+                       set {
+                               source = value;
+                       }
+               }
+
+               void CorrectlyInitialize ()
+               {
+                       Source = CancellationTokenSource.NoneSource;
+                       initialized = true;
                }
        }
 }