Знаю что много об этом сказано! Знаю что специально сделали потокобезопасные операции с приставкой s или с не важно.. Если сам не специалист в этой области приходится обращаться... На конкретных примерах ОБЩЕГО вида. -------------------------------------------- 1. это небезопасно! A={} function OnAllTrade(alltrade) table.insert(A, alltrade) end
function main() Table={} Table=A[1] end -------------------------------------------- 2. А это безопасно? если нет то почему?
A,B={},{} function OnAllTrade(alltrade) table.insert(A, alltrade) B=A end
function main() Table={} Table=B[1] end ------------------------------------------ 3. аналогично? A=0 function OnAllTrade(alltrade) table.insert(A, alltrade) A=A+alltrade.price-const_1+const_2+... end
function main() C=A/100 if C>const_N then ... end end ------------------------------------------ 4. ....? A=0 function OnAllTrade(alltrade) table.insert(A, alltrade) A=A+alltrade.price-const_1+const_2+... B=A end
function main() C=B/100 if C>const_N then ... end end ---------------------------------------- 5. функция getQuoteLevel2(class,sec) и т.п. вставленная внутрь main безопасна, не изменится ли таблица в процессе присваивания(чтения)? если нет то почему? что такое хэш и в чём отличие от массива? ------------------------------------ 6. Прошу, если это возможно, провести маленькую лекцию или дать ссылку где почитать о работе терминала в плане обработки поступающей информации и взаимодействии скрипта lua с той информацией что поступила в quik. Ясно что вот колбэк он вызывается при изменениях.. НО более подробно в доступной форме, что находится в "чёрном ящике"? Что там за информационные очереди, как они меняются, почему двигаемся по этой очереди, как к этой очереди подвязываются колбэки и main...Вот такого плана... Пожалуйста! Очень прошу, потому как ни чего не понятно...
Добрый день. 1 Да, это не безопасно. можете получить что в A[1] == nil
2. Если A и B таблицы, то B=A не копирует содержимое таблиц, а присваивает ссылку на таблицу A в переменную B, и все изменения в A отражаются в B. Далее аналогично п. 1
3 и 4 Примеры не очень понятны. A это таблица или переменная со значением ноль?
5. getQuoteLevel2 всегда возвращает текущий слепок стакана. Что значит "процесс присваивания чтения" не совсем понятно, поясните.
2. Я правильно понял что фактически меняя таблицу А я одновременно буду менять B за счёт того что В есть просто ссылка на A. А если я сделаю пустую операцию над А и приравняю В к этому. Например что то вроде
function copy_(a) return a end function OnAllTrade(alltrade) table.insert(A, alltrade) B=copy_(A) end
function main() Table={} Table=B[1] end
В 3 и 4 извините поторопился забыл удалить строчку при копировании. Имеются ввиду обычные числовые переменные. Соответственно вроде бы обычные переменные можно то же одновременно модифицировать в колбэке и читать в main() и вроде может получиться в результате ерунда неизвестного вида. Что мешает этому?
Насколько я понял из старого форума проблема только в table.insert. Так вот чем table.insert отличается от обычных операций допустим сложения умножения (вроде бы то же модификация). И чем таблицы при модификации отличаются от простых переменных?
Что то я совсем запутался. Следуя вашим словам B={9,4,3,8} C=B таблица C это только ссылка на таблицу B тогда есть разница между записями а) C[1]=C[1]/2; table.sort(B) б) table.sort(B); C[1]=C[1]/2 Это так? И на предыдущие вопросы ответ те пожалуйста!?
Добрый день. В терминале обеспечивается физическая целостность данных. В случае с обычным присвоением a = b проблем нет - вы не сможете получить неопределенное значение переменной a. Либо значение до присвоения, либо после. В случае с table.insert проблема в том, что это не "атомарная" операция, а целая функция. которая делает следующее:
Добрый день. В терминале обеспечивается физическая целостность данных. В случае с обычным присвоением a = b проблем нет - вы не сможете получить неопределенное значение переменной a. Либо значение до присвоения, либо после. В случае с table.insert проблема в том, что это не "атомарная" операция, а целая функция, которая делает следующее: - все элементы с индексом больше либо равным заданному получают индексы на единицу больше; - указанный элемент вставляется по заданному индексу; Обращение в момент выполнения функции к элементам таблицы может привести к неопределенной ситуации. Для этого были сделаны потокобезопасные функции - получить доступ к таблице можно лишь после завершения их работы.
Michael Bulychev пишет: Для этого были сделаны потокобезопасные функции - получить доступ к таблице можно лишь после завершения их работы.
Поподробнее пожалуйста. Это значит, что при обращении к таблице из другого потока текущая операция будет приостановлена до окончания обновления таблицы?
Надо делать так, как надо. А как не надо - делать не надо.
Возможно насчет глобальных я не совсем корректно выразился. Выполнение функции sinsert заблокирует выполнение кода в другом потоке до окончания работы функции.
Michael Bulychev пишет: Выполнение функции sinsert заблокирует выполнение кода в другом потоке до окончания работы функции.
Давайте, чтобы не было разночтения сформулируем более точно. Выполнение функции sinsert заблокирует выполнение кода в другом потоке до окончания работы функции в любом случае или только при обращении из другого потока к таблице, модифицируемой sinsert? Другими словами, sinsert приостанавливает выполнение другого потока в любом случае или нет?
Надо делать так, как надо. А как не надо - делать не надо.
хэш - это число. В луа используется для хранения строковых данных. В луа таким образом обеспечивается быстрое сравнение строк, так как сравниваются фактически числа. Кроме того, хранятся лишь уникальные строки, что исключает избыточное хранение копий строк.
Можете изменить алгоритм таким образом, чтобы параллельный поток блокировался только в том случае, если происходит попытка одновременного доступа к модифицируемой таблице?
Надо делать так, как надо. А как не надо - делать не надо.
С колбеками, вроде, понятно: если в колбеке одного скрипта вызывается потокобезопасная функция, то работа основного потока QUIK и дополнительного main этого скрипта "замораживается" на время выполнения функции. А если потокобезопасная функция вызывается в main, окажет ли это влияние на потоки других скриптов?
Надо делать так, как надо. А как не надо - делать не надо.
Любое обращение к глобальным переменным, равно как и любая модификация стека в LUA происходит через критические секции. Исследования показывают, что нет в целом ряде случаев абсолютно никакой выгоды от многопоточности, если не используется соответствующая операционная система и многоядерные процессоры. Широко распространено и подтверждено на практике мнение, что число потоков - должно соответствовать числу ядер. Вот, кстати, статейка на тему: http://www.dtf.ru/articles/print.php?id=39888
Добрый день. Это нельзя сказать точно, тут, как говорится кто первый встал... Важен другой момент - при обычном insert возможна ситуация когда элемент t[1] уже существует, но еще ничем не заполнен. То есть isert это функция в процессе выполнения которой блокировка может случаться и освобождаться неоднократно. При использовании sinsert такого не случится - если элемент t[1] существует (t[1] ~= nil), то и его содержимое уже корректно заполнено.
Старатель пишет: С колбеками, вроде, понятно: если в колбеке одного скрипта вызывается потокобезопасная функция, то работа основного потока QUIK и дополнительного main этого скрипта "замораживается" на время выполнения функции. А если потокобезопасная функция вызывается в main, окажет ли это влияние на потоки других скриптов?
Но пока выполняется потокобезопасная функция основной поток терминала "заморожен", информация с сервера не поступает, колбеки не вызываются. Это вы называете "никак не влияет"?
Надо делать так, как надо. А как не надо - делать не надо.
Michael Bulychev, мне кажется или вы потеряли основную мысль обсуждения?
Цитата
Старатель пишет: С колбеками, вроде, понятно: если в колбеке одного скрипта вызывается потокобезопасная функция, то работа основного потока QUIK и дополнительного main этого скрипта "замораживается" на время выполнения функции. А если потокобезопасная функция вызывается в main, окажет ли это влияние на потоки других скриптов?
Надо делать так, как надо. А как не надо - делать не надо.
У меня такое ощущение, что это я вам рассказываю, как работает ваш программный продукт. Хотя наоборот было бы гораздо эффективней.
Скрипт 1:
Скрытый текст
Код
local bRun, sTime = true
local sClassCode, sSecCode = "QJSIM", "SBER"
function main()
while bRun do
PrintDbgStr("main1")
sleep(1000)
end
end
function OnStop()
bRun = nil return 0
end
function OnParam(class_code, sec_code)
if not bRun then return end
if sec_code ~= sSecCode or class_code ~= sClassCode then return end
local Time = getParamEx(class_code, sec_code, 'TIME').param_image
if Time ~= sTime then
PrintDbgStr("1: "..Time)
sTime = Time
end
end
Скрипт 2:
Скрытый текст
Код
local bRun, sTime
local sClassCode, sSecCode = "QJSIM", "SBER"
function main()
local t, n = {}, 5000000
for i = 1, n do t[i] = n - i end
PrintDbgStr("start")
bRun = true
table.ssort(t)
PrintDbgStr("end")
while bRun do sleep(100) end
end
function OnStop()
bRun = nil return 0
end
function OnParam(class_code, sec_code)
if not bRun then return end
if sec_code ~= sSecCode or class_code ~= sClassCode then return end
local Time = getParamEx(class_code, sec_code, 'TIME').param_image
if Time ~= sTime then
PrintDbgStr("2: "..Time)
sTime = Time
end
end
Запускаем - делаем выводы.
Надо делать так, как надо. А как не надо - делать не надо.
Старатель пишет: Какими? (Речь сейчас не идёт про длительную обработку колбека.)
Для чего мы завели такие функции и чего они позволяют избежать я уже объяснял. В Вашем примере использование ssort совершенно не к месту. Используйте просто sort.
Michael Bulychev пишет: Для чего мы завели такие функции и чего они позволяют избежать я уже объяснял. В Вашем примере использование ssort совершенно не к месту. Используйте просто sort.
Вы, наверное, не поняли: это псевдокод. Таким образом, я показал вам, что утверждение
Michael Bulychev, Прошу Вас, самым детальнейшим образом расписать, как устроено межскриптовое взаимодействие/влияние в QLUA -> интересует: 1. порядок инициализации главной виртуальной машины - > что после чего запускается, как и на каком этапе происходит цикл регистрации и опроса коллбеков. 2. Также прошу расписать в каких случаях создаётся новый lua-thread (имеется ввиду только в обычных скриптах. 3. (несовсем по теме, конечно, но... ) 1. в какое место совать свою GUI-билиотеку? в основное тело скрипта, 2. в майн 3. или создавать для этого новый поток ОС и делать в нём свою message-loop бо как диспетчеризация сообщений квиковским главным потоком уже будет не досягаема?
Michael Bulychev пишет: Согласитесь, что пример немного не жизненный?
Я что-то не понял, с чем вы спорите? Вы можете привести "жизненный пример", когда использование потокобезопасной функции в одном скрипте "никак не влияет" на другие скрипты?
Надо делать так, как надо. А как не надо - делать не надо.
Michael Bulychev пишет: Нет, просто нет такого механизма в Lua. за конкретным объектом должен следить сам пользователь.
Но в луа нет ни функций QLUA, ни возможности создания функции main в отдельном потоке. - Это все сугубо ноу-хау QUIK. Может быть,продолжая развитие данного направления, сделать необходимые механизмы синхронизации потоков для всех пользователей? Я для себя кое-что сделал. Но некоторые вопросы удобнее решить на стороне терминала .
честно сказать, я уже и на майн и на потоки согласен НО! Дайте примеры достойные подражания? А то - документация - никакая, техподдержка, если почитать их сообщения со старого и этого форума и сопоставить (благо MySQL сейчас может пользоваться каждый) друг другу - противоречит, разработчики - привыкли ограничиваться лишь парой фраз. В итоге, как говорится, "вот вам qlua и (ну вы поняли...)". При этом, сотрудники компании ещё сильно обижаются, когда их упрекают в отсутствии знания собственного продукта. Видать, писать, что "проблема будет исправлена в следующей версии" в этой компании уже давно вошло в привычку за 15 лет.
хочу привести реальный пример, из жизни. хоть он и несовсем по теме - но главное - суть: есть 3D-движок CryEngine - от вполне себе современной и раскрученной игры. Причём, он тоже поддерживает LUA. Так вот: чуть покопавшись в его SDK и примерах скриптинга - я чот не нашёл там ни повального использования метатаблиц, ни корутин, ни потоков. Там есть развитая библиотека уже встроенных на уровне движка объектов (Entity). Чтобы наследовать какой-то объект или свойство от другого объекта - там не надо писать полушаманский код на метатаблицах - всё сделано на уровне домохозяек и школьников - хочешь наследовать - вызови пару функций и будет тебе счастье. Насчёт доступа ке глобальным переменным, во многих скриптовых движках - уже давно для этого используют классы, т.е. глобальная переменная - это - тоже класс, причём встроенный в сам движок. Пользователь - вообще в данном случае не думает ни о каких потоках и синхронизации - он просто дёргает методы и навешивает на эту глобальную переменную - события. Список можно бесконечно продолжать. Хочется ещё раз спросить: для кого эта QLUA - затевалась? Кто целевая аудитория? Какие перспективы? Если всё - это для трейдеров - то это точно не для них, потому как разгребать за вами ваши же огрехи ценою своего счёта по причинам описанным выше - не хватит денег ни у кого. Если это для программистов - то программисты от него тоже - не в восторге. Им было бы куда проще и гибче писать на C++ и не быть ни в чём стеснёнными. Я не спорю, что сама по себе LUA - вполне себе достойный скриптовый язык. НО!!! Вы доведите её уже наконец, до ума, а не выпускайте на рынок вечно-сырой продукт.
Уважаемые разработчики, ответьте на такой вопрос: Является ли запись в файл значений того или иного набора переменных с помощью функции file:write() потокобезопасной? Иными словами, если в один и тот же файл будет производиться запись в коллбэках (типа OnParam, OnTrade, OnQuote и т.п.), а также в функции main(), то не приведет ли это к каким-то нежелательным или непредсказуемым последствиям?
Дмитрий пишет: Уважаемые разработчики, ответьте на такой вопрос: Является ли запись в файл значений того или иного набора переменных с помощью функции file:write() потокобезопасной? Иными словами, если в один и тот же файл будет производиться запись в коллбэках (типа OnParam, OnTrade, OnQuote и т.п.), а также в функции main(), то не приведет ли это к каким-то нежелательным или непредсказуемым последствиям?
write не является нашей функцией, это стандартная функция Lua, поэтому, затруднимся дать однозначный ответ. Попробуйте поискать ответ в сообществе Lua community