TGB (Все сообщения пользователя)

Выбрать дату в календареВыбрать дату в календаре

Страницы: 1 2 3 4 5 6 7 След.
Кривые шибки в QLua
 
Цитата
s_mike@rambler.ru написал:
TGB, прекратите фантазировать.
 Хотелось бы увидеть ваш комментарий (с возможными возражениями), но конкретный, с указанием строк в выложенном мною тесте.
----
Цитата
Daniil Pozdnyakov написал:
Ваше письмо получено, проблема изучается. Постараемся в ближайшее время дать ответ.
 Спасибо. Буду ждать обновления QUIK и после этого запускать свой тест.
Кривые шибки в QLua
 
Где реакция поддержки?
----
  Третий раз (первый комментарий был написан 10.09.2021 07:46:28  https://forum.quik.ru/messages/forum10/message57872/topic5823/#message57872) обращаю внимание поддержки на то, что тест, выложенный 10.09.2021 07:46:28  в данной ветке,  в QUIK (8.13.1.16, 9.1.3.11 и 9.2.1.4 (с последними обновлениями), в QLua 5.3 демонстрирует ошибку в запусках колбеков.  Это подтверждено пользователем Anton (смотрите комментарий 61).
  Если перевести на простой язык, то диагностируется ошибка синхронизации выполнения потока запуска колбеков и потока main скрипта (и это после полутора года эксплуатации новых версий QUIK :!: ). Ошибки синхронизации могут проявляться как случайные сбои в сриптах пользователей в различные моменты времени.
  Что из выше написанного не понятно?
  А если непонятно, то где вопросы?
Кривые шибки в QLua
 
Просьба (повторная) к поддержке: довести содержимое моего комментария: https://forum.quik.ru/messages/forum10/message57872/topic5823/#message57872 до разработчиков QUIK.
  В QUIK 9.2.1.4 (с последними обновлениями) тестовый скрипт, выложенный в упомянутом выше комментарии, демонстрирует, по моему мнению, ошибку в запусках колбеков, в QLua 5.3 ( в  QLua 5.4 эта ошибка не диагностируется, но это не означает, что в 5.4 такой ошибки нет).
Кривые шибки в QLua
 
Цитата
Anton написал:
TGB ,  у меня для вас две новости, как водится:
1) в 5.3 воспроизводится буквально сразу, запущено 4 скрипта и заказаны все параметры по всем инструментам (на боевом);
2) в 5.4 в тех же условинях НЕ ВОСПРОИЗВОДИТСЯ.
 Действительно, в Qlua 5.4 тест ошибку не диагностирует.
---
 Спасибо Антону за его уточнение.
--
А где поддержка?
Кривые шибки в QLua
 
Цитата
Anton написал:
Все такое же, имена поменяйте. Там может вообще темплейт в сорце.
 Имена я способен поменять, но мы же обсуждаем не то что я могу сделать, а как это сделано в текущем QLua.
Цитата
Anton написал:
Это значит, что коллектор начинает агрессивничать и влезать в любую доступную дыру. Где он там дыру в мейне нашел, науке пока неизвестно.
В принципе, если обеспечено четкое разделение между потоками, среды исполнения Lua (то есть, она разделяемый ресурс с корректной синхронизацией доступа к ней) то это эквивалентно однопоточному Lua, в котором ошибки, конечно есть, но их мало.
Кривые шибки в QLua
 
Цитата
Anton написал:
lua_getglobal(s, "OnAllTrade");
  Что то, не  сильно, похоже на детали.  Например, не охватывается случай "OnParam".
