Добавить функции для отложения выполнения колбеков

Страницы: 1
RSS
Добавить функции для отложения выполнения колбеков
 
https://forum.quik.ru/messages/forum10/message55112/topic6356/#message55112

Добавить функции вида pauseCallbacks и resumeCallbacks, где первая приостанавливает вызовы многопоточных колбеков, а вторая возобновляет. Использование таких функций позволит избежать потери данных и обрушения скриптов в некоторых ситуациях.
 
А тупо в колбеке поставить флаг нужно ли его исполнять - не вариант?
 
Imersio Arrigo, во-первых проигнорированный колбек не будет исоплнен повторно. Во-вторых колбек вызванный при обработке очереди этого же колбека создает потерю данных.

Не было бы проблемы - не было бы просьбы её решить.
 
Дык проблемы и нет никакой.
 
Imersio Arrigo,в первом посте сразу же ссылка на тред, где у людей как раз такая пролема. Там собственно и попросили, я просто создал отделный тред и немного поточнее пожелание сформулировал.
 
Цитата
Артем написал:
Imersio Arrigo,в первом посте сразу же ссылка на тред, где у людей как раз такая пролема. Там собственно и попросили, я просто создал отделный тред и немного поточнее пожелание сформулировал.

Там намучено не пойми чего.

Цитата
Артем написал:
первая приостанавливает вызовы многопоточных колбеков

Что такое "многопоточный колбек"?

Цитата
Артем написал:
проигнорированный колбек не будет исоплнен повторно.

Так вы предполагаете, что после возобновления все "пропущенные" колбеки будут вызваны?? из вашего первого сообщения такое желание совершенно не очевидно.
 
swerg, вы сами прекрасно знаете что это за "многопоточные колбеки". Да, должна сохраняться очередь пропущенных колбеков и потом вызываться, на мой взгляд это должно было быть совершенно очевидно так что я не стал ничего расписывать.
 
Цитата
Артем написал:
swerg, вы сами прекрасно знаете что это за "многопоточные колбеки".

Если бы знал - я бы вас не переспрашивал.
В QLua есть понятие callback-функций, которые вызываются терминалом при определённых событиях. Вызов этот происходит в основном потоке работы терминала QUIK.

Вы придумали термин "многопоточные колбеки" - было бы хорошо, если бы вы объяснили что он означает.
Впрочем, пожелание ваше, быть однозначно понятым или нет - решать вам, ибо "на мой взгляд это должно было быть совершенно очевидно" - позиция крайне наивная.
 
swerg, мы тут все люди умные (точнее сказать я не считаю окружающих за идиотов), понимаем что просто пропускать колбеки с важной информацией это плохая задумка - стало быть надо их сохранять.

Обычно колбеки однопоточные - вызываются из того же треда, в котором работает скрипт, пока собственно скрипт лежит в спячке и ничего не делает. Тут ни у кого никаких проблем не возникает. Но ввиду особенностей квика, колбеки тут многопоточные - вызываются из чужого треда в любой момент, причём вызываться они могут прямо посреди выполнения другого кода. Иногда это прямым образом разрушает стек ВМ и скрипт падает с ошибками обращения к нилам, возможно с избавлением от Lua 5.1 эта проблема отпадёт. А еще иногда колбек вызывается в момент обработки очереди данных, которые собирает этот же колбек, из-за чего соответственно происходит разрушение очереди, из-за чего скрипт тоже падает с ошибками обращения к нилам, хотя тут целостность стека не нарушается, просто данные были удалены из другого треда.

Я говорил уже что от такой многопоточности надо избавляться, и делать скрипты Lua строго однопоточными. Колбеки можно вызывать из функции sleep, результат будет такой же только без всего этого многопоточного геморроя. Альтернативный вариант, без переписывания всей этой каши, это добавить вот такого рода две функции, чтобы заблокировать вызов колбеков когда не надо.
 
Цитата
Артем написал:
Но ввиду особенностей квика, колбеки тут многопоточные - вызываются из чужого треда в любой момент, причём вызываться они могут прямо посреди выполнения другого кода. Иногда это прямым образом разрушает стек ВМ и скрипт падает с ошибками обращения к нилам

Callback-функции вызываются в основном потоке работы терминала.
В "другом потоке" работает main().

Так что что там вызывается "посреди выполнения другого кода" - мне не понять.

Цитата
Артем написал:
А еще иногда колбек вызывается в момент обработки очереди данных, которые собирает этот же колбек, из-за чего соответственно происходит разрушение очереди, из-за чего скрипт тоже падает с ошибками обращения к нилам, хотя тут целостность стека не нарушается, просто данные были удалены из другого треда.

