global-functions: $ScriptLock: handle array by index

This should mitigate race conditions while rewriting the array.
This commit is contained in:
Christian Hesse 2021-08-30 21:50:46 +02:00
parent d356d6f57c
commit ae8e22941e

View file

@ -931,18 +931,48 @@
:return [ :len [ / system script job find where script=$Script ] ]; :return [ :len [ / system script job find where script=$Script ] ];
} }
:local TicketCount do={
:local Script [ :tostr $1 ];
:global ScriptLockOrder;
:local Count 0;
:foreach Ticket in=($ScriptLockOrder->$Script) do={
:if ([ :typeof $Ticket ] != "nothing") do={
:set Count ($Count + 1);
}
}
:return $Count;
}
:local IsFirstTicket do={
:local Script [ :tostr $1 ];
:local Check [ :tostr $2 ];
:global ScriptLockOrder;
:foreach Ticket in=($ScriptLockOrder->$Script) do={
:if ($Ticket = $Check) do={ :return true; }
:if ([ :typeof $Ticket ] != "nothing" && $Ticket != $Check) do={ :return false; }
}
:return false;
}
:local AddTicket do={ :local AddTicket do={
:local Script [ :tostr $1 ]; :local Script [ :tostr $1 ];
:local Add [ :tostr $2 ]; :local Add [ :tostr $2 ];
:global ScriptLockOrder; :global ScriptLockOrder;
:if ([ :typeof ($ScriptLockOrder->$Script) ] = "nothing") do={
:set ($ScriptLockOrder->$Script) [ :toarray "" ];
}
:while (true) do={ :while (true) do={
:set ($ScriptLockOrder->$Script) (($ScriptLockOrder->$Script), $Add); :local Pos [ :len ($ScriptLockOrder->$Script) ];
:set ($ScriptLockOrder->$Script->$Pos) $Add;
:delay 10ms; :delay 10ms;
:foreach Ticket in=($ScriptLockOrder->$Script) do={ :if (($ScriptLockOrder->$Script->$Pos) = $Add) do={ :return true; }
:if ($Ticket = $Add) do={ :return true; }
}
} }
} }
@ -952,16 +982,19 @@
:global ScriptLockOrder; :global ScriptLockOrder;
:while (true) do={ :local Count 0;
:local New [ :toarray "" ]; :foreach Id,Ticket in=($ScriptLockOrder->$Script) do={
:foreach Ticket in=($ScriptLockOrder->$Script) do={ :if (($ScriptLockOrder->$Script->$Id) = $Remove) do={
:if ($Ticket != $Remove) do={ :set ($ScriptLockOrder->$Script->$Id);
:set New ($New, $Ticket);
}
} }
:set ($ScriptLockOrder->$Script) $New;
:delay 12ms; :if ([ :typeof ($ScriptLockOrder->$Script->$Id) ] != "nothing") do={
:if (($ScriptLockOrder->$Script->0) != $Remove) do={ :return true; } :set Count ($Count + 1);
}
}
:if ($Count = 0) do={
:set ($ScriptLockOrder->$Script);
} }
} }
@ -973,7 +1006,7 @@
$LogPrintExit2 error $0 ("No script '" . $Script . "' is running!") true; $LogPrintExit2 error $0 ("No script '" . $Script . "' is running!") true;
} }
:if ([ :len ($ScriptLockOrder->$Script) ] >= [ $JobCount $Script ]) do={ :if ([ $TicketCount $Script ] >= [ $JobCount $Script ]) do={
$LogPrintExit2 error $0 ("More tickets than running scripts '" . $Script . "', resetting!") false; $LogPrintExit2 error $0 ("More tickets than running scripts '" . $Script . "', resetting!") false;
:set ($ScriptLockOrder->$Script); :set ($ScriptLockOrder->$Script);
/ system script job remove [ find where script=$Script ]; / system script job remove [ find where script=$Script ];
@ -983,12 +1016,12 @@
$AddTicket $Script $MyTicket; $AddTicket $Script $MyTicket;
:local WaitCount 0; :local WaitCount 0;
:while ($WaitMax > $WaitCount && (($ScriptLockOrder->$Script->0) != $MyTicket || [ :len ($ScriptLockOrder->$Script) ] < [ $JobCount $Script ])) do={ :while ($WaitMax > $WaitCount && ([ $IsFirstTicket $Script $MyTicket ] = false || [ $TicketCount $Script ] < [ $JobCount $Script ])) do={
:delay 100ms;
:set WaitCount ($WaitCount + 1); :set WaitCount ($WaitCount + 1);
:delay 100ms;
} }
:if (($ScriptLockOrder->$Script->0) = $MyTicket && [ :len ($ScriptLockOrder->$Script) ] = [ $JobCount $Script ]) do={ :if ([ $IsFirstTicket $Script $MyTicket ] = true && [ $TicketCount $Script ] = [ $JobCount $Script ]) do={
$RemoveTicket $Script $MyTicket; $RemoveTicket $Script $MyTicket;
:return false; :return false;
} }