Существует ненулевая вероятность, что сборщик придёт как раз во время обхода таблицы в одном из потоков.
Скрытый текст
Код
local p = {}
function OnParam(class_code, sec_code)
p[sec_code] = class_code
end
local t = {}
function OnAllTrade(alltrade)
t[alltrade.sec_code] = alltrade.class_code
end
function main()
while run do
for k, v in pairs(p) do
p[k] = nil
end
for k, v in pairs(t) do
t[k] = nil
end
sleep(1)
end
end
Надо делать так, как надо. А как не надо - делать не надо.
Roman Azarov написал: С некоторой вероятностью может появиться следующая ошибка?
Верно
Цитата
Roman Azarov написал: У себя подобного за целый день не увидели
Можете форсировать события:
Скрытый текст
Код
local p = {}
function OnParam(class_code, sec_code)
for i = 1, 20 do
p[sec_code..i] = class_code
end
end
local t = {}
function OnAllTrade(alltrade)
for i = 1, 20 do
t[alltrade.sec_code..i] = alltrade
end
end
function main()
while run do
for k, v in pairs(p) do
p[k] = nil
end
for k, v in pairs(t) do
t[k] = nil
end
sleep(1)
end
end
и сделать перезаказ всех обезличенных сделок.
Надо делать так, как надо. А как не надо - делать не надо.
Чтобы обход таблицы был более корректным, изменим тестовый скрипт, так, чтобы добавление и удаление полей таблицы осуществлялось в одном потоке:
Скрытый текст
Код
local run = true
function OnStop()
run = nil
end
local function f(t)
for i = 1, 100 do
t[""..i] = i
end
for k, v in pairs(t) do
t[k] = nil
end
t = {}
return t
end
p = {}
function OnParam(class_code, sec_code)
p = f(p)
end
a = {}
function OnAllTrade(alltrade)
a = f(a)
end
m = {}
function main()
while run do
m = f(m)
sleep(1)
end
end
Ошибка "invalid key to 'next'" никуда не делась. Для форсирования: перезаказать все обезличенные сделки.
Надо делать так, как надо. А как не надо - делать не надо.
Старатель, ходить по массиву можно обычными функциями, а удалять/добавлять значения надо потокобезопасными. Вообще, удалять значения из массива в цикле по этому же массиву это плохая практика; вы тут судя по всему просто очищаете стол, вместо этого можно просто создать пустой - это не только надежнее и проще, но еще и работает быстрее.
То что вам поенепременно надо использовать непотокобезопасные методы в многопоточной программе - тут что называется своих мозгов в чужую голову не вставишь.
Артем написал: удалять значения из массива в цикле по этому же массиву это плохая практика
В Lua не запрещено, из Reference Manual:
Цитата
The behavior of next is undefined if, during the traversal, you assign any value to a non-existent field in the table. You may however modify existing fields. In particular, you may set existing fields to nil.
Ошибка, обсуждаемая в ветке, может возникнуть при работе с таблицей в одном потоке. При чём здесь вообще потокобезопасные функции, которые к тому же, не работают с ассоциативными массивами?
Старатель, аргументы я привел, вы их благополучно проигнорировали. Тут что называется нами три типа людей: есть джентльмены которые соглашаются, есть обезьяны которые начинают спорить с задокументированными и/или воспроизводимыми вещами, и есть такие вот индивиды которые просто делают вид что ничего сказано и не было. Неприятно когда просишь обосновать что-то думая что умнее всех и никто ничего не скажет, а кто-то берет и обосновывает, понимаю.
Совет от профи: просто не работайте с одной и той же памятью из разных тредов, вот и все. В луа конечно мутексов нету, уж не предусмотрено многопоточности на уровне вм, просто в арке люди слову на глобус натягивают. Но вам родина нафига двойную буферизацию дала?
Артем, джентльмены соглашаются только с тем, кто прав. А умников, которые считают себя "профи" в каждом вопросе, а по факту даже не понимают сути обсуждаемого, надо на место ставить.
Что вы там обосновали? Про "небо голубое"? Аргументов от вас лично я так и не увидел.
Цитата
Артем написал: просто не работайте с одной и той же памятью из разных тредов
Спасибо, кэп, без вас бы не разобрались. Ветка про другое. Второй поток вообще может не знать про таблицу в первом, или может знать, но не работать с ней.
Надо делать так, как надо. А как не надо - делать не надо.
Roman Azarov написал: У себя подобного за целый день не увидели
Roman Azarov, вот тест, который воспроизводит ошибку практически сразу после перезаказа обезличенных сделок.
Скрытый текст
Можете поиграться со значением параметра n
Код
local n = 25
local run = true
function OnStop()
run = nil
end
function OnParam(class_code, sec_code)
p = {}
for i = 1, n do
p[tostring(i)] = tostring(i)
end
for k, v in pairs(p) do
p[k] = os.time()
p[k] = nil
end
end
function OnAllTrade(alltrade)
a = {}
for i = 1, n do
a[tostring(i)] = tostring(i)
end
for k, v in pairs(a) do
a[k] = os.time()
a[k] = nil
end
end
function main()
while run do
m = {}
for i = 1, n do
m[tostring(i)] = tostring(i)
end
for k, v in pairs(m) do
m[k] = os.time()
m[k] = nil
end
sleep(1)
end
end
Надо делать так, как надо. А как не надо - делать не надо.
Тем временем, в Lua 5.4 продолжают находить баги. Так что если разработчики, всё-таки, будут обновлять версию, то просьба до самой последней обновить. https://www.lua.org/bugs.html#5.4.3
Баги были есть и будут. Тут есть два подхода: постоянно обновляться до самой свежей версии, в процессе чего что-то может сломаться, либо выбрать версию и сидеть на ней всё обозримое будущее, а с багами люди разберутся на месте.
Roman Azarov написал: У себя подобного за целый день не увидели
Roman Azarov, вот тест, который воспроизводит ошибку практически сразу после перезаказа обезличенных сделок. Скрытый текст Можете поиграться со значением параметра n
Код
local n = 25
local run = true
function OnStop ()
run = nil
end
function OnParam (class_code, sec_code)
p = {}
for i = 1 , n do
p[tostring(i)] = tostring(i)
end
for k, v in pairs(p) do
p[k] = os.time ()
p[k] = nil
end
end
function OnAllTrade (alltrade)
a = {}
for i = 1 , n do
a[tostring(i)] = tostring(i)
end
for k, v in pairs(a) do
a[k] = os.time ()
a[k] = nil
end
end
function main ()
while run do
m = {}
for i = 1 , n do
m[tostring(i)] = tostring(i)
end
for k, v in pairs(m) do
m[k] = os.time ()
m[k] = nil
end
sleep ( 1 )
end
end
Добрый день,
Действительно, в ПО QLUA есть ошибка функций обратного вызова скрипта приводящая к подобным ошибкам. Мы справим её в очередном обновлении ПО приносим извинения за причинённые неудобства.