add LogicalCallContext to ExecutionContext
authorYann ROBIN <me.show@gmail.com>
Fri, 7 Dec 2012 16:36:24 +0000 (17:36 +0100)
committerYann ROBIN <me.show@gmail.com>
Fri, 7 Dec 2012 16:36:24 +0000 (17:36 +0100)
Save LogicalCallContext when Capture is called

Restore LogicalCallContext on Run.

see msdn for behavior of ExecutionContext http://msdn.microsoft.com/en-us/library/h84136b2.aspx

mcs/class/corlib/System.Threading/ExecutionContext.cs
mcs/class/corlib/Test/System.Threading/ExecutionContextTest.cs

index 32e729c1de1ebed5af30ddd3ce4985a2523f0668..8efe3c5af56c12924d92d527b0833b94c7afea0b 100644 (file)
@@ -31,9 +31,9 @@ using System.Runtime.InteropServices;
 using System.Runtime.Serialization;
 using System.Security;
 using System.Security.Permissions;
+using System.Runtime.Remoting.Messaging;
 
 namespace System.Threading {
-
        [Serializable]
        public sealed class ExecutionContext : ISerializable
 #if NET_4_0
@@ -43,6 +43,7 @@ namespace System.Threading {
 #if !MOONLIGHT
                private SecurityContext _sc;
 #endif
+               private LogicalCallContext _lcc;
                private bool _suppressFlow;
                private bool _capture;
 
@@ -65,8 +66,13 @@ namespace System.Threading {
                {
                        throw new NotImplementedException ();
                }
-               
+
                public static ExecutionContext Capture ()
+               {
+                       return Capture(true);
+               }
+               
+               internal static ExecutionContext Capture (bool captureSyncContext)
                {
                        ExecutionContext ec = Thread.CurrentThread.ExecutionContext;
                        if (ec.FlowSuppressed)
@@ -77,6 +83,7 @@ namespace System.Threading {
                        if (SecurityManager.SecurityEnabled)
                                capture.SecurityContext = SecurityContext.Capture ();
 #endif
+                       capture.LogicalCallContext = CallContext.CreateLogicalCallContext(false);
                        return capture;
                }
                
@@ -106,6 +113,18 @@ namespace System.Threading {
                }
                
                // internal stuff
+
+               internal LogicalCallContext LogicalCallContext {
+                       get {
+                               if (_lcc == null)
+                                       return new System.Runtime.Remoting.Messaging.LogicalCallContext();
+                               return _lcc;
+                       }
+                       set {
+                               _lcc = value;
+                       }
+               }
+
 #if !MOONLIGHT
                internal SecurityContext SecurityContext {
                        get {
@@ -149,10 +168,22 @@ namespace System.Threading {
                                        "Null ExecutionContext"));
                        }
 
-                       // FIXME: supporting more than one context (the SecurityContext)
-                       // will requires a rewrite of this method
-
-                       SecurityContext.Run (executionContext.SecurityContext, callback, state);
+                       // 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);
                }
 
                public static AsyncFlowControl SuppressFlow ()
@@ -163,4 +194,4 @@ namespace System.Threading {
                }
 #endif
        }
-}
+}
\ No newline at end of file
index a37e6b9726b8bc788e7e3f56d57523d828f2af32..e148335b30d3a5f9e2f186cc9d00e76c78522dbb 100644 (file)
@@ -25,6 +25,7 @@
 // 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.Runtime.Remoting.Messaging;
 
 #if NET_2_0
 
@@ -46,6 +47,16 @@ namespace MonoTests.System.Threading {
                        success = (bool)o;
                }
 
+               public class CallContextValue : ILogicalThreadAffinative
+               {
+                       public object Value { get; set; }
+
+                       public CallContextValue(object value)
+                       {
+                               this.Value = value;
+                       }
+               }
+
                [SetUp]
                public void SetUp ()
                {
@@ -59,6 +70,27 @@ namespace MonoTests.System.Threading {
                                ExecutionContext.RestoreFlow ();
                }
 
+               [Test]
+               public void CaptureCallContext ()
+               {
+                       var value = new CallContextValue(true);
+                       object capturedValue = null;
+
+                       CallContext.SetData("testlc", value);
+
+                       ExecutionContext ec = ExecutionContext.Capture ();
+                       Assert.IsNotNull (ec, "Capture");
+                       Assert.AreEqual(value, CallContext.GetData("testlc")); 
+                       CallContext.SetData("testlc", null);
+
+                       ExecutionContext.Run(ec, new ContextCallback(new Action<object>((data) => {
+                               capturedValue = CallContext.GetData("testlc");
+                       })), null);
+
+                       Assert.AreEqual(value, capturedValue); 
+                       Assert.AreNotEqual(value, CallContext.GetData("testlc"));
+               }
+
                [Test]
                public void Capture ()
                {