Callback-функции работают строго последовательно, т.к. выполняются все в одном потоке. Уберите код из main() (ну кроме заглушки про is_run) - и никакого "параллельного кода" у вас не останется, будет ровно то, что вы хотите - полностью однопоточный код без каких-либо проблем.

Так определение "многопоточных колбеков" будет уже или нет?
 
Цитата
Артем написал:
точнее сказать я не считаю окружающих за идиотов
Да я рад бы не считать, но они такую дичь говорят что появляются сильные сомнения.
Цитата
Артем написал:
Обычно колбеки однопоточные - вызываются из того же треда, в котором работает скрипт, пока собственно скрипт лежит в спячке и ничего не делает.
Щта? Колбек - по сути функция, вызываемая извне. Никогда нельзя говорить что она "в том же потоке". Никогда.
Цитата
Артем написал:
Но ввиду особенностей квика, колбеки тут многопоточные - вызываются из чужого треда в любой момент, причём вызываться они могут прямо посреди выполнения другого кода.
И это нормально. Это правильно. Событие во внешнем мире возникает независимо от твоего скрипта, и оно к нему асинхронно априори.
Цитата
Артем написал:
Иногда это прямым образом разрушает стек ВМ
ЩТА?? Причем тут стек ВМ?? Вообще, причем?
Цитата
Артем написал:
еще иногда колбек вызывается в момент обработки очереди данных, которые собирает этот же колбек, из-за чего соответственно происходит разрушение очереди, из-за чего скрипт тоже падает с ошибками обращения к нилам
Ээээ, батенька... Дык вы в гонки данных не умеете. Ну так с этого и надо начинать, а не требовать реализации каких-то непонятных костылей.
Цитата
Артем написал:
Я говорил уже что от такой многопоточности надо избавляться, и делать скрипты Lua строго однопоточными. Колбеки можно вызывать из функции sleep, результат будет такой же только без всего этого многопоточного геморроя. Альтернативный вариант, без переписывания всей этой каши, это добавить вот такого рода две функции, чтобы заблокировать вызов колбеков когда не надо.
Рекомендую читать букварь. Много думать.
И да, сразу, на будущее - если захватить лок в коллбеке и не вернуть его - квичек повиснет.

Цитата
swerg написал:
Так определение "многопоточных колбеков" будет уже или нет?
Видимо под "многопоточными колбеками" подразумевается ВНЕЗАПНЫЙ вызов колбека квичком, и ... "из-за чего соответственно происходит разрушение очереди, из-за чего скрипт тоже падает с ошибками" :)
 
Цитата
Imersio Arrigo написал:
Ээээ, батенька... Дык вы в гонки данных не умеете. Ну так с этого и надо начинать, а не требовать реализации каких-то непонятных костылей.
Подразумевая что для решения вопросов с гонками данных пользоваться такими вещами как локи, мутексы и семафоры это нинужно, да и сами они это непонятные костыли.


То что я предложил реализовать в виде флага это как раз потому, что просто локи ставить - квик зависнет. Тут еще конечно под "колбеками" понимаются прерывания, да и вообще система через задницу что никакие стандартные термины не подходят. Но я людей за идиотов не считаю - думаю что они сами всё это соображают - а оказывается что нет.
 
Цитата
Артем написал:
как локи, мутексы и семафоры это нинужно, да и сами они это непонятные костыли.
А. Ну если это костыли, тогда ок.

Цитата
Артем написал:
Тут еще конечно под "колбеками" понимаются прерывания
Тут я малость выпал из контекста: -какие-такие прерывания?
Цитата
Артем написал:
да и вообще система через задницу что никакие стандартные термины не подходят.
Можно поподробнее: -что именно через задницу?
 
Arrigo, тут "колбеки" функционируют как прерывания - при вызове он вычищает стек, загружает вектор, исполняет прерывание, и после выхода восстанавливает стек. При этом как бы исполнение кода идет в одном и том же VM Lua однопоточно, но из разных тредов. Восстановление стека не всегда бывает корректное, в силу неизвестных причин, отчего скрипты падают. А еще колбек может вклиниться в исполнение главного треда прямо посреди внутреннего цикла, например, если используется pairs в частности, отчего бывают потери данных, как раз из-за гонок и прочего геморроя. Это наверное наименее очевидное и частое проявление жопошности архитектуры, при этом наиболее критическое к работе системы. Кому это не видится как "через жопу" у того у самого руки оттуда растут - это просто диагноз. Есть более простые ляпы, например использование глобальных числовых констант вместо строковых идентификаторов и вообще С-образный интерфейс в целом вместо Lua-идиоматичных объектов с методами (причем не везде).
 
