Skip to content

Commit

Permalink
[cs] Improve FieldLookup + thread safety
Browse files Browse the repository at this point in the history
  • Loading branch information
waneck committed Mar 15, 2015
1 parent e55fe73 commit d770d5b
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 20 deletions.
14 changes: 2 additions & 12 deletions gencs.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
40 changes: 32 additions & 8 deletions std/cs/internal/FieldLookup.hx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
{
Expand All @@ -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)
{
Expand All @@ -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;
}

Expand Down Expand Up @@ -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
}

0 comments on commit d770d5b

Please sign in to comment.