Search
Write a publication
Pull to refresh
18
0
Send message

Тоже недавно выбирал скриптовый движок для связки с С++. Остановился на LUA.

C C++ библиотекой sol прокидывать данные С++ vs LUA оказалось очень просто (и наверное еффективнее чем в тяжеловесном V8). Хотя и есть пару нюансов.

Поэтому, недолго обсудив, мы решили использовать опенсорсный JS-движок V8. Основной аргумент: он уже использовался коллегами в другом сервисе, который находился в том же репозитории, что и наш. Поэтому многое можно было переиспользовать.

Действительно ли ваши аргументы в пользу V8 перевешивают достоинства LUA? Или вопрос о том какой движок выбрать серьезно не рассматривался?

Да, если встать на вашу точку зрения, похоже AsyncValue решает две задачи. Возможно удастся его декомпозировать, главное не переусложнить.

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

Таким образом появился AsyncValue класс — такой std::future на стероидах (на мой взгляд). Ну а виджеты — простое и удобное дополнение к ним.
Тут важнее взаимодействие между классом gui и классом бизнес-логики.

Предположим.
И для класса gui класс бизнес-логики выглядит как однопоточный класс, в котором ничего нельзя изменить извне этого потока

Как вы это гарантируете, кроме как на словах? И не сильное ли это ограничение?
Ну как бы обычно смысл в том, что «пересчитать результат» в конкретном случае может только один поток

да, но берем мы этот поток из пула потоков (мы же не резервируем на каждый тип расчета по потоку, потоков не напасёшся). Предыдущий рассчет на другом потоке рассылает сигнал, как нам определить есть ли сейчас текущий рассчет или надо новый поток брать и считать?
Если будет свободное время — попробую
Хорошо.
Как избежать ситуации, когда мы рассылаем сигнал с результатом, а в каком-то другом потоке изменили/пересчитали результат и нужно послать опять сигнал с новым результатом. Как запретить параллельные рассылки сигналов?
Есть 2 потока, один поток с гуи, другой с бизнес-логикой. Поток с бизнес логикой будет большую часть времени ничего не делать, но при получении сигнала начнет работать над задачей. При этом так как весь поток бизнес-логи принадлежит классу бизнес-логики, то никаких мьютексов, атомиков и других средств синхронизации не требуется.

Вы сделали очень сильные предположения, с ними, конечно, никакие локи не нужны.
В реальности бизнес-логика работает на пуле потоков с достаточно развесистой системой зависимостей, когда результатом работы одной операции пользуются несколько зависимых операций и тому подобное.
Я подумал, что ваш комментарий
Так а std::atomic?

относится к моему высказыванию
Те же future/promise кажется используют мютексы,

но наверное он относился ко второй части моего сообщения
Можете привести схемотичный пример с акторами, хотелось бы посмотреть как там можно решить подобные проблемы.


Просто мой класс AsyncValue в чем-то похож на std::future, в котором нет атомиков.
Насколько я теперь понимаю, вы предлагаете акторы с атомиками. Скорее всего там внутри будут какие-то очереди, динамические аллокации, чего хотелось бы избежать. Если я не прав, поправьте.
я кажется понял вас, вместо одного объекта с синхронизацией его внутреннего состояния, вы предлагаете пересылать это внутренее состояние через параметр сигнала без всяких локов.
Тогда получается сам этот объект вырождается просто в сигнал. Это единственное, что он может выдать заинтересованным клиентам без локов. Но как клиены возьмут текущее состояние объекта без локов, когда сигнал ни разу еще не запустился? Как сделать wait?
Интересно, из коробки Qt так работать не должен. Похоже вы создавали кнопку не в главном потоке, поэтому и клики туда шли асинхронно.
Расскажите как атомики помогают реализовать ожидающий/блокирующий std::future:get()?
Слоты конечно потокобезопасные, но их недостаточно.
Я описал одну из проблем, вот у вас прогресс идет и асинхронная операция закончилась, надо удалить прогресс и положить вместо него результат операции, но пока идет рассылка сигналов, удалять прогресс нельзя, то есть нужно держать и прогресс и результат одновременно. И заменять одно на другое, очевидно, под локом
С помощью таких AsyncValue очень удобно строить внутреннюю логику программы, выстраивать цепочки зависимых значений. А с помощью готовых виджетов очень легко поверх этого строить GUI. Там где должен лежать виджет результата асинхронной операции просто кладем AsyncWidget и он сам покажет прогресс или ошибку или ваш виджет с готовым результатом.

Библиотека — попытка обобщить такой подход и выделить повторяющийся код.

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

Самописный виджет конечно можно использовать, но в этом и суть библиотек, что они дают хорошие дефолтные реализации с возможностью кастомизации. Моя библиотеки именно об этом.
Как обойтись без локов, когда в одном потоке значение вычисляется, а в другом оно используется в виджете? Те же future/promise кажется используют мютексы, а тут «тяжеловесные » объекты GUI.

Можете привести схемотичный пример с акторами, хотелось бы посмотреть как там можно решить подобные проблемы.
Насколько я вижу библиотека rxcpp дает набор примитивов для асинхронных вычислений. Как я писал в статье, моя библиотека не завязана на конкретную асинхронную библиотеку и може истользоватся в том числе и с rxcpp.

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

Например в вашем примере я не вижу как можно отобразить прогресс асинхронной операции, как передать процент сделанного в этот виджет, так можно отменить операцию, если пользователь нажал кнопку Стоп или система знает, что результат операции уже не нужен.
Где «Рисующий поток отделен от потоков в которых обрабатываются клики»? Мне кажется это невозможно. По крайней мере в QtWidgets сообщения от виджетов обрабатываются в главном потоке.

ам же и так достаточно асинхронности.

Подскажите стандартный виджет показа асинхронной операции.
Ммм… Какое событие и в каком стандартном виджете? Не понял вопроса.
На старом видео с прошлой конференции Герб чуть подробнее про это сказал.

Основная мысль — сейчас уже есть вещи, которые нельзя отладить (например нельзя войти в конструктор с = default), отладку должна предоставлять IDE.

Information

Rating
Does not participate
Registered
Activity