Цитата
Артем написал:
тут "колбеки" функционируют как прерывания - при вызове он вычищает стек, загружает вектор, исполняет прерывание, и после выхода восстанавливает стек. При этом как бы исполнение кода идет в одном и том же VM Lua однопоточно, но из разных тредов.
"тут" - это где? в квике? С каких это пор?

Весь остальной текст после цитаты обсуждать не вижу смысла. По очевидным причинам.

Цитата
Артем написал:
Есть более простые ляпы, например использование глобальных числовых констант вместо строковых идентификаторов и вообще С-образный интерфейс в целом вместо Lua-идиоматичных
Почему вдруг использование глобалов стало ляпом?
А С-подобный интерфейс отчего вдруг стал плохим?
 
Arrigo, тут уже люди много стен головами разломали по поводу квиковского оригинального подхода к многопоточности и связанных с этим проблем. Из недавнего:

https://forum.quik.ru/forum10/topic6356/
https://forum.quik.ru/forum10/topic5119/
https://forum.quik.ru/forum10/topic5823/

То что колбеки обрывают исполнение главного кода в произвольной точке* легко проверить, устанавливая разные значения глобальной переменной в разных местах и чтение этой переменной в колбеке. То что при вызове колбеков стек вычищается подтверждает debug.traceback.


*когда ВМ снимает удерживаемый лок, т.е. при вызове любой функции или при аллокации памяти
 
Цитата
Артем написал:
при вызове колбеков стек вычищается
Ничего там не вычищается. У колбеков свой стек отдельный, поэтому в нем и нет ничего.
 
Anton, понятно. Но как тогда основной стек ломается? Если ничего не трогать то и ошибок быть не должно - K.I.S.S. и все дела.
 
Цитата
Артем написал:
Но как тогда основной стек ломается? Если ничего не трогать то и ошибок быть не должно
Посмотрите на lua_rawequal, например. Она из сей без лока выполняется, по идее слоты никуда не денутся с текущего стека, сравнивай не хочу. Вроде на первый взгляд так и есть, а дальше там посмотрите, там и за строками лазит, и метаметоды может дергать, и на стек слоты добавлять. И все без лока. Вот один из примеров, как может стек поломаться, там еще есть такого добра, если порыться. А в идеальном мире не должен стек ломаться, да.
 
Цитата
Артем написал:
Тут еще конечно под "колбеками" понимаются прерывания, да и вообще система через задницу что никакие стандартные термины не подходят.

Вы зачем-то намешиваете совершенно разные термины, а потом пишете "никакие стандартные термины не подходят".
Отлично подходят, именно термин callback-функция, которая вызывается в момент нужного события.
Прерывания - это из другой оперы, не стоит их сюда примешивать.

Цитата
Артем написал:
Но я людей за идиотов не считаю - думаю что они сами всё это соображают - а оказывается что нет.

Достаточно лишь внятно и полно излагать ваши мысли, не думая, что "это и так очевидно".  Ведь то, что вам очевидно - может быть совершенно не очевидно другим, учитывая контекст, а в дополнение к этому и вы можете не совсем корректно и полно излагать ваши мысли, что вкупе с "и так очевидно" даёт совершенно гремучую смесь.

Вот тут нарисована картинка, которую даже стырили в документацию ARQA.
https://quik2dde.ru/viewtopic.php?id=16

Может она что-то для вас прояснит?

 
swerg, тут колбек останавливает выполнение главного треда в произвольный момент времени, а не запускается когда тот бездействует, и не исполняется параллельно. Так что функционально это прерывание а не колбек. Можно спорить конечно что прерывания это тоже колбеки так что всё правильно, но это ad dictionarium fallacy. Из контекста как раз должно было быть всё очевидно. Попробуйте тоже людей за идиотов не держать, не надо считать что если что-то недосказано значит ТС тупица а не то что это должно быть и так понятно всем кто имеет с этим дело так что подробно расписывать как для детей когда не спрашивают это как минимум неуважительно.
 
Цитата
Артем написал:
и не исполняется параллельно
Он исполняется параллельно. Другое дело, что сам луа - разделяемый ресурс, и доступ к нему потоков - по очереди. Если мейн и колбеки сишные в длл, они реально будут параллельно исполняться (пока снова не полезут в луа). Картинку выше для чистого луа можно мелко порезать горизонтальными линиями и в каждой полосе будет работать либо мейн, либо колбек, это правда, но так же работает вытесняющая многозадачность на одноядерном процессоре и никто не говорит, что это не многозадачность.
 
Цитата
Anton написал:
Цитата
Артем написал:
и не исполняется параллельно
Он исполняется параллельно.

