Quellcode durchsuchen

* TypeTranslator.cs:
1. Fix the construction of TypeData for nullable types: it should not
be primitive since the primitive were loaded in static ctor.
2. Rename primitiveNullableTypes -> nullableTypes to reflect
correctly the field purpose.
3. Unify synchronization with synchronized hashtable.

svn path=/trunk/mcs/; revision=78002

Konstantin Triger vor 18 Jahren
Ursprung
Commit
4fa89551db

+ 9 - 0
mcs/class/System.XML/System.Xml.Serialization/ChangeLog

@@ -1,3 +1,12 @@
+2007-05-27  Konstantin Triger <[email protected]>
+
+	* TypeTranslator.cs:
+		1. Fix the construction of TypeData for nullable types: it should not
+			be primitive since the primitive were loaded in static ctor.
+		2. Rename primitiveNullableTypes -> nullableTypes to reflect 
+			correctly the field purpose.
+		3. Unify synchronization with synchronized hashtable.
+
 2007-05-24  Konstantin Triger <[email protected]>
 
 	* TypeTranslator.cs: fix typo: set IsNullable flag for primitiveNullableTypes.

+ 43 - 27
mcs/class/System.XML/System.Xml.Serialization/TypeTranslator.cs

@@ -43,34 +43,46 @@ namespace System.Xml.Serialization
 		static Hashtable nameCache;
 		static Hashtable primitiveTypes;
 		static Hashtable primitiveArrayTypes;
-		static Hashtable primitiveNullableTypes;
+		static Hashtable nullableTypes;
 
 #if TARGET_JVM
-		const string AppDomainCacheName = "System.Xml.Serialization.TypeTranslator.AppDomainCache";
-		static Hashtable AppDomainCache {
-			get {
-				Hashtable res = (Hashtable)AppDomain.CurrentDomain.GetData(AppDomainCacheName);
+		static readonly object AppDomain_TypeTranslatorCacheLock = new object ();
+		const string AppDomain_nameCacheName = "System.Xml.Serialization.TypeTranslator.nameCache";
+		const string AppDomain_nullableTypesName = "System.Xml.Serialization.TypeTranslator.nullableTypes";
+		
+		static Hashtable AppDomain_nameCache {
+			get { return GetAppDomainCache (AppDomain_nameCacheName); }
+		}
 
-				if(res == null) {
-					lock(AppDomainCacheName) {
-						res = (Hashtable)AppDomain.CurrentDomain.GetData(AppDomainCacheName);
-						if (res == null) {
-							res = new Hashtable();
-							AppDomain.CurrentDomain.SetData(AppDomainCacheName, res);
-						}
+		static Hashtable AppDomain_nullableTypes {
+			get { return GetAppDomainCache (AppDomain_nullableTypesName); }
+		}
+
+		static Hashtable GetAppDomainCache(string name) {
+			Hashtable res = (Hashtable) AppDomain.CurrentDomain.GetData (name);
+
+			if (res == null) {
+				lock (AppDomain_TypeTranslatorCacheLock) {
+					res = (Hashtable) AppDomain.CurrentDomain.GetData (name);
+					if (res == null) {
+						res = Hashtable.Synchronized (new Hashtable ());
+						AppDomain.CurrentDomain.SetData (name, res);
 					}
 				}
-
-				return res;
 			}
+
+			return res;
 		}
 #endif
 
 		static TypeTranslator ()
 		{
 			nameCache = new Hashtable ();
-			primitiveArrayTypes = new Hashtable ();
+			primitiveArrayTypes = Hashtable.Synchronized (new Hashtable ());
 
+#if !TARGET_JVM
+			nameCache = Hashtable.Synchronized (nameCache);
+#endif
 			// XSD Types with direct map to CLR types
 
 			nameCache.Add (typeof (bool), new TypeData (typeof (bool), "boolean", true));
@@ -136,12 +148,12 @@ namespace System.Xml.Serialization
 			primitiveTypes.Add ("base64", new TypeData (typeof (byte[]), "base64", true));
 
 #if NET_2_0
-			primitiveNullableTypes = Hashtable.Synchronized(new Hashtable ());
+			nullableTypes = Hashtable.Synchronized(new Hashtable ());
 			foreach (DictionaryEntry de in primitiveTypes) {
 				TypeData td = (TypeData) de.Value;
 				TypeData ntd = new TypeData (td.Type, td.XmlType, true);
 				ntd.IsNullable = true;
-				primitiveNullableTypes.Add (de.Key, ntd);
+				nullableTypes.Add (de.Key, ntd);
 			}
 #endif
 		}
@@ -163,11 +175,19 @@ namespace System.Xml.Serialization
 
 				TypeData pt = GetTypeData (type); // beware this recursive call btw ...
 				if (pt != null) {
-						TypeData tt = (TypeData) primitiveNullableTypes [pt.XmlType];
+						TypeData tt = (TypeData) nullableTypes [pt.XmlType];
+#if TARGET_JVM
+						if (tt == null)
+							tt = (TypeData) AppDomain_nullableTypes [pt.XmlType];
+#endif
 						if (tt == null) {
-							tt = new TypeData (type, pt.XmlType, true);
+							tt = new TypeData (type, pt.XmlType, false);
 							tt.IsNullable = true;
-							primitiveNullableTypes [pt.XmlType] = tt;
+#if TARGET_JVM
+							AppDomain_nullableTypes [pt.XmlType] = tt;
+#else
+							nullableTypes [pt.XmlType] = tt;
+#endif
 						}
 						return tt;
 				}
@@ -180,7 +200,6 @@ namespace System.Xml.Serialization
 				// that's why the following check is needed.
 				TypeData at = GetPrimitiveTypeData (xmlDataType);
 				if (type.IsArray && type != at.Type) {
-					lock (primitiveArrayTypes) {
 						TypeData tt = (TypeData) primitiveArrayTypes [xmlDataType];
 						if (tt != null)
 							return tt;
@@ -191,17 +210,15 @@ namespace System.Xml.Serialization
 						}
 						else
 							throw new InvalidOperationException ("Cannot convert values of type '" + type.GetElementType () + "' to '" + xmlDataType + "'");
-					}
 				}
 				return at;
 			}
 
-			lock (nameCache) {
 				TypeData typeData = nameCache[runtimeType] as TypeData;
 				if (typeData != null) return typeData;
 
 #if TARGET_JVM
-				Hashtable dynamicCache = AppDomainCache;
+				Hashtable dynamicCache = AppDomain_nameCache;
 				typeData = dynamicCache[runtimeType] as TypeData;
 				if (typeData != null) return typeData;
 #endif
@@ -232,7 +249,6 @@ namespace System.Xml.Serialization
 				nameCache[runtimeType] = typeData;
 #endif
 				return typeData;
-			}
 		}
 
 		public static bool IsPrimitive (Type type)
@@ -250,8 +266,8 @@ namespace System.Xml.Serialization
 			TypeData td = (TypeData) primitiveTypes [typeName];
 			if (td != null && !td.Type.IsValueType)
 				return td;
-			// for 1.x profile, 'primitiveNullableTypes' is null
-			Hashtable table = nullable && primitiveNullableTypes != null ? primitiveNullableTypes : primitiveTypes;
+			// for 1.x profile, 'nullableTypes' is null
+			Hashtable table = nullable && nullableTypes != null ? nullableTypes : primitiveTypes;
 			td = (TypeData) table [typeName];
 			if (td == null) throw new NotSupportedException ("Data type '" + typeName + "' not supported");
 			return td;