Skip to content

Commit 3eb24d8

Browse files
committed
Lock hash tables during augmented assignment
1 parent f381012 commit 3eb24d8

File tree

1 file changed

+46
-6
lines changed

1 file changed

+46
-6
lines changed

M2/Macaulay2/d/evaluate.d

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,31 +1262,68 @@ nullCoalescion(lhs:Code,rhs:Code):Expr := (
12621262
else e);
12631263
setup(QuestionQuestionS, nullify, nullCoalescion);
12641264
1265+
HashTableOrNull := HashTable or null;
1266+
1267+
-- check if code is x#k or x.k (where x is a hash table)
1268+
-- if so, lock it and return (so we can unlock it later)
1269+
maybeLock(c:Code):HashTableOrNull := (
1270+
when c
1271+
is x:binaryCode do (
1272+
if x.f == DotS.symbol.binary || x.f == SharpS.symbol.binary
1273+
then (
1274+
y := eval(x.lhs);
1275+
when y is z:HashTable do (
1276+
if !z.beingInitialized then lockWrite(z.mutex);
1277+
HashTableOrNull(z))
1278+
else HashTableOrNull(null()))
1279+
else HashTableOrNull(null()))
1280+
else HashTableOrNull(null()));
1281+
1282+
maybeUnlock(x:HashTableOrNull):void := (
1283+
when x
1284+
is y:HashTable do (
1285+
if !y.beingInitialized then unlock(y.mutex))
1286+
else nothing);
1287+
12651288
augmentedAssignmentFun(x:augmentedAssignmentCode):Expr := (
12661289
when lookup(x.oper.word, augmentedAssignmentOperatorTable)
12671290
is null do buildErrorPacket("unknown augmented assignment operator")
12681291
is s:Symbol do (
1292+
-- check if we're modifying a hash table and lock if so
1293+
table := maybeLock(x.lhs);
12691294
-- evaluate the left-hand side first
12701295
lexpr := nullE;
12711296
if s.word.name === "??" -- x ??= y is treated like x ?? (x = y)
12721297
then (
12731298
e := nullify(x.lhs);
12741299
when e
12751300
is Nothing do nothing
1276-
else return e)
1301+
else (
1302+
maybeUnlock(table);
1303+
return e))
12771304
else lexpr = eval(x.lhs);
1278-
when lexpr is e:Error do return lexpr else nothing;
1305+
when lexpr is e:Error do (
1306+
maybeUnlock(table);
1307+
return lexpr)
1308+
else nothing;
12791309
-- check if user-defined method exists
12801310
meth := lookup(Class(lexpr), Expr(SymbolClosure(globalFrame, x.oper)));
12811311
if meth != nullE then (
12821312
rexpr := eval(x.rhs);
1283-
when rexpr is e:Error do return rexpr else nothing;
1313+
when rexpr is e:Error do (
1314+
maybeUnlock(table);
1315+
return rexpr)
1316+
else nothing;
12841317
r := applyEEE(meth, lexpr, rexpr);
12851318
when r
12861319
is s:SymbolClosure do (
12871320
if s.symbol.word.name === "Default" then nothing
1288-
else return r)
1289-
else return r);
1321+
else (
1322+
maybeUnlock(table);
1323+
return r))
1324+
else (
1325+
maybeUnlock(table);
1326+
return r));
12901327
-- if not, use default behavior
12911328
left := evaluatedCode(lexpr, codePosition(x.lhs));
12921329
when x.lhs
@@ -1305,7 +1342,10 @@ augmentedAssignmentFun(x:augmentedAssignmentCode):Expr := (
13051342
is y:binaryCode do (
13061343
r := Code(binaryCode(s.binary, Code(left), x.rhs, x.position));
13071344
if y.f == DotS.symbol.binary || y.f == SharpS.symbol.binary
1308-
then AssignElemFun(y.lhs, y.rhs, r)
1345+
then (
1346+
z := AssignElemFun(y.lhs, y.rhs, r);
1347+
maybeUnlock(table);
1348+
z)
13091349
else InstallValueFun(CodeSequence(
13101350
convertGlobalOperator(x.info), y.lhs, y.rhs, r)))
13111351
is y:adjacentCode do (

0 commit comments

Comments
 (0)