Параллельно с чем? Хорошо бы уточнять, а то каша получается в понимании разными людьми.
 
Цитата
swerg написал:
Хорошо бы уточнять
Уточним. Основной поток квика, в котором вызываются колбеки, выполняется параллельно с потоками мейнов всех скриптов. Насколько эта параллельность честная (на отдельных ядрах) - определяется операционной системой и повлиять на это нельзя. В моменты конкуренции за разделяемый ресурс (луа-машину) основной поток квика ожидает освобождения ресурса потоком мейна того скрипта, в котором он собирается вызвать колбек; мейны других скриптов при этом продолжают выполняться и не влияют на ожидание. И обратно, поток мейна скрипта ожидает освобождения ресурса основным потоком квика; мейны и колбеки других скриптов опять же не влияют.
 
Цитата
Anton написал:
В моменты конкуренции за разделяемый ресурс (луа-машину) основной поток квика ожидает освобождения ресурса потоком мейна того скрипта, в котором он собирается вызвать колбек; мейны других скриптов при этом продолжают выполняться и не влияют на ожидание.
Точно не влияют? Нужно, чтобы потоки мейнов всех скриптов освободили разделяемый ресурс (луа-машину), не?
Надо делать так, как надо. А как не надо - делать не надо.
 
Цитата
Старатель написал:
Нужно, чтобы потоки мейнов всех скриптов освободили разделяемый ресурс (луа-машину), не?
Нет, лок у каждого скрипта свой. Можно, наверное, придумать какой-нибудь сценарий по типу обедающих философов, навскидку такой на ум не приходит.
 
Anton, т.о., вы опровергаете раннее написанное вами
Цитата
Anton написал:
Картинку выше для чистого луа можно мелко порезать горизонтальными линиями и в каждой полосе будет работать либо мейн, либо колбек

Допустим, работают три скрипта, в каждом из которых, выполняется байт-код в main продолжительностью t1, t2 и t3 соответвенно. В момент времени t возникает необходимость вызвать колбек в 1-м скрипте. При этом t < t1 < t2< t3.

Вопрос: в какой момент будет вызван колбек, и повлияет ли скрипт 3 на работу скриптов 1 и 2?
Надо делать так, как надо. А как не надо - делать не надо.
 
Цитата
Старатель написал:
Вопрос: в какой момент будет вызван колбек
Будет вызван в момент t1, второй и трейтий скрипты продолжат выполнять свой байткод, пока первый будет выполнять колбек. Только что проверил.

Цитата
Старатель написал:
повлияет ли скрипт 3 на работу скриптов 1 и 2?
Вот тут смешной ответ. Скрипт 3 не повлияет, а скрипт 1 повлияет. Как так? У квика не возникает необходимости вызвать колбек только в скрипте 1, он последовательно вызовет колбеки в скриптах 1, 2, 3, и всегда в этом порядке. Если какой-то из скриптов просто не определил колбек, ну слава богу, баба с возу. Так вот, если картинку перевернуть, то есть скрипт 1 самый тормозной (t1 самый длинный), то колбек в скрипте 1 все равно выполнится в момент t1, несмотря на то, что скрипты 2 и 3 уже закончили байткод и по идее можно было бы дернуть этот же колбек в них.
 
Цитата
Артем написал:
swerg, тут колбек останавливает выполнение главного треда в произвольный момент времени

Нет, не в произвольный.
В терминале возникает какое-то событие.
1) Терминал доделывает все свои дела, в том числе полностью завершается выполнение Lua-кода колбеков, отрисовывает интерфейс если надо и т.д.
2) Выбирает событие из своей очереди
3) Вызывает Lua-колбек произошедшего события (если таковой имеется), этот колбек до конца выполняется (т.е. до выхода из колбека), ведь так?
4) Если есть еще активные скрипты с таким же колбеком - все такие колбеки последовательно вызываются и завершаются (выходом из них)
Всё это в рамках одного основного потока терминала
5) После этого терминал обрабатывает свой код, связанный с данным событием (никакие колбеки не вызываются в этот момент)
6) Терминал переходит к следующему пришедшему событию и далее на пункт 2)

Где ж вы тут видите "произвольный момент времени"? Нет произвольного момента, колбеки выполняются строго поочерёдно и лишь тогда, когда
а) все ране вызванные колбеки (причем всех скриптов) полностью завершили свою работу
б) терминал "сознательно" вызывает колбеки, когда "все к этому готово", а не "внезапно по событию".

Цитата
Артем написал:
Так что функционально это прерывание а не колбек.

Очередное событие в очереди может висеть сколько угодно, если какой-то колбек будет слишком долго выполняться, верно ведь? так что ни о каком прерывании "внезапном" речи нет.
 
