projects
/
mono.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Merge pull request #819 from brendanzagaeski/patch-1
[mono.git]
/
mcs
/
class
/
corlib
/
System.Threading
/
CancellationTokenSource.cs
diff --git
a/mcs/class/corlib/System.Threading/CancellationTokenSource.cs
b/mcs/class/corlib/System.Threading/CancellationTokenSource.cs
index b82e49f59bfb751b810a4406af15003b593f7152..c5557f0446e69b7808e73a295b08c7c244d4e469 100644
(file)
--- a/
mcs/class/corlib/System.Threading/CancellationTokenSource.cs
+++ b/
mcs/class/corlib/System.Threading/CancellationTokenSource.cs
@@
-61,7
+61,7
@@
namespace System.Threading
#if NET_4_5
timer_callback = token => {
var cts = (CancellationTokenSource) token;
#if NET_4_5
timer_callback = token => {
var cts = (CancellationTokenSource) token;
- cts.Cancel ();
+ cts.Cancel
Safe
();
};
#endif
}
};
#endif
}
@@
-118,23
+118,46
@@
namespace System.Threading
public void Cancel (bool throwOnFirstException)
{
CheckDisposed ();
public void Cancel (bool throwOnFirstException)
{
CheckDisposed ();
+ Cancellation (throwOnFirstException);
+ }
+
+ //
+ // Don't throw ObjectDisposedException if the callback
+ // is called concurrently with a Dispose
+ //
+ public void CancelSafe ()
+ {
+ if (!disposed)
+ Cancellation (true);
+ }
+ void Cancellation (bool throwOnFirstException)
+ {
if (canceled)
return;
Thread.MemoryBarrier ();
canceled = true;
if (canceled)
return;
Thread.MemoryBarrier ();
canceled = true;
-
- handle.Set ();
+
+ Thread.MemoryBarrier ();
+
+ // Dispose might be running at same time
+ if (!disposed)
+ handle.Set ();
+
if (linkedTokens != null)
UnregisterLinkedTokens ();
if (linkedTokens != null)
UnregisterLinkedTokens ();
-
+
+ var cbs = callbacks;
+ if (cbs == null)
+ return;
+
List<Exception> exceptions = null;
List<Exception> exceptions = null;
-
+
try {
Action cb;
try {
Action cb;
- for (int id =
int.MinValue + 1; id <= currId; id++
) {
- if (!c
allback
s.TryRemove (new CancellationTokenRegistration (id, this), out cb))
+ for (int id =
currId; id != int.MinValue; id--
) {
+ if (!c
b
s.TryRemove (new CancellationTokenRegistration (id, this), out cb))
continue;
if (cb == null)
continue;
continue;
if (cb == null)
continue;
@@
-153,24
+176,13
@@
namespace System.Threading
}
}
} finally {
}
}
} finally {
- c
allback
s.Clear ();
+ c
b
s.Clear ();
}
if (exceptions != null)
throw new AggregateException (exceptions);
}
}
if (exceptions != null)
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)
{
#if NET_4_5
public void CancelAfter (TimeSpan delay)
{
@@
-212,7
+224,7
@@
namespace System.Threading
throw new ArgumentException ("Empty tokens array");
CancellationTokenSource src = new CancellationTokenSource ();
throw new ArgumentException ("Empty tokens array");
CancellationTokenSource src = new CancellationTokenSource ();
- Action action = src.
SafeLinkedCancel
;
+ Action action = src.
CancelSafe
;
var registrations = new List<CancellationTokenRegistration> (tokens.Length);
foreach (CancellationToken token in tokens) {
var registrations = new List<CancellationTokenRegistration> (tokens.Length);
foreach (CancellationToken token in tokens) {
@@
-250,18
+262,20
@@
namespace System.Threading
void Dispose (bool disposing)
{
if (disposing && !disposed) {
void Dispose (bool disposing)
{
if (disposing && !disposed) {
- Thread.MemoryBarrier ();
disposed = true;
disposed = true;
+ Thread.MemoryBarrier ();
if (!canceled) {
if (!canceled) {
- Thread.MemoryBarrier ();
UnregisterLinkedTokens ();
callbacks = null;
UnregisterLinkedTokens ();
callbacks = null;
+ } else {
+ handle.WaitOne ();
}
#if NET_4_5
if (timer != null)
timer.Dispose ();
#endif
}
#if NET_4_5
if (timer != null)
timer.Dispose ();
#endif
+
handle.Dispose ();
}
}
handle.Dispose ();
}
}