А как вы обясните:
Цитата
Anton написал:
в 5.3 воспроизводится буквально сразу, запущено 4 скрипта и заказаны все параметры по всем инструментам (на боевом
----
Цитата
Anton написал:
Это lua_lock() + lua_getglobal() + lua_unlock(), совершенно бессмысленно это проделывать, точно зная, что в скрипте нет такой функции. Дискутировать лень.
 Ну, конечно, вместо lua_getglobal(...)  (кстати, lua_lock() и lua_unlock() выполняется внутри функции lua_getglobal), эквивалентной с точки зрения времени обращения, обращению к глобальной переменной, даже если этой переменной не существует, можно заняться более содержательным алгоритмом регистрации колбеков скриптов (где можно и ошибиться - замечательная возможность).
Кривые шибки в QLua
 
Цитата
Anton написал:
в 5.3 воспроизводится буквально сразу, запущено 4 скрипта и заказаны все параметры по всем инструментам (на боевом);
 Все-таки, воспроизводится.
----
Цитата
Anton написал:
в 5.4 в тех же условинях НЕ ВОСПРОИЗВОДИТСЯ.
 Ну. тогда АРКИ надо объявить, что в версия QLua 5.3 не работоспособна.
---
Цитата
Anton написал:
колбеки так и запускаются, плюс-минус детали.
  Раскажите детали. Мне это было бы интересно.

 
Цитата
Anton написал:
Если не был объявлен, квик его не будет дергать. Очень даже хорошая оптимизация, иначе квик бы на каждое событие разыскивал необъявленные функции во всех скриптах, что несколько затратно, учитывая локи.
  Вы, наверное, знаете, что обращение lua_getglobal (<Основной State в котором запускается колбек>, <Имя колбека>) это эквивалентно обращение в тексте скрипта к переменной скрипта (тоесть. выполняется быстро). Это же обращение к полю таблицы. Или вы думаете, что это не так? Тогда подискутируем.
  А если это так, то о каком "разыскивании по всем скриптам" идет речь, когда происходит обращение к глобальной таблице, определяемой <Основной State в котором запускается колбек>.
  Вообще то, мне было бы интересно пообщаться с главным разработчиком QUIK. Но вы же, похоже не главный?
Кривые шибки в QLua
 
Поддержка понимает, что пока не будут устранены "кривые, мерцающие, редкие" ошибки QLua, на нее будет постоянно валиться вал разнообразных ошибок из  различных функциональностей QLua?
   Если бы я был разработчиком QLua, то в первую очередь занимался бы устранением именно "кривых" ошибок. Это глобальные ошибки, которые могут проявляться у пользователя в любых местах его скриптов, вводя в заблуждения относительно источника ошибок.
Кривые шибки в QLua
 
Я не очень понимаю в чем могут быть проблемы запуска колбеков QLua.
 Вот вариант как это можно сделать просто ( C-API Lua):
Код
   if ( lua_getglobal (<Основной State в котором запускается колбек>, <Имя колбека>) == LUA_TFUNCTION)     // запись и проверка переменной колбека скрипта в стек
   { 
       if ( lua_pcall(<Основной State в котором запускается колбек>, <Количество параметров колбека>, <Список параметров колбека>)  ~= 0 )   // запуск колбека 
      {
          <Обработка ошибки при запуске колбека>
      }
    }
   else    //  в переменной колбека не функция
   {
        <Обработка ошибки пользователя, задавшего в качестве колбека не функцию>
   }


Этот вариант обеспечивает возможность (отсутствующую в существующей версии QLua) замены пользователем функции, вызываемой в качестве колбека, при исполнении скрипта.
Кривые шибки в QLua
 
Просьба к поддержке довести содержимое этого комментария до разработчиков QUIK.
-----
  В версиях QUIK (8.13.1.16  и   9.1.3.11), похоже, есть ошибка, демонстрируемая кодом скрипта, который выложен в комментарии далее.
   Этот скрипт появился в результате анализа редко возникающей «мерцающей» ошибки (похожей на ошибки QLua, описанные Старателем в данной ветке), когда в переменной сразу после присвоения ей значения, это значение на следующем шаге оказывалось искаженным.
   При одновременном запуске трех экземпляров скриптов в QUIKе, подключенного к учебному серверу, в разные моменты времени, но достаточно часто (~ c 10 минутным ин-тервалом) выдается сообщение о том, что параллельно (одновременно) выполняются байт-код потока колбека и байт-код потока main (смотрите текст скрипта). В существующей реализации QLua такого быть не должно. Можно предположить, что в QLua есть ошибка в реализации запуска колбеков.
---
Код скрипта:
Код

  --- Функции работы с очередями (написаны на "чистом" Lua без обращения к C-функциям)  ---
    local new  =   function  ()
        return  {first  =   1 , last  =   0 }
     end 
    ---
    local push  =   function  (self, v)
        local  last  =  self.last  +  1 
        self[last]  =  v
        self.last  =  last
        return  last
     end 
    ---
    local pop  =   function  (self)
       local  first  =  self.first
       if  first  >  self.last  then   return   nil   end 
       local  v  =  self [first]
       self.first  =  first + 1 
       self[first]  =   nil 
       return  v, first
     end 
    ---
    local size  =   function  (self)
        return  self.last  -  self.first  + 1 
     end 
-----
--------- Создание очереди------
local  Queue_QUIK = new()
---------------------------------------

---  Основной поток обработки колбеков "обходит", запушенные на выполнение скрипты, с тем чтобы по событиям запускать их колбеки.
--  При этом должна быть обеспечена корректная синхронизация выполнения байт-кода колбека таким образом, что он не может выполняеться 
--  параллельно с байт-кодом потока main.
----------------------
local for_OnParam = 2 -- Множитель количества записей в очередь ----
local N_OnParam = 0
--- OnParam написана на "чистом" Lua без обращения к C-функциям  ---
function OnParam(p1, p2)
    for i = 1, for_OnParam do 
      N_OnParam = N_OnParam + 1
      -- Зпаись события  ---
      push (Queue_QUIK, {'OnParam', N_OnParam, {p1, p2}})   --  1. здесь создаются таблицы и может быть запущена автоматическая сборка мусора, 
                                                                                            --     которая работает для всей инсталяции Lua и не является потокобезопасной ---                                                                              
   end 
end
   
 ----   Обработка событий QUIK  (написана на "чистом" Lua без обращения к C-функциям) ----      
local function handle_events()   
      ----- ####  Для отладки ---
   local OnParam_begin = N_OnParam   
   local size_Queue_QUIK = size(Queue_QUIK)
   ---------------------------------
   ---  Чтение очереди событий -----
   local ms, first_q = pop (Queue_QUIK) 
      
    while ( ms  )   do        --- Есть события --- 
       -------------------------------
        ---  Чтение очереди событий -----      
        ms, first_q = pop (Queue_QUIK)  --Queue_QUIK: pop()         
   end
    ---   
    for i = 1, 1000 do      end  ---- нагрузка   ####  Отладка ---
   
    if N_OnParam ~= OnParam_begin then   --  Счетчик N_OnParam может иpмениться только в OnParam  
                                                              --  А это означает, что одновременно (параллельно) работают поток main и основной 
                         --  поток обработки колбеков, что недопустимо.
   --- это C-функция, но она вызывается только если  N_OnParam ~= OnParam_begin 
         message ( ' Параллельное выполнение колбека и потока main:  N_OnParam - OnParam_begin = ' .. tostring(N_OnParam - OnParam_begin)
                        .. '    size_Queue_QUIK = ' .. tostring(size_Queue_QUIK) )
    end      
    ----
end      
--------------------------------------------------------------------------------------------------------------------
--------
IsRun = true
function main()
    -------------------
    while IsRun do 
        handle_events()  ----   функция чтения событий OnParam ---
        sleep(2)  
    end
  ------------------
end   
   
function OnStop()
     IsRun = false
    return 10000   
end
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
 
В моем комментарии https://forum.quik.ru/messages/forum10/message57220/topic5823/#message57220
в п.2 было описано предложение по добавлению интерфейса работы с событиями QUIK.
 Ниже выложен код модуля реализации этого предложения на «чистом» Qlua, а также шаблон использования этого модуля. В этом шаблоне демонстрируется схема обработки событий фондового рынка и событий таблиц QUIK.
Для подключения модуля к шаблону его надо сохранить в файле под именем even_handling_module.lua в папку хранения кода запуска QUIK (info.exe).
 Код модуля и шаблона можно использовать свободно. При его распространении желательна ссылка на меня.
 Описание использования модуля приведено в его коде и коде шаблона, описывающего схему обработки событий QUIK.
----
Код модуля:
Код
--[[     TGB      ----   Модуль реализации обработки событий QUIK с использованием очередей событий  фондового рынка и событий таблиц QUIK ---

                                                                               Краткая спецификация модуля.
1. Реализуется схема взаимодействия main с колбеками через две потокобезопасные эффективные очереди, одна из которых обслуживает колбеки 
фондового рынка, а вторая, колбеки событий таблиц QUIK, созданных скриптером;
2. При работе обработке колбеков есть две функции: <функция подписки на события фондового рынка>
 и <функция подписки на события пользовательских таблиц >; в этих функциях скриптер может, в виде списка (в таблице) подписаться на события 
 в соответствии с существующими именами колбеков; реализация подписки сведена к автоматическому созданию (скрытых) от пользователя  
 функций колбеков, записывающих свои параметры с добавлением «от кого параметры» в соответствующие очереди;
3. Для работы с очередями по новой схеме есть две функции чтения соответственно очередям;
 при чтении очередей в считываемой таблице передаются: <имя события>, <время записи в очередь>, <параметры в том виде, как они описаны, в существующих колбеках>.
                При работе по этой схеме, QLua для скриптера становится однопоточным и снимаются многие сложные проблемы. 
----
                              !!  Колбеки OnInit и OnStop обрабатываются как обычно.
-------------------------
--]]
----   Функции работы с очередями (выложенные на форуме Старателем) ------
--- При использовании между потоком колбеков и потоком main  потокобезопасные 
local Queue  =  {
     new  =   function  (self)
        return  setmetatable({first  =   1 , last  =   0 }, {__index  =  self})
     end ,
     push  =   function  (self, v)
        local  last  =  self.last  +  1 
        self[last]  =  v
        self.last  =  last
        return  last
     end ,
     pop  =   function  (self)
        local  first  =  self.first
        if  first  >  self.last  then   return   nil   end 
        local  v  =  self[first]
       self.first  =  first + 1 
       self[first]  =   nil 
        return  v
     end ,
     size  =   function  (self)
        return  self.last  -  self.first  + 1 
     end 
}
--------- Создание очередей-----------
local  Queue_QUIK = Queue:new()
local  Queue_QUIK_tbl = Queue:new()
   ----- Функции чтения очередей -------
local function Queue_evn_QUIK()  return Queue_QUIK: pop()  end 
local function Queue_evn_QUIK_tbl()  return Queue_QUIK_tbl: pop()  end 
----- Функции запроса текущих размеров  очередей -------
local function sizeQueue_evn_QUIK()  return Queue_QUIK: size()  end 
local function sizeQueue_evn_QUIK_tbl()  return Queue_QUIK_tbl: size()  end 
--  Конец Функции работы с очередями  ---------------------------------------

              local function f_nil ()  end 
            ---     Переменные  событий фондового рынка -------
             OnAccountBala nce = f_nil        --- изменение позиции по счету
             OnAccountPosit ion = f_nil          --- изменение позиции по счету
             OnAllTr ade = f_nil                       --- новая обезличенная сделка
             OnClea nUp = f_nil                       --- смена торговой сессии
             OnCl ose = f_nil                            --- закрытие терминала QUIK или выгрузка файла qlua.dll
             OnConnec ted = f_nil                    --- установление связи с сервером QUIK
             OnDepoLi mit = f_nil                    --- изменение бумажного лимита
             OnDepoLimitDel ete = f_nil         --- удаление бумажного лимита
             OnDisconnec ted = f_nil               --- отключение от сервера QUIK
             OnF irm = f_nil                             --- получение описания новой фирмы
             OnFuturesClientHold ing = f_nil        --- изменение позиции по срочному рынку
             OnFuturesLimitCha nge = f_nil         --- изменение ограничений по срочному рынку
             OnFuturesLimitDel ete = f_nil            --- удаление лимита по срочному рынку
--             OnI nit = f_nil                                 --- инициализация функции main
             OnMoneyLi mit = f_nil                  --- изменение денежного лимита
             OnMoneyLimitDel ete = f_nil       --- удаление денежного лимита
             OnNegD eal = f_nil                       --- новая заявка на внебиржевую сделку или изменение параметров существующей заявки на внебиржевую сделку
             OnNegTr ade = f_nil                     --- новая сделка для исполнения или изменение существующей сделки для исполнения
             OnOr der = f_nil                             --- новая заявка или изменение параметров существующей заявки
             OnPa ram = f_nil                           --- изменение текущих параметров 
             OnQu ote = f_nil                            --- изменение стакана котировок
--             OnS top = f_nil                              --- остановка скрипта из диалога управления
             OnStopOr der = f_nil                    --- новая стоп-заявка или изменение параметров существующей стоп-заявки
             OnTr ade = f_nil                            --- новая сделка или изменение параметров существующей сделки
             OnTransRe ply = f_nil                   --- ответ на транзакцию
------                     
            local  unsubscribe_tbl =    ---- Функции отписки  ----
          {
               ['OnAccountBalance'] = function ()   OnAccountBala nce = f_nil   end
             , ['OnAccountPosition'] = function ()   OnAccountPosit ion = f_nil   end
             , ['OnAllTrade'] = function ()   OnAllTr ade = f_nil   end
             , ['OnCleanUp'] = function ()   OnClea nUp = f_nil  end
             , ['OnClose'] = function ()   OnCl ose = f_nil  end
             , ['OnConnected'] = function ()   OnConnec ted = f_nil  end
             , ['OnDepoLimit'] = function ()   OnDepoLi mit = f_nil  end
             , ['OnDepoLimitDelete'] = function ()   OnDepoLimitDel ete = f_nil  end
             , ['OnDisconnected'] = function ()   OnDisconnec ted = f_nil  end
             , ['OnFirm'] = function ()   OnF irm = f_nil  end
             , ['OnFuturesClientHolding'] = function ()   OnFuturesClientHold ing = f_nil  end
             , ['OnFuturesLimitChange'] = function ()   OnFuturesLimitCha nge = f_nil  end
             , ['OnFuturesLimitDelete'] = function ()   OnFuturesLimitDel ete = f_nil  end
--             , ['OnInit'] = function ()   OnI nit = f_nil  end
             , ['OnMoneyLimit'] = function ()   OnMoneyLi mit = f_nil  end
             , ['OnMoneyLimitDelete'] = function ()   OnMoneyLimitDel ete = f_nil  end
             , ['OnNegDeal'] = function ()   OnNegD eal = f_nil  end
             , ['OnNegTrade'] = function ()   OnNegTr ade = f_nil  end
             , ['OnOrder'] = function ()   OnOr der = f_nil  end
             , ['OnParam'] = function ()   OnPa ram = f_nil  end
             , ['OnQuote'] = function ()   OnQu ote = f_nil  end
--             , ['OnStop'] = function ()   OnS top = f_nil  end
             , ['OnStopOrder'] = function ()   OnStopOr der = f_nil  end
             , ['OnTrade'] = function ()   OnTr ade = f_nil end
             , ['OnTransReply'] = function ()   OnTransRe ply = f_nil  end
          }
         -----
            local  subscribe_tbl =    ---- Функции подписки  ----
          {
               ['OnAccountBalance'] = function ()   OnAccountBala nce = function (...)  Queue_QUIK: push ({'OnAccountBalance', os.time (), {...}} ) end   end
             , ['OnAccountPosition'] = function ()   OnAccountPosit ion = function (...)  Queue_QUIK: push ({'OnAccountPosition', os.time (), {...}} ) end    end
             , ['OnAllTrade'] = function ()   OnAllTr ade = function (...)  Queue_QUIK: push ({'OnAllTrade', os.time (), {...}} ) end     end
             , ['OnCleanUp'] = function ()   OnClea nUp = function (...)  Queue_QUIK: push ({'OnCleanUp', os.time (), {...}} ) end  end
             , ['OnClose'] = function ()   OnCl ose = function (...)  Queue_QUIK: push ({'OnClose', os.time (), {...}} ) end  end
             , ['OnConnected'] = function ()   OnConnec ted = function (...)  Queue_QUIK: push ({'OnConnected', os.time (), {...}} ) end  end
             , ['OnDepoLimit'] = function ()   OnDepoLi mit = function (...)  Queue_QUIK: push ({'OnDepoLimit', os.time (), {...}} ) end  end
             , ['OnDepoLimitDelete'] = function ()   OnDepoLimitDel ete = function (...)  Queue_QUIK: push ({'OnDepoLimitDelete', os.time (), {...}} ) end  end
             , ['OnDisconnected'] = function ()   OnDisconnec ted = function (...)  Queue_QUIK: push ({'OnDisconnected', os.time (), {...}} ) end  end
             , ['OnFirm'] = function ()   OnF irm = function (...)  Queue_QUIK: push ({'OnFirm', os.time (), {...}} ) end  end
             , ['OnFuturesClientHolding'] = function ()   OnFuturesClientHold ing = function (...)  Queue_QUIK: push ({'OnFuturesClientHolding', os.time (), {...}} ) end  end
             , ['OnFuturesLimitChange'] = function ()   OnFuturesLimitCha nge = function (...)  Queue_QUIK: push ({'OnFuturesLimitChange', os.time (), {...}} ) end  end
             , ['OnFuturesLimitDelete'] = function ()   OnFuturesLimitDel ete = function (...)  Queue_QUIK: push ({'OnFuturesLimitDelete', os.time (), {...}} ) end  end
--             , ['OnInit'] = function ()   OnI nit = function (...)  Queue_QUIK: push ({'OnInit', os.time (), {...}} ) end  end
             , ['OnMoneyLimit'] = function ()   OnMoneyLi mit = function (...)  Queue_QUIK: push ({'OnMoneyLimit', os.time (), {...}} ) end  end
             , ['OnMoneyLimitDelete'] = function ()   OnMoneyLimitDel ete = function (...)  Queue_QUIK: push ({'OnMoneyLimitDelete', os.time (), {...}} ) end  end
             , ['OnNegDeal'] = function ()   OnNegD eal = function (...)  Queue_QUIK: push ({'OnNegDeal', os.time (), {...}} ) end  end
             , ['OnNegTrade'] = function ()   OnNegTr ade = function (...)  Queue_QUIK: push ({'OnNegTrade', os.time (), {...}} ) end  end
             , ['OnOrder'] = function ()   OnOr der = function (...)  Queue_QUIK: push ({'OnAccountBalance', os.time (), {...}} ) end  end
             , ['OnParam'] = function ()   OnPa ram = function (...)  Queue_QUIK: push ({'OnParam', os.time (), {...}} ) end  end
             , ['OnQuote'] = function ()   OnQu ote = function (...)  Queue_QUIK: push ({'OnQuote', os.time (), {...}} ) end  end
--             , ['OnStop'] = function ()   OnS top = function (...)  Queue_QUIK: push ({'OnStop', os.time (), {...}} ) end  end
             , ['OnStopOrder'] = function ()   OnStopOr der = function (...)  Queue_QUIK: push ({'OnStopOrder', os.time (), {...}} ) end  end
             , ['OnTrade'] = function ()   OnTr ade = function (...)  Queue_QUIK: push ({'OnTrade', os.time (), {...}} ) end  end
             , ['OnTransReply'] = function ()   OnTransRe ply = function (...)  Queue_QUIK: push ({'OnTransReply', os.time (), {...}} ) end  end
          }
         -----   
        -- Подписаться на события фондового рынка --         
        ---  Ключи таблицы - имена событий ----
        local function  subscribe (tbl)
         local err ={},  f
            for k, v in next, tbl do
             f = subscribe_tbl [k]
                if f then f() else  err[#err +1] = k  end
            end   
            return err          
        end
      
      -- Отписаться от событий фондового рынка --
        ---  Ключи таблицы - имена событий ----
        local function  unsubscribe (tbl)
         local err ={},  f
            for k, v in next, tbl do
             f = unsubscribe_tbl [k]
                if f then f() else  err[#err +1] = k  end
            end   
            return err       
        end
      
      --- Вывод данных о состоянии подписки на события фондового рынка  ---
       local function  condition_subscribe ()
             local tbl= {}
            ---
              tbl['OnAccountBalance'] = OnAccountBalance ~= f_nil or nil
              tbl['OnAccountPosition'] = OnAccountPosition ~= f_nil or nil
              tbl['OnAllTrade'] = OnAllTrade ~= f_nil or nil 
              tbl['OnCleanUp'] = OnCleanUp  ~= f_nil or nil
              tbl['OnClose'] = OnClose ~= f_nil or nil 
              tbl['OnConnected'] = OnConnected ~= f_nil or nil 
              tbl['OnDepoLimit'] = OnDepoLimit ~= f_nil or nil 
              tbl['OnDepoLimitDelete'] = OnDepoLimitDelete ~= f_nil or nil
              tbl['OnDisconnected'] = OnDisconnected ~= f_nil or nil 
              tbl['OnFirm'] = OnFirm ~= f_nil or nil
              tbl['OnFuturesClientHolding'] = OnFuturesClientHolding ~= f_nil or nil
              tbl['OnFuturesLimitChange'] =  OnFuturesLimitChange ~= f_nil or nil
              tbl['OnFuturesLimitDelete'] =OnFuturesLimitDelete ~= f_nil or nil
--              tbl['OnInit'] = OnInit ~= f_nil or nil 
              tbl['OnMoneyLimit'] = OnMoneyLimit ~= f_nil or nil
              tbl['OnMoneyLimitDelete'] = OnMoneyLimitDelete ~= f_nil or nil
              tbl['OnNegDeal'] = OnNegDeal ~= f_nil or nil
              tbl['OnNegTrade'] = OnNegTrade ~= f_nil or nil
              tbl['OnOrder'] = OnOrder ~= f_nil or nil
              tbl['OnParam'] = OnParam ~= f_nil or nil
              tbl['OnQuote'] = OnQuote ~= f_nil or nil
--              tbl['OnStop'] = OnStop ~= f_nil or nil
              tbl['OnStopOrder'] = OnStopOrder ~= f_nil or nil
              tbl['OnTrade'] = OnTrade ~= f_nil or nil
              tbl['OnTransReply'] = OnTransReply ~= f_nil or nil
            
          return  tbl   
        end
      
        ----------------------------------------------------------------      
            
 ----   Обработка событий QUIK  ----      
 ----   
local tbl_QUIK_fun  --- Для хранения функции обработки событий таблиц QUIK ---
local tbl_fun            --- Для хранения таблицы функции обработки событий фондового рынка ---
local period = 100    -- период счетчика для выдачи сообшений ---
local event_counter  = 0  -- текущее значение циклов "разгребания" очередей событий ---
local event_counter_mess  = 0  -- счетчик для выдачи сообщений --
local event_counter_mess  = 0  -- счетчик для выдачи сообщений --
local read_latency_max  = 0   -- максимальная задержка чтения очередей событий (сек.)--
------------------------------------------------------------------
         
      local tbl_QUIK = {} ---- Общая таблица состояния обработки таблиц QUIK ---
      ---- Функция обаботки колбеков таблиц QUIK ----
      local function callback_tbl_QUIK(...)  --- (NUMBER t_id, NUMBER msg, NUMBER par1, NUMBER par2
          local par ={...}
         par = par[1]
          if tbl_QUIK[par] then  -- Запись в очередь событий таблиц QUIK.  os.time () - дата_время записи ---
              Queue_QUIK_tbl: push ({par, os.time (), {...}} )
          end
      end 
      
      -- Подписка на события таблицы QUIK  ---
      local function  subscribe_tbl_QUIK (t_id, f_t)
            if    tbl_QUIK[t_id]  then return nil end   
          tbl_QUIK_fun = tbl_QUIK_fun or f_t 
          if SetTableNotificationCallback ( t_id,  callback_tbl_QUIK) == 1 then
             tbl_QUIK[t_id] = 1
            return nil 
         else
            message('!!! Ошибка задания колбека для таблицы: ' ..  t_id)
            error('!!! Ошибка задания колбека для таблицы: ' ..  t_id)
            return nil 
         end
        end
         --   Отписка от событий таблицы QUIK ----
        local function  unsubscribe_tbl_QUIK (t_id) -- Отписка от событий таблицы QUIK  ---
          if tbl_QUIK [t_id]   then tbl_QUIK [t_id] = nil  end
         if  next (tbl_QUIK) == nil then  tbl_QUIK_fun = nil  end
        end
      --  Состояние подписки на события таблицы QUIK ----
      local function condition_subscribe_tbl_QUIK ()  --- Состояние подписки на события таблиц QUIK ---
         return tbl_QUIK
      end
      -----------------------------------------------
---  Установить функции обработки событий  ----
local function install_event_handling_functions(tbl_f)
   tbl_fun = tbl_f
   event_counter  = 0  
   event_counter_mess  = 0 
   event_counter_max  = 0 
   read_latency_max  = 0
   --- Подписка на события фондового рынка ---
   --- ! Ключи таблицы - имена событий ---- 
   unsubscribe (unsubscribe_tbl)  ---- Отписаться от всех событий
   subscribe (tbl_f)   ---  Подписка на события всей таблицы tbl_fun (для записей с функциями обработки событий)
end
 
---- Функция обработки всех событий QUIK:  function handle_events(lim)   -----
--  Параметр lim (по умолчанию равен 1000000)  определяет максимальное количестко событий, обрабатаваемых за один вызов функции --
--- Если очереди событий пусты, то функция завершается.
-- Результат (их три):  1) количество обработанных событий; 2) максимальное количество событий за один вызов функции; 
-- 3) максимальная задержка (в сек.) между записью и чтением событий
local function handle_events(lim)   
   lim = lim or 1000000
   local f_ms
   ---  Чтение очередей событий -----
    local ms_tbl = Queue_QUIK_tbl: pop()   -- ms_tbl = {t_id,  os.time (), {NUMBER t_id, NUMBER msg, NUMBER par1, NUMBER par2}}
   local ms = Queue_QUIK: pop()             -- ms_tbl = {<Имя события>, os.time (), {<Параметры события>}}
   local os_time, os_time_d
   ---
    while (ms_tbl or ms  )   do        -- Есть события --- 
       -------------------------------
      os_time = os.time ()
       event_counter  = event_counter  + 1
      event_counter_mess = event_counter_mess + 1
      if event_counter_mess >= period then
         event_counter_mess = 0
         message ( '!! Длительный цикл обработки событий: ' .. event_counter )
      end
       --- Обработка событий таблиц QUIK ---
       if ms_tbl then   
--  message ( tostring(ms_tbl[1]))
          os_time_d = os_time - ms_tbl [2]
          if read_latency_max < os_time_d then read_latency_max = os_time_d  end
          if tbl_QUIK_fun then  tbl_QUIK_fun (unpack (ms_tbl[3]))  end       -- Запуск функции обработки событий таблиц QUIK ---
       end   
     ----------- События  фондового рынка ---
       if type (tbl_fun) == 'table' then 
           if ms then  
            os_time_d = os_time - ms [2] 
               if read_latency_max < os_time_d  then read_latency_max = os_time_d end      
              f_ms = tbl_fun[ms[1]]
               -- message ( tostring(ms[3][2]))
               if f_ms then f_ms (unpack (ms[3])) end  -- Запуск функции обработки событий фондового рынка ---
           end
      end
      if event_counter >= lim then break  end  
        ---  Чтение очередей событий -----      
         ms_tbl = Queue_QUIK_tbl: pop()   -- ms_tbl = {t_id,  os.time (), {NUMBER t_id, NUMBER msg, NUMBER par1, NUMBER par2}}
        ms = Queue_QUIK: pop()       
   end
   
    ---  Ведение счетчиков циклов обработки событий ----
   if event_counter_max < event_counter then
      event_counter_max = event_counter
   end
   event_counter_rt = event_counter
    event_counter  = 0
    event_counter_mess  = 0
   read_latency_max  = 0
   return event_counter_rt, event_counter_max, read_latency_max
end
      
-----------------------------------------------
 return { 
--   Queue = Queue                                                 --- Функции работы с очередями ----
-- , Queue_evn_QUIK = Queue_evn_QUIK                -- Чтение параметров событий рынка ---
-- , Queue_evn_QUIK_tbl = Queue_evn_QUIK_tbl      -- Чтение параметров событий таблиц QUIK  ---
   sizeQueue_evn_QUIK = sizeQueue_evn_QUIK    -- Текущий размер очереди событий рынка ---
 , sizeQueue_evn_QUIK_tbl = sizeQueue_evn_QUIK_tbl   -- Текущий размер очереди событий таблиц QUIK   ---
 , subscribe = subscribe                                       -- Подписаться на события фондового рынка --
 , unsubscribe = unsubscribe                                -- Отписаться от событий фондового рынка --
 , condition_subscribe = condition_subscribe         -- Сотояние подписки на события фондового рынка --
 , subscribe_tbl_QUIK = subscribe_tbl_QUIK          -- Подписаться на события таблиц QUIK --
 , unsubscribe_tbl_QUIK = unsubscribe_tbl_QUIK   -- Отписаться от событий таблиц QUIK --
 , condition_subscribe_tbl_QUIK = condition_subscribe_tbl_QUIK  -- Сотояние подписки на таблицы QUIK  --
 , install_event_handling_functions = install_event_handling_functions  --  Установить функции обработки событий  ----
 , handle_events = handle_events    -- Функция обработки всех событий QUIK  -----
 }  ---
--------------------------------------




----
Код шаблона:

Код
local even_handling_module = require('even_handling_module')  -- Подключение модуля обработки событий QUIK  ---
---
local subscribe = even_handling_module.subscribe
local unsubscribe = even_handling_module.unsubscribe
local condition_subscribe = even_handling_module.condition_subscribe
local subscribe_tbl_QUIK = even_handling_module.subscribe_tbl_QUIK
local unsubscribe_tbl_QUIK = even_handling_module.unsubscribe_tbl_QUIK
local condition_subscribe_tbl_QUIK = even_handling_module.condition_subscribe_tbl_QUIK
local sizeQueue_evn_QUIK = even_handling_module.sizeQueue_evn_QUIK   
local sizeQueue_evn_QUIK_tbl = even_handling_module.sizeQueue_evn_QUIK_tbl
local install_event_handling_functions = even_handling_module.install_event_handling_functions
local handle_events = even_handling_module.handle_events

IsRun = true

function main()
      
      --- Работа с событиями таблиц QUIK -----
      ----- Функция обработки событий таблиц QUIK  -----
      --  FUNCTION (NUMBER t_id, NUMBER msg, NUMBER par1, NUMBER par2)  ---
      --  t_id – идентификатор таблицы;  msg – код сообщения;  par1 и par2 – значения параметров определяются типом сообщения msg  ----
        local function tbl_QUIK_fun (t_id, msg, par1, par2) 
              message ( 'tbl_QUIK_fun (t_id: ' .. t_id)
       end       
      -----
    TableQUIK=AllocTable()  -- Создание таблицы QUIK --
        AddColumn(TableQUIK, 1, "Легенда", true, QTABLE_STRING_TYPE, 6)
        AddColumn(TableQUIK, 2, "Год", true, QTABLE_STRING_TYPE, 6)
        AddColumn(TableQUIK, 3, "Месяц", true, QTABLE_STRING_TYPE, 6)
        AddColumn(TableQUIK, 4, "День", true, QTABLE_STRING_TYPE, 6)
        CreateWindow(TableQUIK)
        for i=1,10 do -- Цикл заполняет ячейки
                 InsertRow(TableQUIK,-1)
                 for j=1,4 do
                          SetCell(TableQUIK, i, j, tostring(i).."-"..tostring(j))
                 end
        end
      
    TableQUIK1=AllocTable()  -- Создание таблицы QUIK --
        AddColumn(TableQUIK1, 1, "Легенда", true, QTABLE_STRING_TYPE, 6)
        AddColumn(TableQUIK1, 2, "Год", true, QTABLE_STRING_TYPE, 6)
        AddColumn(TableQUIK1, 3, "Месяц", true, QTABLE_STRING_TYPE, 6)
        AddColumn(TableQUIK1, 4, "День", true, QTABLE_STRING_TYPE, 6)
        CreateWindow(TableQUIK1)
        for i=1,10 do -- Цикл заполняет ячейки
                 InsertRow(TableQUIK1,-1)
                 for j=1,4 do
                          SetCell(TableQUIK1, i, j, tostring(i).."-"..tostring(j))
                 end
        end
      ---
        subscribe_tbl_QUIK (TableQUIK, tbl_QUIK_fun)  --- Подписка на события TableQUIK
       subscribe_tbl_QUIK (TableQUIK1, tbl_QUIK_fun)   --- Подписка на события TableQUIK1
  --   unsubscribe_tbl_QUIK (TableQUIK)    --- Отдписка от событий TableQUIK1
   --- Конец  Работа с событиями таблиц QUIK  -----
   
   
   ---  Работа с событиями фондового рынка ----
    ---    Функции обработки событий фондового рынка ---
    local function F_OnParam(p1, p2)
 --      message ( 'Тикер: ' .. tostring(p2))
    end
   --  
    local function F_OnAllTrade(t)
       message ( 'F_OnAllTrade: ' )
    end   
   
   local function F_OnConnected(t)
       message ( 'F_OnConnected: ' )
    end   
   
   ---- и т.д  ----
   -------------------------------------------------------------------
    ------  !!!  Для перехода на обработку событий в очередях, в скрипте достаточно к именам функций колбеков добавить префикс 'F_'
   ---  Таблица функций обработки событий фондового рынка  (параметры как в соответствующих колбеках) -----
    local tbl_fun =  
          {    
               ['OnAccountBalance'] = F_OnAccountBalance   --- Имя функции обработки события OnAccountBalance  --
             , ['OnAccountPosition'] = F_OnAccountPosition   -- и т.д.  ---
             , ['OnAllTrade'] = F_OnAllTrade
             , ['OnCleanUp'] = F_OnCleanUp
             , ['OnClose'] = F_OnClose
             , ['OnConnected'] = F_OnConnected
             , ['OnDepoLimit'] = F_OnDepoLimit
             , ['OnDepoLimitDelete'] = F_OnDepoLimitDelete
             , ['OnDisconnected'] = F_OnDisconnected
             , ['OnFirm'] = F_OnFirm
             , ['OnFuturesClientHolding'] = F_OnFuturesClientHolding
             , ['OnFuturesLimitChange'] = F_OnFuturesLimitChange
             , ['OnFuturesLimitDelete'] = F_OnFuturesLimitDelete
--             , ['OnInit'] = F_OnInit
             , ['OnMoneyLimit'] = F_OnMoneyLimit
             , ['OnMoneyLimitDelete'] = F_OnMoneyLimitDelete
             , ['OnNegDeal'] = F_OnNegDeal
             , ['OnNegTrade'] = F_OnNegTrade
             , ['OnOrder'] = F_OnOrder
             , ['OnParam'] = F_OnParam
             , ['OnQuote'] = F_OnQuote
--             , ['OnStop'] = F_OnStop
             , ['OnStopOrder'] = F_OnStopOrder
             , ['OnTrade'] = F_OnTrade
             , ['OnTransReply'] = F_OnTransReply
          }
         
    install_event_handling_functions (tbl_fun)   -- Установка таблицы функций обработки событий фондового рынка --- 
    ----
    for i, v in next, condition_subscribe() do
        message( 'Скрипт подписан на событие фондового рынка ' .. i )
    end
     ---  Работа с событиями фондового рынка ----
    -------------------
    while IsRun do 
        ---- Функция обработки всех событий QUIK:  function handle_events(lim)   -----
        --  Параметр lim (по умолчанию равен 1000000)  определяет максимальное количестко событий, обрабатаваемых за один вызов функции --
        --- Если очереди событий пусты, то функция завершается.
        --  Результат (их три):  1) количество обработанных событий в вызове функции; 2) максимальное количество обработанных событий за один вызов функции; 
        -- 3) максимальная задержка (в сек.) между записью и чтением событий (в вызове функции).
        local event_counter, event_counter_max, read_latency_max = handle_events()  ----   Обработка всех событий QUIK  ----
      if event_counter > 0 then  -- В очередях были события ----
            message ( 'event_counter: ' .. event_counter ..  ';  read_latency_max: ' .. read_latency_max  )
      end   
       ----  Обработка в main остального -----
   
   
       ----  Конец Обработка в main остального -----
        sleep(2)  
  end
  ------------------
