LogicalSet/GetData implementation in CallContext
authorBart Vries <b.vries@sanba.nl>
Mon, 25 Nov 2013 15:59:59 +0000 (16:59 +0100)
committerBart Vries <b.vries@sanba.nl>
Mon, 25 Nov 2013 15:59:59 +0000 (16:59 +0100)
mcs/class/corlib/System.Runtime.Remoting.Messaging/CallContext.cs
mcs/class/corlib/System.Runtime.Remoting.Proxies/RealProxy.cs
mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs
mcs/class/corlib/Test/System.Threading/ExecutionContextTest.cs

index 4b5352a4aead209e4acf58aa54c1629724d1adba..cc252edf83dfbc0f5628b3acd330ffc63ac49316 100644 (file)
@@ -46,6 +46,7 @@ namespace System.Runtime.Remoting.Messaging
        public sealed class CallContext 
        {
                [ThreadStatic] static Header [] Headers;
+               [ThreadStatic] static Hashtable logicalDatastore;
                [ThreadStatic] static Hashtable datastore;
                [ThreadStatic] static object hostContext;
                
@@ -62,28 +63,37 @@ namespace System.Runtime.Remoting.Messaging
                public static void FreeNamedDataSlot (string name) 
                {
                        Datastore.Remove (name);
+                       LogicalDatastore.Remove (name);
                }
 
                public static object GetData (string name) 
                {
-                       return Datastore [name];
+                       if (LogicalDatastore.ContainsKey (name)) {
+                               return LogicalDatastore [name];
+                       } else {
+                               return Datastore [name];
+                       }
                }
                
                public static void SetData (string name, object data) 
                {
-                       Datastore [name] = data;
+                       if (data is ILogicalThreadAffinative) {
+                               LogicalSetData (name, data);
+                       } else {
+                               LogicalDatastore.Remove (name);
+                               Datastore [name] = data;
+                       }
                }
-
-               [MonoTODO]
+               
                public static object LogicalGetData (string name) 
                {
-                       throw new NotImplementedException ();
+                       return LogicalDatastore [name];
                }
-               
-               [MonoTODO]
+
                public static void LogicalSetData (string name, object data) 
                {
-                       throw new NotImplementedException ();
+                       Datastore.Remove (name);
+                       LogicalDatastore [name] = data;
                }
 
                public static Header[] GetHeaders () 
@@ -99,12 +109,11 @@ namespace System.Runtime.Remoting.Messaging
                internal static LogicalCallContext CreateLogicalCallContext (bool createEmpty)
                {
                        LogicalCallContext ctx = null;
-                       if (datastore != null) {
-                               foreach (DictionaryEntry entry in datastore)
-                                       if (entry.Value is ILogicalThreadAffinative) {
-                                               if (ctx == null) ctx = new LogicalCallContext ();
-                                               ctx.SetData ((string)entry.Key, entry.Value);
-                                       }
+                       if (logicalDatastore != null) {
+                               ctx = new LogicalCallContext ();
+                               foreach (DictionaryEntry entry in logicalDatastore) {
+                                       ctx.SetData ((string)entry.Key, entry.Value);
+                               }
                        }
 
                        if (ctx == null && createEmpty)
@@ -115,26 +124,28 @@ namespace System.Runtime.Remoting.Messaging
 
                internal static object SetCurrentCallContext (LogicalCallContext ctx)
                {
-                       object oldData = datastore;
+                       object oldData = new object[] { datastore, logicalDatastore };
 
                        if (ctx != null && ctx.HasInfo)
-                               datastore = (Hashtable) ctx.Datastore.Clone ();
+                               logicalDatastore = (Hashtable) ctx.Datastore.Clone ();
                        else
-                               datastore = null;
+                               logicalDatastore = null;
                                
                        return oldData;
                }
                
-               internal static void UpdateCurrentCallContext (LogicalCallContext ctx)
+               internal static void UpdateCurrentLogicalCallContext (LogicalCallContext ctx)
                {
                        Hashtable data = ctx.Datastore;
                        foreach (DictionaryEntry entry in data)
-                               SetData ((string)entry.Key, entry.Value);
+                               LogicalSetData ((string)entry.Key, entry.Value);
                }
                
                internal static void RestoreCallContext (object oldContext)
                {
-                       datastore = (Hashtable) oldContext;
+                       object[] contextArray = (object[])oldContext;
+                       datastore = (Hashtable)contextArray [0];
+                       logicalDatastore = (Hashtable)contextArray [1];
                }
 
                private static Hashtable Datastore
@@ -146,6 +157,16 @@ namespace System.Runtime.Remoting.Messaging
                                return r;
                        }
                }
+
+               private static Hashtable LogicalDatastore
+               {
+                       get {
+                               Hashtable r = logicalDatastore;
+                               if (r == null)
+                                       return logicalDatastore = new Hashtable ();
+                               return r;
+                       }
+               }
        }
 
        [System.Runtime.InteropServices.ComVisible (true)]