Цитата
Старатель написал:
т.о., вы опровергаете раннее написанное вами
Таки нет. Ранее написанное - с точки зрения одного скрипта. Представьте другую картинку, посередине поток квика, а слева и справа ДВА потока мейнов двух скриптов. Если смотреть только на пару "левый скрипт - квик" или только на пару "правый скрипт - квик", все сказанное в силе. Да и в целом общая картинка тоже порезана горизонтальными линиями, только для левой и правой частей они не совпадают. Не знаю, без картинки трудно наверное представить.
 
Цитата
Старатель написал:
В моменты конкуренции за разделяемый ресурс (луа-машину) основной поток квика ожидает .....

На мой взгляд вы куда-то не туда роете. Ну т.е. там, где нет практической пользы.
Для практической пользы достаточно считать, что все main() работают параллельно, и параллельно с ними работают callback'и.
Параллельно - значит любая часть кода этих main() и callback'ов может быть выполнена в произвольном порядке.
Нужен точный порядок - надо придумывать синхронизацию, да. Иначе просто считать, что любой кусок кода может быть выполнен в любой момент.

На мой взгляд это всё, что требуется учитывать для практического использования.
 
Артем,
я таки напомню мой вопрос, адресованный вам, на который вы упорно стесняетесь дать ответ:

Цитата
Что такое "многопоточный колбек"?

Ответ от вас хотелось бы услышать.
 
Цитата
Anton написал:
У квика не возникает необходимости вызвать колбек только в скрипте 1, он последовательно вызовет колбеки в скриптах 1, 2, 3, и всегда в этом порядке. Если какой-то из скриптов просто не определил колбек, ну слава богу, баба с возу. Так вот, если картинку перевернуть, то есть скрипт 1 самый тормозной (t1 самый длинный), то колбек в скрипте 1 все равно выполнится в момент t1, несмотря на то, что скрипты 2 и 3 уже закончили байткод и по идее можно было бы дернуть этот же колбек в них.


Со скриптом 1 понятно.
Вы, наверное, хотели сказать, что в таком случае скрипты 2 и 3 вызовут колбек не по окончании работы своего байт-кода, а будут ждать скрипт 1, и вызовут колбек в момент t1 + dt (время на обработку колбека предыдущими скриптами).
В любом случае, мы имеем взаимное и неочевидное (в том смысле, что не возможно предугадать) влияние скриптов друг на друга.
Надо делать так, как надо. А как не надо - делать не надо.
 
Старатель,  да, все так. Угадывать особо и не нужно, если у нас среднее время выполнения колбека достаточно мало, все будет работать, с поправкой на вызываемый "тупящими" колбеками джиттер. Если среднее время велико (больше среднего времени между колбеками), квик в конце концов забьет свою очередь сообщений и мы увидим любимое окошко "программа не отвечает, казнить нельзя помиловать". Правило одно, стараться не держать колбеки.
 
swerg, я даже больше скажу - колбек может прийти только в тот момент, когда главный тред снимает лок Lua. Хотя в любой нетривиальной программе это происходит на каждой второй строчке. Это во-первых. А во-вторых, всё вами описаное действо не влияет на то, в какой точке (на какой строке) скриптовый main будет остановлен и очередной колбек будет запущен.


Я вам только что про "недосказание не значит незнание" указал, а вы опять туда же. Самому то не стыдно искренне считать что все окружающие - пустоголовые кретины? Я бы тут так же мог кукарекать что вы не соображаете как тут это работает раз не указали про локи в своем списке, но я понимаю головой что люди каждую мелочь не прописывают когда их не спрашивают.


Обычные колбеки в скриптах (это контекст) вызываются когда скрипт сам дёргает процедуру вызова всех накопленых колбеков прямым или косвенным способом, тобишь поллинг - стандартный метод практически везде, от видеоигр и веб-браузеров до программного обеспечения мейнфреймов. Это подразумевая что никакого мултитрединга скриптов нет, максимум - синглтредовые корутины, как и делают большинство людей с айсикью получше чем у остальных. Причина так делать чисто техническая - скриптовые языки принципиально не приспособлены работать на нескольких процессорах, как может работать функция на С через pthreads, так что люди программирующие на трезвую голову и не пытаются натянуть сову на глобус и просто живут с тем фактом, что мультитредового исполнения функций в скриптах нет и программные решения они разрабатывают вокруг этого факта. В арке люди решили что они умнее всей планеты и хакнули некое подобие мультитрединга, от чего в итоге просто страдают пользователи (кучу тредов по этому поводу уже нафлудили) и никакой выгоды по сравниению с поллингом достигнуто не было (треды функций скриптов всё равно выполняются по одному а не все одновременно). Так вот, колбеки которые вызывает хост-программа, вклинивающиеся прямо посреди мейна на первой же точке где снимается лок, это так-называемые "многопоточные колбеки". И работают они в целом аналогично прерываниям CPU (кто с микроконтроллерами работал тот хорошо знаком), только в новых версиях Lua прервать исполнение мейна можно не в любой момент, а только когда исполняется определённые опкоды. Подход к реализации этих "многопоточных колбеков" настолько несуразный, что по итогу не подходит никакая стандартная терминология. Я надеюсь вы теперь перестанете продвигать вашу ad dictionarium fallacy в качестве аргумента, так как "словарное определение" было дано.
 
