// Authors:
// Lluis Sanchez (lluis@novell.com)
// Sebastien Pouliot <sebastien@ximian.com>
+// Marek Safar (marek.safar@gmail.com)
//
// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2014 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
using System.Security;
using System.Security.Permissions;
using System.Runtime.Remoting.Messaging;
+using System.Collections.Generic;
namespace System.Threading {
[Serializable]
private LogicalCallContext _lcc;
private bool _suppressFlow;
private bool _capture;
+ Dictionary<string, object> local_data;
internal ExecutionContext ()
{
}
- internal ExecutionContext (ExecutionContext ec)
+ private ExecutionContext (ExecutionContext ec)
{
#if !MOBILE
if (ec._sc != null)
_sc = new SecurityContext (ec._sc);
#endif
+ if (ec._lcc != null)
+ _lcc = (LogicalCallContext) ec._lcc.Clone ();
+
_suppressFlow = ec._suppressFlow;
_capture = true;
}
public static ExecutionContext Capture ()
{
- return Capture (true);
+ return Capture (true, false);
}
- internal static ExecutionContext Capture (bool captureSyncContext)
+ internal static ExecutionContext Capture (bool captureSyncContext, bool nullOnEmpty)
{
- ExecutionContext ec = Thread.CurrentThread.ExecutionContext;
+ ExecutionContext ec = Current;
if (ec.FlowSuppressed)
return null;
+ if (nullOnEmpty && ec._sc == null && (ec._lcc == null || !ec._lcc.HasInfo))
+ return null;
+
ExecutionContext capture = new ExecutionContext (ec);
#if !MOBILE
if (SecurityManager.SecurityEnabled)
capture.SecurityContext = SecurityContext.Capture ();
#endif
-
-#if !MONOTOUCH
- capture.LogicalCallContext = CallContext.CreateLogicalCallContext (false);
-#endif
return capture;
}
internal LogicalCallContext LogicalCallContext {
get {
if (_lcc == null)
- return new LogicalCallContext ();
+ _lcc = new LogicalCallContext ();
return _lcc;
}
set {
}
}
+ internal Dictionary<string, object> DataStore {
+ get {
+ if (local_data == null)
+ local_data = new Dictionary<string, object> ();
+ return local_data;
+ }
+ set {
+ local_data = value;
+ }
+ }
+
#if !MOBILE
internal SecurityContext SecurityContext {
get {
set { _suppressFlow = value; }
}
- // Note: Previous to version 2.0 only the CompressedStack and (sometimes!) the WindowsIdentity
- // were propagated to new threads. This is why ExecutionContext is internal in before NET_2_0.
- // It also means that all newer context classes should be here (i.e. inside the #if NET_2_0).
-
public static bool IsFlowSuppressed ()
{
- return Thread.CurrentThread.ExecutionContext.FlowSuppressed;
+ return Current.FlowSuppressed;
}
public static void RestoreFlow ()
{
- ExecutionContext ec = Thread.CurrentThread.ExecutionContext;
+ ExecutionContext ec = Current;
if (!ec.FlowSuppressed)
throw new InvalidOperationException ();
ec.FlowSuppressed = false;
}
- [MonoTODO ("only the SecurityContext is considered")]
[SecurityPermission (SecurityAction.LinkDemand, Infrastructure = true)]
public static void Run (ExecutionContext executionContext, ContextCallback callback, object state)
{
"Null ExecutionContext"));
}
-#if MOBILE
- callback (state);
-#else
- // FIXME: supporting more than one context should be done with executionContextSwitcher
- // and will requires a rewrite of this method
- var callContextCallBack = new ContextCallback (new Action<object> ((ostate) => {
- var originalCallContext = CallContext.CreateLogicalCallContext (true);
- try {
- CallContext.SetCurrentCallContext (executionContext.LogicalCallContext);
- callback (ostate);
- } finally {
- CallContext.SetCurrentCallContext (originalCallContext);
- }
- }));
- SecurityContext.Run (executionContext.SecurityContext, callContextCallBack, state);
-#endif
+ var prev = Current;
+ try {
+ Thread.CurrentThread.ExecutionContext = executionContext;
+ callback (state);
+ } finally {
+ Thread.CurrentThread.ExecutionContext = prev;
+ }
}
public static AsyncFlowControl SuppressFlow ()
t.ExecutionContext.FlowSuppressed = true;
return new AsyncFlowControl (t, AsyncFlowControlType.Execution);
}
+
+ internal static LogicalCallContext CreateLogicalCallContext (bool createEmpty)
+ {
+ var lcc = Current._lcc;
+ if (lcc == null) {
+ if (createEmpty)
+ lcc = new LogicalCallContext ();
+
+ return lcc;
+ }
+
+ return (LogicalCallContext) lcc.Clone ();
+ }
+
+ internal void FreeNamedDataSlot (string name)
+ {
+ if (_lcc != null)
+ _lcc.FreeNamedDataSlot (name);
+
+ if (local_data != null)
+ local_data.Remove (name);
+ }
+
+ internal static ExecutionContext Current {
+ get {
+ return Thread.CurrentThread.ExecutionContext;
+ }
+ }
}
}
\ No newline at end of file