Тоже недавно выбирал скриптовый движок для связки с С++. Остановился на LUA.
C C++ библиотекой sol прокидывать данные С++ vs LUA оказалось очень просто (и наверное еффективнее чем в тяжеловесном V8). Хотя и есть пару нюансов.
Поэтому, недолго обсудив, мы решили использовать опенсорсный JS-движок V8. Основной аргумент: он уже использовался коллегами в другом сервисе, который находился в том же репозитории, что и наш. Поэтому многое можно было переиспользовать.
Действительно ли ваши аргументы в пользу V8 перевешивают достоинства LUA? Или вопрос о том какой движок выбрать серьезно не рассматривался?
Да, если встать на вашу точку зрения, похоже AsyncValue решает две задачи. Возможно удастся его декомпозировать, главное не переусложнить.
По моему мнению библиотечные классы должны быть просты и удобны в использовании. Реализация может быть сложноватой (на то она и библиотека) с понятными накладными расходами на использование. При этом желательно, чтобы неправильное использование класса приводило к ошибкам компиляции или хотя бы рантайм проверкам.
Таким образом появился AsyncValue класс — такой std::future на стероидах (на мой взгляд). Ну а виджеты — простое и удобное дополнение к ним.
Ну как бы обычно смысл в том, что «пересчитать результат» в конкретном случае может только один поток
да, но берем мы этот поток из пула потоков (мы же не резервируем на каждый тип расчета по потоку, потоков не напасёшся). Предыдущий рассчет на другом потоке рассылает сигнал, как нам определить есть ли сейчас текущий рассчет или надо новый поток брать и считать?
Хорошо.
Как избежать ситуации, когда мы рассылаем сигнал с результатом, а в каком-то другом потоке изменили/пересчитали результат и нужно послать опять сигнал с новым результатом. Как запретить параллельные рассылки сигналов?
Есть 2 потока, один поток с гуи, другой с бизнес-логикой. Поток с бизнес логикой будет большую часть времени ничего не делать, но при получении сигнала начнет работать над задачей. При этом так как весь поток бизнес-логи принадлежит классу бизнес-логики, то никаких мьютексов, атомиков и других средств синхронизации не требуется.
Вы сделали очень сильные предположения, с ними, конечно, никакие локи не нужны.
В реальности бизнес-логика работает на пуле потоков с достаточно развесистой системой зависимостей, когда результатом работы одной операции пользуются несколько зависимых операций и тому подобное.
но наверное он относился ко второй части моего сообщения
Можете привести схемотичный пример с акторами, хотелось бы посмотреть как там можно решить подобные проблемы.
Просто мой класс AsyncValue в чем-то похож на std::future, в котором нет атомиков.
Насколько я теперь понимаю, вы предлагаете акторы с атомиками. Скорее всего там внутри будут какие-то очереди, динамические аллокации, чего хотелось бы избежать. Если я не прав, поправьте.
я кажется понял вас, вместо одного объекта с синхронизацией его внутреннего состояния, вы предлагаете пересылать это внутренее состояние через параметр сигнала без всяких локов.
Тогда получается сам этот объект вырождается просто в сигнал. Это единственное, что он может выдать заинтересованным клиентам без локов. Но как клиены возьмут текущее состояние объекта без локов, когда сигнал ни разу еще не запустился? Как сделать wait?
Слоты конечно потокобезопасные, но их недостаточно.
Я описал одну из проблем, вот у вас прогресс идет и асинхронная операция закончилась, надо удалить прогресс и положить вместо него результат операции, но пока идет рассылка сигналов, удалять прогресс нельзя, то есть нужно держать и прогресс и результат одновременно. И заменять одно на другое, очевидно, под локом
С помощью таких AsyncValue очень удобно строить внутреннюю логику программы, выстраивать цепочки зависимых значений. А с помощью готовых виджетов очень легко поверх этого строить GUI. Там где должен лежать виджет результата асинхронной операции просто кладем AsyncWidget и он сам покажет прогресс или ошибку или ваш виджет с готовым результатом.
Библиотека — попытка обобщить такой подход и выделить повторяющийся код.
Возможно демо в картинкой из проекта вам даст лучшее представление. У нас есть некий GUI (эдитбокс с именем файла) который запускает асинхронную загрузку картинки. Виджет из библиотеки показывает прогресс, пока идет загрузка и ошибку если загрузить не удалось и картинку в случае успеха. Пользователю библиотеки нужно лишь указать как грузить картинку и как ее показывать в GUI, а всю работу с прогрессом и ошибками библиотека берет на себя.
Да, основной задачей изначально был унифицированный виджет для отображения асинхронной операции и результата её работы. Но более мясистым классом оказался AsyncValue.
Самописный виджет конечно можно использовать, но в этом и суть библиотек, что они дают хорошие дефолтные реализации с возможностью кастомизации. Моя библиотеки именно об этом.
Как обойтись без локов, когда в одном потоке значение вычисляется, а в другом оно используется в виджете? Те же future/promise кажется используют мютексы, а тут «тяжеловесные » объекты GUI.
Можете привести схемотичный пример с акторами, хотелось бы посмотреть как там можно решить подобные проблемы.
Насколько я вижу библиотека rxcpp дает набор примитивов для асинхронных вычислений. Как я писал в статье, моя библиотека не завязана на конкретную асинхронную библиотеку и може истользоватся в том числе и с rxcpp.
На мой взгляд ценность мое библиотеки в том, что она задает хорошие дефолты для состояние Progress и Error. И готовые виджеты, которые из коробки отобразят Progress и Error. Пользователю лишь надо указать как вычислять асинхронный результат (возможно и с помощью rxcpp) и предоставить метод-фабрику виджета, который отобразит этот результат. Вся остальная машинерия делается библиотекой.
Например в вашем примере я не вижу как можно отобразить прогресс асинхронной операции, как передать процент сделанного в этот виджет, так можно отменить операцию, если пользователь нажал кнопку Стоп или система знает, что результат операции уже не нужен.
Где «Рисующий поток отделен от потоков в которых обрабатываются клики»? Мне кажется это невозможно. По крайней мере в QtWidgets сообщения от виджетов обрабатываются в главном потоке.
ам же и так достаточно асинхронности.
Подскажите стандартный виджет показа асинхронной операции.
Тоже недавно выбирал скриптовый движок для связки с С++. Остановился на LUA.
C C++ библиотекой sol прокидывать данные С++ vs LUA оказалось очень просто (и наверное еффективнее чем в тяжеловесном V8). Хотя и есть пару нюансов.
Действительно ли ваши аргументы в пользу V8 перевешивают достоинства LUA? Или вопрос о том какой движок выбрать серьезно не рассматривался?
По моему мнению библиотечные классы должны быть просты и удобны в использовании. Реализация может быть сложноватой (на то она и библиотека) с понятными накладными расходами на использование. При этом желательно, чтобы неправильное использование класса приводило к ошибкам компиляции или хотя бы рантайм проверкам.
Таким образом появился AsyncValue класс — такой std::future на стероидах (на мой взгляд). Ну а виджеты — простое и удобное дополнение к ним.
Предположим.
Как вы это гарантируете, кроме как на словах? И не сильное ли это ограничение?
да, но берем мы этот поток из пула потоков (мы же не резервируем на каждый тип расчета по потоку, потоков не напасёшся). Предыдущий рассчет на другом потоке рассылает сигнал, как нам определить есть ли сейчас текущий рассчет или надо новый поток брать и считать?
Как избежать ситуации, когда мы рассылаем сигнал с результатом, а в каком-то другом потоке изменили/пересчитали результат и нужно послать опять сигнал с новым результатом. Как запретить параллельные рассылки сигналов?
Вы сделали очень сильные предположения, с ними, конечно, никакие локи не нужны.
В реальности бизнес-логика работает на пуле потоков с достаточно развесистой системой зависимостей, когда результатом работы одной операции пользуются несколько зависимых операций и тому подобное.
относится к моему высказыванию
но наверное он относился ко второй части моего сообщения
Просто мой класс AsyncValue в чем-то похож на std::future, в котором нет атомиков.
Насколько я теперь понимаю, вы предлагаете акторы с атомиками. Скорее всего там внутри будут какие-то очереди, динамические аллокации, чего хотелось бы избежать. Если я не прав, поправьте.
Тогда получается сам этот объект вырождается просто в сигнал. Это единственное, что он может выдать заинтересованным клиентам без локов. Но как клиены возьмут текущее состояние объекта без локов, когда сигнал ни разу еще не запустился? Как сделать wait?
Я описал одну из проблем, вот у вас прогресс идет и асинхронная операция закончилась, надо удалить прогресс и положить вместо него результат операции, но пока идет рассылка сигналов, удалять прогресс нельзя, то есть нужно держать и прогресс и результат одновременно. И заменять одно на другое, очевидно, под локом
Библиотека — попытка обобщить такой подход и выделить повторяющийся код.
Возможно демо в картинкой из проекта вам даст лучшее представление. У нас есть некий GUI (эдитбокс с именем файла) который запускает асинхронную загрузку картинки. Виджет из библиотеки показывает прогресс, пока идет загрузка и ошибку если загрузить не удалось и картинку в случае успеха. Пользователю библиотеки нужно лишь указать как грузить картинку и как ее показывать в GUI, а всю работу с прогрессом и ошибками библиотека берет на себя.
Самописный виджет конечно можно использовать, но в этом и суть библиотек, что они дают хорошие дефолтные реализации с возможностью кастомизации. Моя библиотеки именно об этом.
Можете привести схемотичный пример с акторами, хотелось бы посмотреть как там можно решить подобные проблемы.
На мой взгляд ценность мое библиотеки в том, что она задает хорошие дефолты для состояние Progress и Error. И готовые виджеты, которые из коробки отобразят Progress и Error. Пользователю лишь надо указать как вычислять асинхронный результат (возможно и с помощью rxcpp) и предоставить метод-фабрику виджета, который отобразит этот результат. Вся остальная машинерия делается библиотекой.
Например в вашем примере я не вижу как можно отобразить прогресс асинхронной операции, как передать процент сделанного в этот виджет, так можно отменить операцию, если пользователь нажал кнопку Стоп или система знает, что результат операции уже не нужен.
Подскажите стандартный виджет показа асинхронной операции.
Основная мысль — сейчас уже есть вещи, которые нельзя отладить (например нельзя войти в конструктор с = default), отладку должна предоставлять IDE.