end   
   
function OnStop()
     IsRun = false
    DestroyTable(TableQUIK)
     DestroyTable(TableQUIK1)
    return 10000   --  !!  По истечении этого интервала времени (в млсек.), данного скрипту на завершение работы, функция main() завершается принудительно. 
                                -- При этом возможна потеря системных ресурсов.   ! Если функция не выдает значение, то по умолчанию оно 5000 (5 сек.)
end

Робот как источник пассивного дохода?
 
Цитата
Pavel написал:
на счете будет оставаться 500, всё что заработаю планирую выводить.
 Вы знаете долларовых миллиардеров, заработавших свои состояния на внутридневной торговли на бирже?
 Банки, имеющие ресурсы, позволяющие нанимать совешенно продвинутных аналитиков фондового рынка и айтишников, и имеющие возможность создавать дочерние предприятия, занимающие внутридневной торговлей, предпочитают зарабатывать на комиссиях по обслуживанию такой торговли. Вас это не наводит ни на какие размышления?
 Если бы кто то мог гарантированно получать прибыль 15% годовых в долларах, мы бы это увидели.
Поиск инструмента по названию
 
Цитата
Виталий написал:
Все заработало как следует - терминал перестал падать.
  Вы в какой версии Quik работаете?  При выкладывании ошибок надо указывать версию QUIK, в которой эта ошибка возникает.