Старатель,  из того что
Цитата
Anton написал:
Цитата
Артем написал:
и не исполняется параллельно
Он исполняется параллельно. Другое дело, что сам луа - разделяемый ресурс, и доступ к нему потоков - по очереди. Если мейн и колбеки сишные в длл, они реально будут параллельно исполняться (пока снова не полезут в луа). Картинку выше  для чистого луа  можно мелко порезать горизонтальными линиями и в каждой полосе будет работать  либо  мейн,  либо  колбек, это правда, но так же работает вытесняющая многозадачность на одноядерном процессоре и никто не говорит, что это не многозадачность.
Тут под "параллельно" имелось ввиду как раз исполнение луа функций одновременно на разных процессорах, то есть колбек выполнялся бы параллельно с мейном. Вытесняющая многозадачность действительно реализована прерываниями, только прерывание запускает соседний тред а не просто выполняется само по себе и возвращает управление в прерванный тред.
 
Старатель,

Anton,


То есть общий порядок исполнения как на верхней диаграмме, а не на нижней?


 
 
Цитата
Артем написал:
Я вам только что про "недосказание не значит незнание" указал, а вы опять туда же. Самому то не стыдно искренне считать что все окружающие - пустоголовые кретины?
Вы хотите про это поговорить?
Обратите внимание, я намеренно вырезал все эти эмоции из предыдущих цитирований, делая вид, что не замечаю, но может напрасно? может это суть проблемы, с которой вы пришли на форум? ну раз вы столько про это пишете.

Цитата
Артем написал:
Обычные колбеки в скриптах (это контекст) вызываются когда скрипт сам дёргает процедуру вызова всех накопленых колбеков прямым или косвенным способом

Я бы не согласился. Callback-функция - это та, которую кто-то вызывает по какому-то событию. А сам это скрипт или среда исполнения этого скрипта - какая разница? По-моему, никакой для применения данного термина.
Кстати, в самом начале следующей цитаты вы ровно про это и пишете, так что не совсем понимаю почему непременно "скрипт сам дёргает". Впрочем, вероятно это не суть важный момент.

Цитата
Артем написал:
Так вот, колбеки которые вызывает хост-программа, вклинивающиеся прямо посреди мейна на первой же точке где снимается лок, это так-называемые "многопоточные колбеки"..

Вообще-то это нормальное, обычное и ожидаемое многопоточное выполнения кода.

Впрочем, наконец-то я, как представитель людей без IQ, понял о чем вы: вам, по сути, просто нужны средства межпоточной синхронизации, доступные их скриптов.

Цитата
Артем написал:
В арке люди решили что они умнее всей планеты и хакнули некое подобие мультитрединга, от чего в итоге просто страдают пользователи (кучу тредов по этому поводу уже нафлудили)

Я согласен с тем, что многопоточность в скриптах была сделана напрасно; от нее оказалось больше проблем, чем пользы. Было ли это очевидно в момент проектирования - не уверен.
Однако пользователи страдают по другим причинам, считаю:
а) не умеют в многопоточность;
б) сделав многопоточность в скриптах, ARQA не добавила функций для межпоточной синхронизации.

Пункт а) решается чтением книжек.

С пунктом б) чуть сложнее ввиду отсутствия готовых функций в QLua.
Например, библиотека w32 для QLua содержит функции работы с мьтексами, что вполне можно использовать для синхронизации, если это необходимо. Правда мьютексы несколько избыточны и тяжеловаты, ведь синхронизируемся ты лишь внутри одного процесса (в терминологии Windows), надо будет добавить в нее и работу с более подходящим для этого случая объектом "критическая секция".

Ну и еще в QLua есть "Потокобезопасные функции для работы с таблицами Lua". В отдельных случаях они спасают, но в очень узком круге случаев, да.
 