index 745c16134451013c22fa87c1e42c13a3a43e0f53..d430e9ccc1d505f0815f4d5c0100f7bf8d9d60d8 100644 (file)
@@ -218,7 +218,7 @@ namespace System.Runtime.Remoting.Proxies
                        }
                        
                        if (res_msg.LogicalCallContext != null && res_msg.LogicalCallContext.HasInfo)
-                               CallContext.UpdateCurrentCallContext (res_msg.LogicalCallContext);
+                               CallContext.UpdateCurrentLogicalCallContext (res_msg.LogicalCallContext);
 
                        exc = res_msg.Exception;
 
index f4bab8d4ad1c5c19dea2259422a92a9129a87b08..66ef9ce0e64df1e9a4d15b7b0dc431eb4f4f19c2 100644 (file)
@@ -796,7 +796,7 @@ namespace System.Runtime.Remoting
                        if (obj is CACD) {
                                CACD cad = (CACD) obj;
                                obj = cad.d;
-                               CallContext.UpdateCurrentCallContext ((LogicalCallContext) cad.c);
+                               CallContext.UpdateCurrentLogicalCallContext ((LogicalCallContext) cad.c);
                        }
                        return obj;
                }
index 9e795120020b85881cd822ca74b8a4ad86069104..3a77d9aba2b70b962b00e5377254c1e45735e22d 100644 (file)
@@ -67,6 +67,66 @@ namespace MonoTests.System.Threading {
                {
                        if (ExecutionContext.IsFlowSuppressed ())
                                ExecutionContext.RestoreFlow ();
+
+                       CallContext.FreeNamedDataSlot ("testlc");
+               }
+
+               [Test]
+               [Category("MobileNotWorking")]
+               public void LogicalGetData_SetData()
+               {
+                       var value = "a";
+
+                       CallContext.SetData ("testlc", value);
+                       var capturedValue = CallContext.LogicalGetData ("testlc");
+
+                       Assert.IsNull (capturedValue);
+               }
+               
+               [Test]
+               [Category("MobileNotWorking")]
+               public void LogicalGetData_SetDataLogicalThreadAffinative()
+               {
+                       var value = new CallContextValue ("a");
+
+                       CallContext.SetData ("testlc", value);
+                       var capturedValue = CallContext.LogicalGetData ("testlc");
+
+                       Assert.AreEqual (value, capturedValue);
+               }
+
+               [Test]
+               [Category("MobileNotWorking")]
+               public void GetData_SetLogicalData()
+               {
+                       var value = "a";
+
+                       CallContext.LogicalSetData ("testlc", value);
+                       var capturedValue = CallContext.GetData ("testlc");
+
+                       Assert.AreEqual (value, capturedValue);
+               }
+
+               [Test]
+               [Category("MobileNotWorking")]
+               public void CaptureLogicalCallContext()
+               {
+                       var value = "Tester";
+                       object capturedValue = null;
+
+                       CallContext.LogicalSetData ("testlc", value);
+
+                       ExecutionContext ec = ExecutionContext.Capture ();
+                       Assert.IsNotNull (ec, "Capture");
+                       Assert.AreEqual (value, CallContext.LogicalGetData ("testlc"));
+                       CallContext.LogicalSetData ("testlc", null);
+
+                       ExecutionContext.Run (ec, new ContextCallback (new Action<object> ((data) => {
+                               capturedValue = CallContext.LogicalGetData ("testlc");
+                       })), null);
+
+                       Assert.AreEqual (value, capturedValue);
+                       Assert.AreNotEqual (value, CallContext.LogicalGetData ("testlc"));
                }
 
                [Test]