Кривые шибки в QLua
 
Цитата
Старатель написал:
и код в сообщении  #24  в частности.
  Ответьте, пожалуйста, есть ли в этом коде вызов стандартных функций? Если есть, то какие и как часто?
Нехватка видеопамяти
 
Цитата
nikolz написал:
пора бы усвоить что халява - она и есть халява.Во-первых, весь квик - это официально бесплатный продукт.
  Это вам так брокеры рассказывают, но при этом в ваших комиссиях брокеру незримо сидит некий процент отчисления за QUIK.
Так что за QUIK пользователь платит и ARQA материально зависит от пользователей.
Кривые шибки в QLua
 
Цитата
s_mike@rambler.ru написал:
и спамить тоже прекращайте.
 
Цитата
s_mike@rambler.ru написал:
и спамить тоже прекращайте.
  Это, конечно, аргумент :smile:  Особенно с учетом того, что вы мне не начальник.
Кривые шибки в QLua
 
Цитата
s_mike@rambler.ru написал:
TGB, прекратите фантазировать.этот код (усложненный) работает в сотнях (может тысячах, я не знаю) копий роботов, из числа выложенных  на сайте и написанных под заказ.
   Вы что, никогда не сталкивались с ситуацией, когда программы использовались сотнями тысячами пользователями и в этих программах потом обнаруживались ошибки?
Кривые шибки в QLua
 
Цитата
s_mike@rambler.ru написал:
этот код (усложненный) работает в сотнях (может тысячах, я не знаю) копий роботов, из числа выложенных  на сайте и написанных под заказ.
 Я же написал, что, похоже, что код потокобезопасный.
 Но если вам все известно, то объясните, что происходит время от времени в коде Старателя?
