Browse Source

[cs] Improve FieldLookup + thread safety

Cauê Waneck 10 years ago
parent
commit
d770d5be5a
2 changed files with 34 additions and 20 deletions
  1. 2 12
      gencs.ml
  2. 32 8
      std/cs/internal/FieldLookup.hx

+ 2 - 12
gencs.ml

@@ -3208,22 +3208,12 @@ let configure gen =
 	let flookup_cl = get_cl (get_type gen (["haxe";"lang"], "FieldLookup")) in
 	(try
 		let basic = gen.gcon.basic in
-		let change_array = ArrayDeclSynf.default_implementation gen native_arr_cl in
 		let cl = flookup_cl in
 		let field_ids = PMap.find "fieldIds" cl.cl_statics in
 		let fields = PMap.find "fields" cl.cl_statics in
 
-		field_ids.cf_expr <- Some (change_array {
-			eexpr = TArrayDecl(List.map (fun (i,s) -> { eexpr = TConst(TInt (i)); etype = basic.tint; epos = field_ids.cf_pos }) hashes);
-			etype = basic.tarray basic.tint;
-			epos = field_ids.cf_pos
-		});
-
-		fields.cf_expr <- Some (change_array {
-			eexpr = TArrayDecl(List.map (fun (i,s) -> { eexpr = TConst(TString s); etype = basic.tstring; epos = fields.cf_pos }) hashes);
-			etype = basic.tarray basic.tstring;
-			epos = fields.cf_pos
-		})
+		field_ids.cf_expr <- Some (mk_nativearray_decl gen basic.tint (List.map (fun (i,s) -> { eexpr = TConst(TInt (i)); etype = basic.tint; epos = field_ids.cf_pos }) hashes) field_ids.cf_pos);
+		fields.cf_expr <- Some (mk_nativearray_decl gen basic.tstring (List.map (fun (i,s) -> { eexpr = TConst(TString s); etype = basic.tstring; epos = fields.cf_pos }) hashes) fields.cf_pos);
 
 	with | Not_found ->
 		gen.gcon.error "Fields 'fieldIds' and 'fields' were not found in class haxe.lang.FieldLookup" flookup_cl.cl_pos

+ 32 - 8
std/cs/internal/FieldLookup.hx

@@ -25,9 +25,14 @@ package cs.internal;
 @:final @:nativeGen
 @:keep @:static class FieldLookup
 {
+	@:protected private static var fieldIds:cs.NativeArray<Int>;
+	@:protected private static var fields:cs.NativeArray<String>;
+	@:protected private static var length:Int;
 
-	@:private private static var fieldIds:Array<Int>;
-	@:private private static var fields:Array<String>;
+	static function __init__()
+	{
+		length = fieldIds.Length;
+	}
 
 	//s cannot be null here
 	private static inline function doHash(s:String):Int
@@ -46,7 +51,7 @@ package cs.internal;
 		//start of binary search algorithm
 		var ids = fieldIds;
 		var min = 0;
-		var max = ids.length;
+		var max = length;
 
 		while (min < max)
 		{
@@ -72,9 +77,12 @@ package cs.internal;
 		var key = doHash(s);
 
 		//start of binary search algorithm
-		var ids = fieldIds;
+		var ids = fieldIds,
+		    fld = fields;
 		var min = 0;
-		var max = ids.length;
+		var max = length;
+
+		var len = length;
 
 		while (min < max)
 		{
@@ -86,15 +94,30 @@ package cs.internal;
 			} else if (key > imid) {
 				min = mid + 1;
 			} else {
-				var field = fields[mid];
+				var field = fld[mid];
 				if (field != s)
 					return ~key; //special case
 				return key;
 			}
 		}
+
 		//if not found, min holds the value where we should insert the key
-		ids.insert(min, key);
-		fields.insert(min, s);
+		//ensure thread safety:
+		cs.Lib.lock(FieldLookup, {
+			if (len != length) //race condition which will very rarely happen - other thread modified sooner.
+				return hash(s); //since we already own the lock, this second try will always succeed
+
+#if eraseGenerics
+			fieldIds = insertInt(fieldIds, length, min, key);
+			fields = insertString(fields, length, min, s);
+#else
+			insert(fieldIds, length, min, key);
+			insert(fields, length, min, s);
+			// ids.insert(min, key);
+			// fields.insert(min, s);
+#end
+			++length;
+		});
 		return key;
 	}
 
@@ -234,5 +257,6 @@ package cs.internal;
 	static function insertInt(a:cs.NativeArray<Int>, length:Int, pos:Int, x:Int):cs.NativeArray<Int> return __insert(a, length, pos, x);
 	static function insertFloat(a:cs.NativeArray<Float>, length:Int, pos:Int, x:Float):cs.NativeArray<Float> return __insert(a, length, pos, x);
 	static function insertDynamic(a:cs.NativeArray<Dynamic>, length:Int, pos:Int, x:Dynamic):cs.NativeArray<Dynamic> return __insert(a, length, pos, x);
+	static function insertString(a:cs.NativeArray<String>, length:Int, pos:Int, x:Dynamic):cs.NativeArray<String> return __insert(a, length, pos, x);
 	#end
 }