swerg, тут уже было написано, что если просто повесить лок то терминал зависнет (до снятия всех локов во всех скриптах). Я в ОПе хотел об этом написать и предложить использовать семафоры, но мне что-то показалось что это и так будет всем очевидно, было бы (как это по русски? не "снисходительно") condescending такие вещи сразу же писать. Кроме того, многопоточно выполняются только колбеки, так что средства синхронизации не нужны, нужны только средства контроля вызова колбеков - так как бесконтрольный вызов колбеков зачастую деструктивный.


Про потокобезопасные варианты фукнций для тейблов я имел глупость ляпнуть в другом треде, отчасти потому что не прочитал вопрос полностью - хештейблы этими функциями не поддерживаются от слова совсем. Можно конечно хешевый код переделать под аррайный, но это во-первых не идиоматично для луа а во-вторых выбрасывает в окно О(1) поиск ключей - хотя в той ситуации было бы всё равно т.к. элементы брались все подряд. Там же я предложил двойную буферизацию, что действительно помогает с гонками данных т.к. там разные данные и гоняться там нечему. Но это никак не препятствует разрушению стека, которое возникает судя по всему когда квик захватывает лок и начинает исполнение колбека в тот момент, когда в основном треде все еще выполняются С функции которые не поставили лок. Просто отложив вызов колбеков до того момента, когда весь скриптовый код уже выполнен (и сразу вызвав весь собравшийся набор), возможно позволило бы полностью решить эту проблему не переписывая всю архитектуру, а только сделав небольшую модификацию. Еще в другом месте я предлагал, чтобы колбеки вызывались только при вызове sleep, что тоже возможно разрулило бы все эти проблемы. Вообще конечно sunk cost fallacy это fallacy, если решение оказалось плохое значит от него надо отказаться в пользу хорошего, причём абсолютно неважно сколько усилий уже было вложено в мертворождённую идею - надо похоронить и начать заново. Но мы тут как бы все должны понимать, что разработка новой системы которая будет работать без нареканий может занять очень много времени, при том что старая работает почти без нареканий и починить её можно было бы достаточно небольшими усилиями.

Убедительная просьба, прекратить тащить сюда ad dictionarium fallacy. Предмет обсуждения это проблемы связанные с многопоточным вызовом колбеков и методы их решения, а не чья терминология насколько соответствует словарной.
 
Хотя нет не семафоры а просто флаги. Как то так, С++ псевдокодом.
Код
void QLuaManager::queueCallback ( Callback &callback ) {
  for ( auto &script : this.scripts )
    script.queueCallback ( callback );
}
void Script::queueCallback ( Callback &callback ) {
  this.queue.push ( callback );
  if ( this.queuePaused == false )
    this.executeQueue ( script );
}
void Script::pauseCallbacks ( ) {
  this.queuePaused = true;
}
void Script::resumeCallbacks ( ) {
  this.queuePaused = false;
  this.executeQueue ( script );
}
 
Цитата
Артем написал:
общий порядок исполнения
Первый вариант - мейны удобно выпускают лок в том порядке, в каком квик их хочет вызывать (заштриховано - квик стоит на локе; от красной линии до первого колбека он тоже стоит, не нарисовал этот момент)




Второй вариант - мейны выпускают лок в произвольном порядке. Поскольку квик хочет вызывать колбеки в жестком порядке, несколько дырок будет пропущено.



 
 
Цитата
Anton написал:
Второй вариант
Точно скрипты 2 и 3 в ожидании очереди запустить свои колбеки будут выполнять полезную работу в мейнах, а не тупо ждать?
Надо делать так, как надо. А как не надо - делать не надо.
 
Цитата
Старатель написал:
скрипты 2 и 3 в ожидании очереди запустить свои колбеки
Они не ждут очереди, ждет квик, мейны выполняются как выполнялись. Если не спят конечно, а если спят то и вопросов никаких, локи выпущены, квик просто дергает колбек и все. (О преимуществе длинного слипа тксть).
 
Цитата
Артем написал:
Хотя нет не семафоры а просто флаги. Как то так, С++ псевдокодом.
А если callback в момент вызова такой функции уже выполняется - как должно работать?
Этим вопросом я намекаю на то, что приведённому вами коду видно, что в многопоток вы не умеете.
Почитайте книжки, ознакомьтесь с объектами синхронизации и их использованием - и всё наладится. Никакие "отложенные колбеки" не понадобятся.

Однако пожелание для QUIK есть: штатные средства межпоточной синхронизации в QLua таки нужны.

Еще лучше, конечно, пересмотреть модель выполнения скриптов. Никакие конкурирующие потоки в рамках одного скрипта там явно не нужны.
 