Кривые шибки в QLua
 
Цитата
Старатель написал:
код в сообщении  #24  в частности.
      Выполненные мною в Lua 5.3 (5.4) тесты атомарности операций вставки/удаления полей в таблицу показали, что эти операции (в условиях реализован-ной многопоточности QLua) все-таки атомарны.  Возможно?, есть ситуации, не охваченные тестированием, когда атомарности может не быть. Если же таких ситуаций нет, то мое утверждение, что выложенный Старателем код Queue (с описанием редко возникающей ошибки) создает потокоопасные очереди, ошибочное.
Кривые шибки в QLua
 
Цитата
Старатель написал:
TGB ,  https://forum.quik.ru/messages/forum10/message57185/topic5823/#message57185 Это ваше сообщение?
Это мое сообщение, но
Цитата
TGB написал:
мы же обсуждаем код Queue_safe
Кривые шибки в QLua
 
Цитата
TGB написал:
TGB  написал:10000 обращений (запись, чтение, удаление) за 500 миллисекунд.Не смотря на то, что сам тест бестолковый, но холостой цикл за 0,5 сек не слишком ли много?
  Опять неточность (мы же обсуждаем код Queue_safe).
В моем обсуждаемом коде Queue_safe во фрагменте тестирования указано:
 --  1.  Этот фрагмент (использование потокобезопасных функций QLua)   (100 000 записей и чтений)  выполняется за ~3560 милисекунд ---
  ................
  --  2. Этот фрагмент (использование Queue_safe)   (100 000 записей и чтений)  выполняется за ~55 милисекунд ---
Кривые шибки в QLua
 
Цитата
Старатель написал:
И не увидел в вашем комментарии каких-то существенных отличий касательно использования метода pop().Больше похоже на спам вашего  OS_...
  Вы в комментарии https://forum.quik.ru/messages/forum10/message57219/topic6198/#message57219
 читали это:
2. Существенная особенность построения очередей в OS_Quesha состоит в том, что они строятся на таблицах, в которых после их создания, нет вставок или удалений их полей (записей). В процессе работы с очередями изменяются только значения существующих полей, обеспечивающих запись/чтения этих очередей. Структура таблиц очередей «заморожена». Это обеспечивает в многопоточном режиме возможность эффективной синхронизации работы с очередями на уровне их полей, а не на глобальном уровне самих очередей.
 Так вот, эта существенная особенность обеспечивает то, что приведенный в комментарии конкретный код модуля Queue_safe создания очередей между колбеками и main является потокобезопасным в существующем QLua, в отличие от выложенного вами Queue, который потокобезопасным не является, о чем я уже писал в этой ветке.
Кривые шибки в QLua
 
Цитата
Старатель написал:
local hour = 0+os.date('%H') выскочила такая ошибка: attempt to perform arithmetic on a nil value
  Ошибка, которую вы обнаружили, замечательна своей локализацией (всего одна строка кода).
---
  Я посмотрел в исходниках Lua 5.3 код функции os.date и то, как она вызывается на исполнение в коде Lua. Этот код не блокирует потоки в текущей версии QLua 5.3 (и это легко проверить).  При этом, os.date, формально, не является C-функцией, так как в внутри ее кода, без блокировки, используется среда исполнения  Lua (ее внутренние функции), формально не гарантирующая корректного параллелизма при ее использовании.  Это же относится к некоторым другим библиотечным функциям Lua, имеющим признак C-функций. В C-функциях можно использовать только C-API Lua. Использование внутренних функции Lua, без блокировки, в коде C-функций является ошибкой.
  В версии Lua 5.3 (а возможно и в 5.4), похоже, есть «дыра» в некоторых ее стандартных функциях, для работы с ними из разных потоков.
  При работе в однопоточном варианте Lua такая «дыра» проявить себя не может. Но, собственно, разработчики Lua не один раз заявляли, что поддерживают однопоточный вариант Lua, а остальное факультатив, с которым надо разбираться тем, кто встраивает Lua в свои решения.
------
   Конечно, можно попытаться анализировать  все коды стандартных функций с используемыми внутренними функциями Lua без блокировки («раскручивая» соответствующие цепочки вызовов внутренних функций Lua) с целью выяснения, вдруг, случайно, какие то, из них, корректны при работе в нескольких потоках. Но по-хорошему, при написании всех кодов модулей библиотечных функции Lua, из ее среды исполнения, должно быть доступно только ее API (обеспечивающее корректность обращения к Lua из разных потоков).
   В принципе, для разработчика QUIK есть простой вариант исправления, в исходниках QLua, стандартных функций с используемыми внутренними функциями Lua без блокировки:
в начале кода таких функций выполняется lua_lock, а при выходах из них (! их может быть несколько) выполняется lua_unlock.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
 
Цитата
Владимир написал:
Мне нет никакого дела до "проблем параллелизма в QLua" - мой скрипт считает, что он один такой работает, и про потоки и прочее знать ничего не знает - для него есть только прерывания от таймера, клавы или мыши.
Думать вы так, конечно, можете, а что же вы иногда жалуетесь на непонятные "падения" вашего скрипта? А может быть и кто то еще получает непонятные ситуации?
Как системщик вы, наверное, должны понимать, что вам (нам) не обеспечена более-менее надежная среда разработки и исполнения скриптов. Вы что против того, чтобы надежность QLua повышалась?  Если нет, то разработчик QUIK должен разбираться, с потоками, синхронизацией и т.д., часто, скрытыми API QUIK, но влияющими работу скриптов. И почему бы, если у кого есть такая возможность, не посодействовать ему, в этом, для нашей пользы?
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
 
Цитата
Владимир написал:
вся задача организации торговли прикладная с головы до пят, и любые попытки привнести сюда системные штучки-дрючки - тем более, глубоко системные, как в данном случае, ни к чему хорошему не приведут.
Очень филосовское замечание :smile:
Где вы видите системные штучки? Код написан на чистом Lua (даже циклов нет :smile:).
---
 Я не понял ваших замечаний. Что в коде не так?
 Здесь выложен конкретный код, который, возможно, пригодится для устранения ситуации,  описанной в комментарии: https://forum.quik.ru/messages/forum10/message54811/topic5823/#message54811
или для варианта модификации QLua, описанного в п.2 комментария: https://forum.quik.ru/messages/forum10/message57220/topic5823/#message57220
и освобождающего скриптера от проблем параллелизма в QLua, Этот код может оказаться интересным и еще кому-нибудь.
  При описании кода я коротко отметил его существенную особенность, Для кого-то из читателей будет понятно, почему это сделано так.  Что в этом плохого?
  Вы же можете пользоваться своими "безразмерными" прикладными очередями или, например, использовать безразмерную (очень простую) очередь, код которой приведен в описании упомянутой мною ситуации. Но скорее всего, вам не нужны никакие очереди. Ну и замечательно.
Кривые шибки в QLua
 
Цитата
Старатель написал:
это уже вне зоны ответственности скриптера, а ошибка в реализации многопоточной модели QLUA.
1. Для устранения вашей конкретной ситуации, возможно, подойдет вариант реализации очередей, приведенный в моем комментарии https://forum.quik.ru/messages/forum10/message57219/topic6198/#message57219
2. Вообще, существует сравнительно несложный вариант заметно улучшить QLua (сделав его однопоточным для скриптера) без изменения его внутренней архитектуры:
1) добавить в API QLua функцию <задание схемы обработки колбеков>, которую скриптер может (но не обязательно) вызвать в начале своего скрипта с параметром задания схемы;  если эта функция не вызвана, то колбеки обрабатывыются так, как это делается сейчас по старой схеме;  дополнительно, в этой функции можно бы задавать версию Lua, а возможно и еще что-нибудь;  при задании новой схемы, внутри QLua автоматически реализуется схема взаимодействия main с колбеками через две потокобезопасные эффективные очереди (как обеспечить их эффективность, наверное, понятно), одна из которых обслуживает колбеки фондового рынка, а вторая, колбеки событий таблиц QUIK, созданных скриптером;
2) при работе по новой схеме обработки колбеков, в API QLua добавить еще две функции: <функция подписки на события фондового рынка> и <функция подписки на события пользовательских таблиц >; в этих функциях скриптер может, в виде списка (в таблице) подписаться на события в соответствии с существующими именами колбеков;  реализация подписки разработчиком QUIK может быть сведена к автоматическому созданию (скрытых) от пользователя функций колбеков, вызываемых, как это делается сейчас, и записывающих свои параметры с добавлением «от кого параметры» в соответствующие очереди;
3) для работы с очередями по новой схеме в API QLua добавить две функции чтения (?возможно также и выполнения некоторых дополнительных функций), соответственно очередям;  при чтении очередей в считываемой таблице передаются: <имя события>, <время записи в очередь>, <параметры в том виде, как они описаны, в существующих колбеках>.
   При работе по второй схеме, QLua для скриптера становится однопоточным и снимаются многие сложные проблемы. Причем, остается возможность не затрагивать и тех скриптеров, которые по тем или иным причинам не станут уходить от старой схемы.
----
 Общая схема работы скриптера в новой схеме обработки событий QUIK.
<Заказывается новая схема обработки событий >
<Выполняется подписка (вместо написания функций колбеков) на обрабатываемые события QUIK>
<В функции main, в цикле  читаются две очереди и обрабатываются считанные параметры событий>
-------
 Мною была описан некий, как мне представляется, не сильно сложный вариант реализации избавления QLua от проблем параллелизма, связанных с его существующей реализацией.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
 
Реализация очередей в OS_Quesha.
1. Кроме ранее описанного контроля, в системе выполняется периодический контроль текущих размеров всех ее очередей.  При создании каждой очереди задается ее предельно-допустимый размер. Если текущий размер, какой то очереди превышает 75% предельно-допустимого, в системе начинает выдаваться об этом сообщение.
2. Существенная особенность построения очередей в OS_Quesha состоит в том, что они строятся на таблицах, в которых после их создания, нет вставок или удалений их полей (записей). В процессе работы с очередями изменяются только значения существующих полей, обеспечивающих запись/чтения этих очередей. Структура таблиц очередей «заморожена». Это обеспечивает в многопоточном режиме возможность эффективной синхронизации работы с очередями на уровне их полей, а не на глобальном уровне самих очередей.
  Далее выложен работающий код реализации очередей с учетом выше написанного для частного случая, когда один поток в нее пишет, а другой читает  (!не допустимы чтения или записи в нескольких потоках):
Код
---- Реализация циклических потокобезопасных очередей без синхронизации для случая, когда один поток в нее пишет, а другой читает  (!не допустимы чтения или записи в нескольких потоках)------
local Queue_safe = {
  ---  size_Queue - размер очереди  ----
  new = function (self, size_Queue)
    local  Queue = {}
    local  cycl = {}      -- таблица-массив хранения элементов очереди
    for i =1, size_Queue do 
        cycl[i] = 0 
   end
   Queue.cycl = cycl
    Queue.QueueLength = size_Queue  --- размер очереди    ---
    Queue.RecordPointer = 1   ---  указатель записи  (изменяется только "писателем")     ---
    Queue.ReadingPointer = 1 ---  указатель чтения  (изменяется только "читателем")     ---
   Queue.written_down = 0   --- количество записанных элементов ---
   Queue.read = 0  --- количество считанных элементов ---
    return setmetatable(Queue, {__index = self})     --- для переключения на Queue_safe при обращение в созданной таблице к push, pop, size  ----
  end,
  
  --- Записываемое в очередь значение не может быть nil  --
  --  Результат: 0 - запись выполнена;  1 -  запись не выполнена (нет места) 
  push = function (self, v)  
        if v == nil then  error(' !!! В очередь нельзя записывать  nil ')  end
      if  self.written_down - self.read >= self.QueueLength then      ----- некуда писать  ----
              return (1)   
        end
        local  cycl = self.cycl
        local pwt=  self.RecordPointer
      cycl [pwt] = v
      local pwf =  pwt +1
        if  pwf  > self.QueueLength then
             pwf=1
        end
        self.RecordPointer = pwf  --- следующая позиция для записи (возможно занятая) --   
      self.written_down = self.written_down + 1
        return (0)
  end,
 
  ---  Два результата: 1) элемент или nil;     2) признак: 0 - очередь после чтения пуста;  > 0 - количество непрочитанных элементов;   -1 - очередь пуста в момент чтения;
  pop = function (self)
      local n = self.written_down - self.read 
      if  n == 0 then
           return nil, -1  --- нет данных
      end
     local  cycl = self.cycl 
     local prt=  self.ReadingPointer
     local v = cycl [prt]
     cycl [prt] = 0      ---  чтобы не было "висячих" ссылок на ссылочные объекты  ----
      prt =  prt +1
      if  prt  > self.QueueLength then
            prt = 1
      end
     self.ReadingPointer = prt
     self.read = self.read + 1
     return  v,  n - 1 
  end,

  size = function (self)
    return self.written_down - self.read
  end
}
----------------------------------------------------------------------
                                                                                            ------  Тесты  -----
local T 
local v
--[[
 --  1.  Этот фрагмент (использование потокобезопасных функций QLua)   (100 000 записей и чтений)  выполняется за ~3560 милисекунд ---
T = {}
for j = 1, 100  do 
  for i = 1, 1000 do  --- запись в очередь
     table.sinsert (T, 'sd')   
  end

  for i = 1, 1000 do  --- чтение из очереди
     v = T[1]
    table.sremove (T, 1)
  end
end
do return end      ------
 -----------------------------------------------------------------
--]]

 --  2. Этот фрагмент (использование Queue_safe)   (100 000 записей и чтений)  выполняется за ~55 милисекунд ---
T = Queue_safe:new(1200) 
  
 for j = 1, 100  do 
  for i = 1, 1000 do  --- запись в очередь
     T: push('sd')
  end

  for i = 1, 1000 do  --- чтение из очереди
     v = T: pop()
  end
end
--------------------------------------------------------------

  Относительно выложенного кода можно отметить следующее.
1. Это сильно упрощенный, работающий вариант реализации очередей, которые используются в OS_Quesha.
2. Особенностью этих очередей, при их создании, является необходимость задания их предельного размера. При записи в очередь, выдается признак успешности этой записи, либо отсутствия места в очереди.
3. Работа с создаваемыми очередями потокобезопасна без синхронизации при их использовании в QLua между колбеками и main.
4. Скорость выполнения операций запись/чтение не зависит от текущей длины очередей (в отличие от очередей, реализуемых с помощью table.sinsert и table.sremove, в которых скорость операций с увеличением текущей длины очереди, резко падает).
Кривые шибки в QLua
 
Цитата
Старатель написал:
Абсолютно беспочвенное утверждение, говорящее об отсутствии понимания работы обсуждаемого кода.
 Вы имеете ввиду, что для записи и чтения в очередь используются свои указатели и, я бы с вами согласился, если бы не существовал общий объект, в котором это происходит (таблица хранения очереди в которую вставляются и из которой вычеркиваются элементы очереди). Вы уверены, что работа с таблицей при изменении ее структуры в Lua реализована потокобезопасно? Где это написано?
Кривые шибки в QLua
 
Цитата
Старатель написал:
В качестве разминки сделайте перезаказ обезличенных сделок (или переключитесь на другой сервер) ближе к концу торговой сессии и посмотрите, с какой задержкой будет обрабатываться ваша очередь и расход памяти скриптом.
  Очередь не моя, а разработчика QUIK.
  Мне не известно как вы обрабатываете обезличенные сделки (сколько это может занимать ресурсов ПК), поэтому я запустил тест для проверки времени выполнения потокобезопасных функций реализации только очереди:
Код
----  Скрипт -тест  ----
 --  Этот фрагмент выполняется  ~500 милисекунд ---
local T = {}
local v
for j = 1, 10  do 
  for i = 1, 1000 do  --- запись в очередь
     table.sinsert  (T, {'sdfdfmffmf', 57})
--     v = T[1]
--    table.sremove(T, 1)
  end

  for i = 1, 1000 do  --- чтение из очереди
 --    table.sinsert  (T, {'sdfdfmffmf', 57})
     v = T[1]
    table.sremove(T, 1)
  end
end


  10000 обращений (запись, чтение, удаление) за 500 миллисекунд.
Понятно, что тест искуственный (без взаимодействия с колбеками), но какое то представление о скорости работы очереди и допустимой ее длине он дает.
Заметного роста памяти QLua я не заметил.

Цитата
Старатель написал:
Цитата TGB  написал: В вашем коде, по вашей ссылке, используется в двух потоках потоконебезопасная очередь OnAllTrades.
И?
Это значит, что при работе с такой очередью могут возникать ошибки синхронизации, которые могут порождать наблюдаемые вами последствия.

==========================
Цитата
_sk_ написал:
Очередь, реализованная Старателем, в этом случае корректно работает и без блокировок.
  А что же ситуации время от времени возникают?
Кривые шибки в QLua
 
Цитата
Старатель написал:
Старатель  написал:
local hour = 0+os.date('%H')
выскочила такая ошибка: attempt to perform arithmetic on a nil value
 Меня заинтриговала ошибка, которую вы обнаружили, в таком коротком коде.
Напишите, пожалуйста:
  Как часто выполняется в скрипте приведенный вами фрагмент?
  Где это выполняется: в main или колбеках?
-----------------------
Цитата
Старатель написал:
Также  ошибка attempt to call a nil value (method 'pop') в 9.1 никуда не пропала. Откуда здесь nil?
В вашем коде, по вашей ссылке, используется в двух потоках потоконебезопасная очередь OnAllTrades.
В API QLua есть функции реализации потокобезопасной очереди, созданные разработчиком QUIK:  table.sinsert, table.sremove.
Пример использования потокобезопасной очереди: https://forum.quik.ru/messages/forum10/message56397/topic6356/#message56397
Работа функций OnStop() и SetCell(), Подвисает скрипт
 
Цитата
Roman Azarov написал:
Просьба уточнить, о каких конкретно функциях, вызываемых из OnStop(), идет речь?
  Цитата (не точная) из известной юморески: "Принесите справки от всех женщин, что вы на них не женаты."  :smile:
Отладка QUIK 8.13
 
Об атомарности операций.
 Рассуждения об атомарности операции без определения ее области реализации это рассуждение о погоде без определения, к чему это относится (к Арктике или Антарктиде).
 Все операции скрипта, по отдельности, команды байт-кода или вызов C-функций являются атомарными, но в тоже время, выполнение скрипта, в целом, может быть и не атомарным (потоконебезопасным). Это связано с тем, что между упомянутыми операциями могут возникнуть переключение потоков, изменяющее контекст выполнение локально-атомарных операций. На самом деле, для выяснения потокобезопасности (атомарности выполнения скрипта в целом) достаточно выявить общие данные, модифицируемые в main и в основном служебном потоке QUIK, генерирующем вызовы колбеков скрипта. Если таких данных нет (а это часто можно обеспечить), то бессмысленно гадать об атомарности отдельных операций скрипта (скрипт выполняется атомарно, то есть, потокобезопасно, если нет таких данных).
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
 
Дополнительно к тому, что было написано в моих предыдущих комментариях относительно OS_Quesha.
1. То, что написано в них, не относится к начальному «освоению» QLua. Это может оказаться интересным, наверное, тем, кто в этом «поварится» некоторое время, после которого проявятся те проблемы, о которых я пишу.
2. Моя позиция относительно любых средств разработки программ: они должны облегчать жизнь пользователя таких средств. Если есть возможность обеспечить такое, то пользователя надо, освобождать от сложных проблем параллельного программирования или обеспечения надежности разрабатываемых программ.
3. OS_Quesha, обеспечивая многопоточность скрипта, написанного на QLua, полностью (если не используются общие модифицируемые в нескольких потоках данные, для работы с которыми есть средства для «продвинутых» разработчиков) освобождают разработчика таких скриптов от проблем параллельного программирования и обеспечивает их надежность.
4. В продолжение моего комментария, в котором описаны средства обеспечения надежности скриптов QLua с использованием контрольных точек.
  Известными проблемами любых программ являются:
1) их возможные блокировки при обращении к разделяемым ресурсам (с синхронизацией доступа к ним);
2) их возможные зацикливания (из-за ошибок в них);
3) «утечка» памяти  (из-за ошибок в них).
 Не существует универсальных, автоматических решений этих проблем. Уже хорошим решением может быть: ранняя диагностика таких проблем и это обеспечивается в OS_Quesha.
 В OS_Quesha выполняется контроль:
1) блокировок ее потоков;
2) зацикливания ее потоков;
3) утечки памяти QLua;
4) утечки памяти самого QUIK.
 Так как нормальные автоматические обработки описанных выше ситуаций мне не известны (они, как правило, связаны с существенными ошибками в скрипте, или QUIK), то по ним выдается четкая диагностика, а далее есть два варианта: продолжение работы скрипта (с продолжением выдачи упомянутой диагностики) или его перезапуск (возможно с перезапуском QUIK).
   В обобщенной классификации, OS_Quesha является «форком QLua», и в нем нет тех проблем, которые описаны в моем комментарии, относительно QLua, в соседней ветке «Отладка QUIK 8.13»; https://forum.quik.ru/messages/forum10/message57036/topic6356/#message57036
Отладка QUIK 8.13
 