swerg, точно так же как в текущей реализации (в этом и суть предложения - поменьше изменений делать): выполнять всё это в одном треде, так что никакое "уже выполняется" там быть не может принципиально. Это во-первых. Во-вторых, мой подход был бы создать на каждый скрипт отдельный тред-диспатчер колбеков, который и занимается собственно их запуском - главный тред тут принципиально не будет ничем блокироваться.

Цитата
Артем написал:
Самому то не стыдно искренне считать что все окружающие - пустоголовые кретины?
Видимо не только не стыдно, но даже наоборот - горделиво. Тфьу.
 
Цитата
Артем написал:
swerg, точно так же как в текущей реализации (в этом и суть предложения - поменьше изменений делать): выполнять всё это в одном треде, так что никакое "уже выполняется" там быть не может принципиально.

Напомню, ветка начиналась с "Добавить функции вида pauseCallbacks и resumeCallbacks, где первая приостанавливает вызовы многопоточных колбеков". И мы долго выясняли про какие многопоточности идёт речь.
Вроде как выяснили (хотя явно вы это не писали, но я вас понял так), что pauseCallbacks и resumeCallbacks вызываются в main(). Ну иначе бы и проблемы не было, очевидно.
Теперь внезапно все это в одном потоке, как так??

Так где вызываются pauseCallbacks и resumeCallbacks? и если не вmain(), то о какой многопоточности речь и как эти функции помогут, будучи вызванными не в main() ?

Цитата
Артем написал:
Во-вторых, мой подход был бы создать на каждый скрипт отдельный тред-диспатчер колбеков, который и занимается собственно их запуском - главный тред тут принципиально не будет ничем блокироваться.

Давайте не менять условия задачи на ходу. Это совсем уже другая история, она здесь не обсуждается.

Цитата
Артем написал:
Цитата
Самому то не стыдно искренне считать что все окружающие - пустоголовые кретины?
Видимо не только не стыдно, но даже наоборот - горделиво. Тфьу.

В самом деле: вы d каждом сообщении не договариваете половину важных деталей под девизом "и так очевидно", а когда совершенно не очевидные детали кое-как клещами из вас вытянешь - вы же других обвиняете в том, что кого-то там держат за идиотов.
Самому-то не стыдно не уметь корректно и внятно общаться?
 
swerg, я уже писал что считаю неуважительным разжёвывать информацию как для детей когда об этом никто не спрашивает. Если вам что-то непонятно то попросите уточнение, а не намекайте/открыто заявляйте о тупизне и некомпетентности - это не только неуважительно так еще и глупо; если вам что-то неясно то это у вас нехватает познаний а не у окружающих. Противная ситуация может быть когда выкладки людей выглядят несуразными так как противоречат вашим знаниям, но тут надо упомянуть про эффект даннинга-крюгера: то что вы считаете свои познания экспертными еще не значит что они действительно экспертные. Простой самотест: если вы думаете что ваши слова/познания 100% ничего не упустили, то вы 100% жертва этого эффекта. Этому эффекту подвержены все и избавиться от него можно только методом накопления знаний по существу вопроса, в плане психологии значит быть продемонстрированным в собственной неправоте столько раз пока вы сами не начнете в ней сомневаться. У более умных людей это занимает меньше попыток; нужно понимать, что мозг это очень слабый и абсолютно ненадёжный аппарат.

Колбеки всегда были в центральном потоке квика а мейны скриптов каждый в своем отдельном потоке (в версиях квика в рамках обсуждения), это не поменялось. Пауза и возобновление могут вызываться в любом месте т.к. они просто ставят флаг, который проверяется перед вызовом колбеков, и если флаг установлен то просто ничего не вызывается. В предложенном псевдокоде колбеки вызываются сразу же при возобновлении, это не может вызывать проблем при использовании внутри кода колбека поскольку колбеки либо стоят на паузе и этот код не может быть исполнен, либо и так уже исполняются в этот момент и эта функция ничего не делает. Постановка колбеков на паузу внутри колбека только ставит флаг, исполнитель колбеков просто перестанет исполнять последующие колбеки в очереди и управление вернётся в мейн скрипта.


То что мой вариант использует еще дополнительные треды - это как лично я бы решил проблему с подвисанием квика во время исполнения колбеков в рамках мультитредовой реализации. Хотя лично я в собственной реализации бы не стал использовать луа мультитрединг вообще, у меня и колбеки и мейн работали бы в одном и том же треде. Была бы отдельная функция, которая дёргает все накопленные эвенты в квике и запускает соответствующие колбеки. Я бы эту функцию затолкал внутрь sleep(), раз скрипт всё равно в этот момент ничем не занят.
Страницы: 1
Читают тему
Наверх