В предыдущих комментариях, при обсуждении конкретного, протестированого  в непрерывном недельном прогоне, решения (в виде мизерной правки в 4-х местах исходников QLua), исправляющего, по моему мнению, существующую в QLua ошибку, было написано много текста, в котором можно «сломать голову».

  На самом деле все достаточно просто.
    В QUIK запускается единственный служебный «основной» поток, который об-служивает колбеки всех запущенных скриптов пользователя и его созданных таблиц QUIK.
    В текущий момент существует, по крайней мере, два варианта, когда скриптер может, «случайно», выполнением кода своего скрипта, заблокировать «основной» поток (при этом перестают запускаться колбеки всех запущенных в QUIK пользователем скриптов и все скрипты «слепнут»:
1) скриптер написал непосредственно в запуске какого-то своего колбека длительно выполняющуюся функцию (почему бы нет?);
2) скриптер сумел написать в main длительно выполняющийся фрагмент байт-кода, в котором нет вызовов C-функций (почему бы нет?).
  Первый вариант лечится, если следовать рекомендациям разработчика QUIK по обработке колбеков.  При этом, все что делается в main пользователя, становится однопоточным (относительно «основного» потока). «Основной» поток, при обработке колбеков, выполняет только короткие записи параметров колбекков в очереди. Причем, в этом случае, при написании и редактировании скрипта, заниматься синхронизацией с «основным» потоком не надо вообще.
  Второй вариант скриптер сейчас может лечить каждый раз, при редактировании скрипта, анализируя  его текст на наличие фрагментов «длинных» байт-кодов и вставляя в них, в «?? нужных» местах какую-нибудь, функционально  пустую C-функцию.  Нужно ли это скриптеру, если это можно вылечить, внеся, предложенные мною, исправления в QLua?
  Могу ли быть ошибки, в предложенном мною? В любом коде ошибки могут быть, но это уже как-то протестировано (непрерывно в течении недель) да и разработчик QUIK может это потестировать.
Отладка QUIK 8.13
 
Цитата
Anton написал:
Потому что арка не знает, как устроен луа.
 Могут узнать, так как есть исходники Lua и это полное описание Lua (вы, что это не понимаете?).

Цитата
Anton написал:
И вы не знаете.
 Знаю. Так как есть исходники Lua. И вы можете узнать, никто не запрещает.

Цитата
Anton написал:
Если бы вы это предложение выкатили команде луа, еще куда б ни шло, там хоть последствия понимают.
 Команде Lua это не нужно. Как только вы встраиваете Lua в свою систему, за последствия отвечаете вы (почитайте в тексте исходников Lua комментарии; они же в свободном доступе).

Цитата
Anton написал:
Еще раз, в текущем луа есть удобная особенность атомарности исполнения байткода. Вы это хотите сломать. Я против самой идеи это ломать.
 Конечно, при этом исчезает интересная возможность многочасового гадания в коде скрипта на атомарность/неатомарность  :smile:, если не следовать рекомендациям разработчика QUIK по взаимодействию с колбеками. Но самое интересное, даже, если вы убежденный противник рекомендаций разработчика Quik и не используете потокобезопасную очередь между вызовом колбеков и main, то, если нет общих данных, модифицируемых в вызовах колбеков и в функциях вызываемых в main, то гаданием атомарность/неатомарность можно, вообще, не заниматься.
Цитата
Anton написал:
Как ее решить без ковыряния в кишках луа, я предложил.
Где ваш протестированный вами код?
Отладка QUIK 8.13
 
Цитата
Владимир написал:
TGB , Дык я же давал чуть не десяток предложений в одном флаконе, и чуть ли не все они были зарегистрированы.
  Вы за то, чтобы поток генерации колбеков блокировался фрагментами байт-кода?
  У вас есть конкретные замечания и возражения против моего конкретного протестированного предложения по устранению этих блокировок?
  Вы за то. чтобы был реализовано гипотетическое, "лабударно-завиральное", никак не проверенное предложение Anton, выдвинутое, как мне, но возможно ошибочно, кажется только для дискредитации того, что уже протестировано?
Отладка QUIK 8.13
 
Опять цитата не моя, а Владимира, Извиняюсь перед собой :smile:
Отладка QUIK 8.13
 
Цитата
TGB написал:
Скрипт свой я уже и не помню
 Я тоже свою систему почти не помню.
  Но вы же? в свое время? "нахлебались", по "полной", на таблицах QUIK (или нет). Вы что, хотите, чтобы и остальные пользователи получили "свое"?
  То, что вы просите, можно сделать самому. Вы, ведь, системный программист?
Мне, просто бывает интересно (когда есть время), как "кипит" "социальный бульон" в текущее время.
Отладка QUIK 8.13
 
swerg, извиняюсь.  В моем предыдущем комментарии все цитата от Anton.
Отладка QUIK 8.13
 
Anton , зачем вы все время требуете продолжение «марлезонского балета»?
Ну хорошо, продолжим.

Цитата
Anton написал:
Я писал сначала, что не надо луа патчить для решения вашей проблемы?
  На самом деле это проблема не моя. Для себя эту проблему я решил достаточно давно (аж в 2019г.,  когда разработал свою систему создания торговых роботов в QUIK). Утомлять вас здесь тем, как это у меня решено, я не буду.

Цитата
swerg написал:
Я написал, как решить ее без патча луа? Написал. Еще что-нибудь?
    Ну, наверное, вам бы стоило протестировать (на интервале, хотя бы, трех суток) предложенное вами решение у себя. И изложить его здесь с той же детальностью, как это сделал я.
 Наверное, из двух работающих решений можно бы выбрать то, которое лучше.
    Возможно, я бы и сам отказался от своего предложения. Я же не «упертый» и с дельными замечаниями, сделанными мне, легко соглашаюсь (можете посмотреть некоторые мои комментарии). А, кстати, почему вы так упорно боретесь против «форка lua»? Как то это сильно смахивает на борьбу за невинность девушки, которая уже больше года замужем.

Цитата
Anton написал:
Нагуглить для вас критическую секцию с таймаутом или сами сумеете?
Этого делать не надо, а лучше поищите закладки в моем коде  :smile: .
Отладка QUIK 8.13
 
Цитата
swerg написал:
Вообще ни о чем не говорит.
Я в начале 2021г. как-то сравнивал количество внешних функций Qlua и Lua. В Qlua их почти на сотню больше.
Каталог luac-скрипта, выполняемого через dofile
 
В Lua 5.4 у меня работает это.
Внутри откомпилированного скрипта, в начале:
<code>
-- Функция  ---
local function dofile_exe_path()
  local str
  for i = 2, 4 do --- поиск корневой функции, вызывающей script_path, начиная с функции в которой вызвана script_path
--     message (tostring(  debug.getinfo(i) ))
     if  debug.getinfo(i)  then   ----
    str = debug.getinfo(i, 'S').source
 else
    break
 end
  end
  return  str
end

local path_script
path_script = dofile_exe_path ()
message( path_script  )  
-- Результат message строка вида :   dofile('<Путь к оттранслированному скрипту>')

<code>
Далее, наверное, разберетесь сами.
Отладка QUIK 8.13
 
Я уже думал, что наш диалог завершен, но вы пишите такие фантазийные, детективные тексты, что мне стало интересно.
Цитата
Anton написал:
но тем, кто будет писать не как я, подложу-ка я закладочку и выкручивайтесь как выйдет". Вот так вот получается.
 Где я такое написал?
Если вам кажется, что это находится в опубликованном мною коде, то укажите, где вы нашли такую закладку?

Цитата
Anton написал:
Я хорошо понимаю, чего вы добиться хотите
 Вы что, экстрасенс  :smile: ?
Я же просто представил протестированный на своем стенде (на котором в сое время тестировал исправление ошибки синхронизации QLua) код исправления блокировок потоков длинными участками байт-кода. Это короткие правки в 4-х местах кода QLua. Их можно изучать визуально, проверять экспериментально, искать в них "до посинения" закладки.

Цитата
Anton написал:
Это невозможно в принципе
 Вот и замечательно! Хорошо построенная программная система должна быть защищенной.

Цитата
Anton написал:
В то же время у нас есть виртуальная машина, поэтому арка может добавить отслеживание зависших скриптов, если вместо кондовой CRITICAL_SECTION в качестве лока будет использовать нечто иное с возможностью таймаута на вход. Если таймаут истек и секция не захвачена, весь скрипт убивается как в случае ошибки, все дела. В идеале сначала дергается некий юзерский колбек с вопросом "тебя прибить или сам отвиснешь", если ответил отвисну и не отвис, в морг. Вот что вам стоило бы попросить у арки, а не луа ломать.
 И это предлагается вместо "прозрачных" правок в 4-х места кода, вносимых туда в течении пяти минут? Как-то очень сложно (я бы до такого не додумался  :smile: ) и вот уж куда удобнее вставлять закладки.
Отладка QUIK 8.13
 
Цитата
Anton написал:
теперь оказывается надо писать только так и никак иначе
Если вы это так поняли, то, придется, все-таки стоит пояснить.
  Конечно же, каждый разработчик может писать скрипты как хочет:
1) постоянно, после очередной редакции скрипта, анализируя код на его атомарность/неатомарность (марлезонский балет);
2) не заморачиваясь проблемама синхронизации с колбеками (вообще не зная что такое атомарность)
И это никак не связано с тем, останется ли блокировка потоков участками байт-кода (как это про-исходит сейчас) или это будет устранено.

Цитата
Anton написал:
этот марлезонский балет достал уже
Согласен.
Отладка QUIK 8.13
 
Цитата
Anton написал:
А на других примерах - произойдет. Это типичнейший паттерн вообще-то, как тут можно НЕ увидеть проблем...
 Похоже, примеры с вами можно бы было обсуждать бесконечно  :smile:
----
Цитата
Anton написал:
Об чем и речь, весь код У ВСЕХ будет в этих костылях просто потому, что вам кровь из носу хотелось чонить в квике починить, пусть даже и не сломанное.
 Опять декларации и страшилки. Но это же можно бы было сформулировать короче: «Не тронь!» :smile:
Вы что, это не читали?:
Цитата
TGB написал:
дело обстоит еще проще. Если вы знакомы с документом разработчика QUIK «Использование Lua в Рабочем месте QUIK.pdf», то его в разделе «2. Взаимодействие потоков Lua скрипта» описана рекомендуемая схема обработки колбеков фондового рынка, которую можно распространить и на обработку колбеков событий таблиц QUIK. Если придерживаться этой схемы, то проблем многопоточности (! из-за основного потока обработки колбеков) в скрипте пользователя не будет вообще: ни в «чистом» Lua-коде ни в смешанном. И не надо ни чем извращаться ни в одной строчке скрипта так как при этом он становится однопоточным (относительно основного потока обработки колбеков). Вы можете почитать комментарии, начиная с  https://forum.quik.ru/messages/forum10/message56387/topic6356/#message56387  , в которых это обсуждается с демонстрацией кодов, рекомендуемых разработчикам QUIK.   Если же в скрипте не используется схема обработки колбеков, рекомендованная разработчиком QUIK, то преобразование любого такого скрипта в функционально эквивалентный, но с рекомендованной схемой, элементарное.
  или вы убежденный противник решения разработчика QUIK, приведенного в указанном фрагменте текста?
  Попытаюсь сформулировать, то, что написано там более понятно и короче.
  Если использовать то, что написано в этом фрагменте, то никакой синхронизации с потоком, обрабатывающем колбеки  не требуется. Ни нужны никакие костыли. Не требуется многочасовой анализ кода скрипта на атомарность/неатомарность, (ворк/неворк  :smile: ). Причем, это справедливо как для существующих версий QLua, так и в случае реализации предлагаемого мною решения, устраняющего ошибку блокировки потоков длинными участками байт-кода.
 Сформулировать это еще короче я уже, наверное, не смогу  :smile:
Отладка QUIK 8.13
 
Цитата
Anton написал:
Модельку такую можно сделать, а как в реальной жизни к такому коду можно прийти, я прошу продемонстрировать.
  Пусть это и демонстрирует реальная жизнь :smile:

Цитата
Anton написал:
Видите? Я табличку атомарно спрятал в локальную переменную и спокойно удалил. Когда DestroyTable снимает лок, мейн видит вместо таблички нил и все правильно понимает.
Точно также, если переключение (! оно не может возникать внутри команд Lua-машины, а только между ними) в байт-коде вдруг возникнет после tid = nil, но до DestroyTable, то оно снимает лок, мейн видит вместо таблички нил и все правильно понимает. При этом исполнение кода в мейн не сможет блокировать поток обработки колбеков и DestroyTable тоже успешно выполнится. В чем вы видите проблемы?

Цитата
Anton написал:
После вашего улучшения такое без критической секции не сделаешь, а их в луа нет, если помните. Придется ради вот этой фигни извращаться. И так на каждой строчке.
 Я помню, что в Qlua есть потокобезопасные функции, обеспечивающие функциональность критической секции и нет проблем использовать их в представленном вами примере (вы с этим сами можете разобраться и я не буду тратить время на то, как это можно сделать), Я только не очень понимаю зачем это может потребоваться в приведенном вами примере?
 Но дело обстоит еще проще. Если вы знакомы с документом разработчика QUIK «Использование Lua в Рабочем месте QUIK.pdf», то его в разделе «2. Взаимодействие потоков Lua скрипта» описана рекомендуемая схема обработки колбеков фондового рынка, которую можно распространить и на обработку колбеков событий таблиц QUIK. Если придерживаться этой схемы, то проблем многопоточности (! из-за основного потока обработки колбеков) в скрипте пользователя не будет вообще: ни в «чистом» Lua-коде ни в смешанном. И не надо ни чем извращаться ни в одной строчке скрипта так как при этом он становится однопоточным (относительно основного потока обработки колбеков). Вы можете почитать комментарии, начиная с https://forum.quik.ru/messages/forum10/message56387/topic6356/#message56387 , в которых это обсуждается с демонстрацией кодов, рекомендуемых разработчикам QUIK.
  Если же в скрипте не используется схема обработки колбеков, рекомендованная разработчиком QUIK, то преобразование любого такого скрипта в функционально эквивалентный, но с рекомендованной схемой, элементарное.
Отладка QUIK 8.13
 
Цитата
Anton написал:
Было уже написано  в этой самой теме не мной. И другие подобные сценарии. Многие вещи, которые в 5.1 требовали длл и никак иначе, теперь можно сделать в скрипте. Вы это хотите сломать. Это уже достаточный аргумент, чтобы не поддержать идею. Можно и в обратную сторону спросить - а что это всем даст? Как скриптер от этого выиграет? Или хотя бы пример делающего что-то полезное кода без сишных вызовов, который иначе ну никак нельзя написать.
  Все, что вы написали (включая ссылку) как-то декларативно и нет конкретики. Типа, это не надо делать, потому что не надо.
 Но в вашем комментарии есть фразы, на которые я попытаюсь ответить или задать вопросы.
1.  Каким образом что-то будет ломаться, если будут переключение потоков внутри «чистого» кода Lua (байт-кода)?
---
 Сейчас переключение потоков в QLua возможно, и выполняется при вызове в скрипте C-функций, которых в рабочем скрипте обычно достаточно много (начиная со sleep). И при этом ничего не ломается.
  Что изменится в описанном выше качественно, если будут переключения на участках байт-кода? Ничего!  Вы же можете, без проблем, в существующий скрипт добавить, для своих целей, новые вызовы C-функций внутрь существующего байт-кода и это нормально.
 Предлагаемый мною вариант переключения внутри байт-кода это, по сути, добавление очень эффективного вызова «пустой», ничего не делающей C-функции через определенный интервал выполнения команд байт-кода. Это обеспечивает возможность переключения потоков внутри байт-кода и устранение блокировки потоков длительными фрагментами байт-кода.
  Интервал вызова «пустой» C-функции может быть таким (например, 1000), что дополнительные «окна» переключения потоков  практически никак не влияют на скорость выполнения скрипта (это проверено мною экспериментально). При этом разработчику скрипта. дополнительно к тому, чем занимается его скрипт, ничего делать не надо.

2.  Что это даст всем (скриптерам)?
 Сейчас, если в скрипте выполняется  длительный участок байт-кода main,  то на время его выполнения, блокируется выполнение основного потока, обрабатывающего колбеки всех запущенных скриптов пользователя и обслуживающего события таблиц QUIK. Все аналогично, если описанное выше, происходит в функции, вызванной в колбеке.
 -----
Для демонстрации выигрыша скриптера от реализации обсуждаемого предложения рассмотрим, например, следующую ситуацию.
У пользователя запущено два скрипта (почему бы нет, они будут выполняться в разных потоках):
первый скрипт продуктив, который реально торгует на рынке (обрабатывает колбеки);
второй скрипт продуктив, который тоже реально торгует на рынке (обрабатывает колбеки).
  Если во втором/первом скрипте в какой-то момент времени  будет обрабатываться длинный байт-код в main и при этом в нем вызовется колбек, то поток обработки колбеков всех скриптов будет заблокирован. При этом перестанут обслуживаться и колбеки первого/второго скрипта. Это может произойти неожиданно и в самом неподходящем месте и породить неприятные последствия для торгующего. Этого ожидает пользователь? Надо ли скриптеру, при каждой редакции своих скриптов анализировать свой код на возможность возникновения описанной ситуации или других похожих?
----
 Если бы было реализовано то, что я предлагаю, то описанных выше блокировок не было бы.
 Кто-то скажет, что описанный выше пример надуманный, редкий и так далее. Но, те, кто разрабатывал более-менее серьезные программы, наверное, понимают, что если есть баг в программе, то рано или поздно он может проявиться.
3. И вопрос Антону: все-таки, интересно, какую конкретную функциональность в своих разработках вы реализуете, использую блокировку потоков выполнением длинных участков байт-кода?
Отладка QUIK 8.13
 
Цитата
Anton написал:
А форк или не форк мне не интересно.
 Ну, не я же начал про  форки.  А ответил потому, что подумал, что, вдруг, узнаю что-то новое.

Цитата
Anton написал:
Вам стало скучно, вы придумали какую-то околесицу и пытаетесь ее всем навязать.
Насчет околесицы не согласен, почитайте наше с вами общение, начиная с комментария: https://forum.quik.ru/messages/forum10/message54757/topic6356/#message54757

Цитата
Anton написал:
Мне не нужны случайные переключения контекста посреди байткода. Мне они помешают.
  Это уже интересно.
Опишите как такие переключения вам мешают. Мне они никак не мешаю.
Отладка QUIK 8.13
 
Цитата
Anton написал:
Того же самого я не хочу достигать, бо не вижу проблемы в существующем поведении и, более того, считаю такое поведение весьма удачным, случайно оно возникло или намеренно.
То есть, вы вполне удовлетворены тем, что QLua является «форком луа» (если вы отвергаете все остальное, приведенное мною в обоснование того, что QLua, похоже, форк ) хотя бы по причине:
Цитата
TGB написал:
1) исходники Lua были изменены для обеспечения многопотоковости QLua (смотрите мой комментарий  https://forum.quik.ru/messages/forum10/message54696/topic6356/#message54696) ;
И тогда что это:
Цитата
Anton написал:
вы предлагаете создать форк луа и встроить в квик именно форк. Это дорога в ад. Надеюсь, в арке это понимают.
Отладка QUIK 8.13
 
1.
Цитата
Anton написал:
Там вы как раз неправильно делаете правильные вещи ) То же самое достигается без изменения кода луа.
  То, что я предложил очень конкретно, работает (прочитайте эту ветку сначала).
Где ваше предложение достичь того же самого без изменения кода Lua?

2. Здесь, как я понимаю, мы с вами обсуждаем конкретное предложение, протестированное  на моем стенде:
Цитата
TGB написал:
Прошло два месяца. Просьба к поддержки: сообщить результаты рассмотрения пожеланий.
 ----  
  Второе пожелание факультатив и, наверное, его стоит рассматривать после устранения критических ошибок, но первое пожелание (было отмечено сразу при описании пожеланий) это устранение ошибки.   Напоминаю:   Бывают ситуации зависания в QLua, когда основной поток обслуживания колбеков всех скриптов пользователя, а также таблиц QUIK (это не таблицы Lua), блокируется выполнением  длинного цикла пользовательской программы на «чистом» Lua, в котором нет ни вызова seep ни вызова других C-функций.  Это может порождать ошибки, которые для многих пользователей QLua (использующих несколько запускаемых скриптов)  являются неожиданными и труднообъяснимыми. Блокируются выполнения колбеков всех скриптов из-за выполнения длинного цикла пользовательской программы на «чистом» Lua в каком-то из запущенных пользователем скриптов.
-----
   Есть простой вариант реализации первого пожелания, кстати, совместимого со вторым  (далее список изменений реализующих этот вариант в в тексте исходни-ков Lua ):
1. В файле   lstate.h  после строки:  lu_byte allowhook;добавить: int Счетчик_для_переключения_State;
2. В файле   lstate.с  после строки:  L->errfunc = 0;добавить:  L->Счетчик_для_переключения_State = 0;
3. В файле   lstate.с  после строки:  L1->stacksize = BASIC_STACK_SIZE;добавить:  L1->Счетчик_для_переключения_State = 0;
4. В файле   lvm.с  после строки:  StkId ra;добавить:  
  if (++L->Счетчик_для_переключения_State > 1000) {   //  1000  надо задать кон-стантой  
     L->Счетчик_для_переключения_State = 0; lua_unlock(L); lua_lock(L);
  }
------------------------------------  
В чем проблема реализации первого пожелания?
  Вместо того, чтобы сделать конкретные замечания по выше предложенному, вы пускаетесь в филосовские рассуждения о том, после какой, внесенной в исходники Lua запятой, считать его «форк луа».  
   Причем, напомню вам, что по вашему же предложению (кстати, поддержанного в комментариях мною) были внесены разработчиком QUIK заметные изменения в обработку исключительных ситуаций Lua.  Наверное, вы ответите, что изменения в обработку исключений не делают Lua «форком луа» :smile: .
Страницы: 1 2 3 4 5 6 7 След.
Наверх