LINUX.ORG.RU

C++, асинхронные вызовы. Библиотека


0

0

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

Фактически она ползволяет строить последовательность из синхронных и спецаильных асинхронных (не сильно отличающихся по стилю работы от сихронных) вызовов, с опредлением обработчика исключений (возможно не одного) и блоков finalize

Это все очень похоже на deferred из twisted python'а, но местами может иметь куда большие возможности.

Это только основа, дальше надо развивать.

Что есть:

  • Сам код. Небольшой. Но шаблон на шаблоне шаблоном погоняет. С небольшими артифактами.
  • Очень поверхностное тестирование

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

Где мне искать единомышеников?

Пример кода:


using namespace sequence;

_void f1();   // асинхронно возращаем void
int f2();       // синхронно возращаем int
_int f3(int); // асинхронно возращаем int
void f4(int);

_void catch1(exception); // асинхронно обработываем исключение
void catch2(exception);   // синхронно обрабоатываем исключение

...

header<void> h; // объявляем последовательность

h.                           // задаем последовательность
dtry_<void>(&f1).
try_<void>(&f2).
dtry_<int>(&f3).
try_<void>(&f4).
dcatch_(&catch1).
catch_(&catch2);

h.toResult();     // Запускаем ее

★★★★

(boost::)asio уже написали.

mv ★★★★★
()

изобретение уже давно написанного кода - одна из самых больших бед С++ программистов :-)

ott ★★★★★
()
Ответ на: комментарий от ott

В качестве повышения квалификации себя, как пейсателя -- самое то. :-)

one_more_hokum ★★★
()
Ответ на: комментарий от ott

> (boost::)asio уже написали.

Совсем другое. По стилю программирования. И по задачам. (по крайеней мере быстрый взгляд на asio такое показал, да и к io мое писание имеет хоть и имеет отношение, но не основное)

> изобретение уже давно написанного кода - одна из самых больших бед С++ программистов :-)

Проша аналоги.

Что я хочу - это обертку на RPC с произволным использовнием, без callback'ов и с ислкючениями

> В качестве повышения квалификации себя, как пейсателя -- самое то. :-)

Ну хотя бы

namezys ★★★★
() автор топика

эх, как надоели все эти С++ выеживания и издевательства над синтаксисом. Всякие _void, dtry_ и dcatch_, где число траев не равно числу кэтчей, болтающиеся не по делу <int> и <void> и т. д. А когда захочется в функции f1 и f2 параметры передавать, или результат f1 подать на вход f2, вообще ужос начнется.

Граждане! у вас есть статически-типизируемый язык, на нем и пишите. А если вам таки нужен еще и динамически-типизируемый - они все сейчас встраеваемые, возьмите соответствующую либу, подключите и пишите на нормальном динамическом языке. А не на этом adhoc-ужоснахе.

gods-little-toy ★★★
()
Ответ на: комментарий от namezys

> Что я хочу - это обертку на RPC с произволным использовнием, без callback'ов и с ислкючениями

СОRBA и вообще все похожее тебе сгенерят классы-обертки.

gods-little-toy ★★★
()
Ответ на: комментарий от gods-little-toy

> А когда захочется в функции f1 и f2 параметры передавать, или результат f1 подать на вход f2, вообще ужос начнется.

Как раз в этом и смысл. Выход одной подается на вход другой.

Я за основу брал twisted из питона. На выходе получил не меньщую функциональность, но сдобрил ее еще статической типизацией. Вы скажите что сложно обменитьваться переменными. На это тоже есть свои решения.

А про CORBA. Раскажите мне, как я могу писать однопоточны GUIвые приложения с ее использованием, чтоб они не весели

При этом хочу код, которые похож по смыслу и простоте понимания на синхронный

ЗЫ: согласен, возможно испоьзование слов dty, catch тута не совсем оправдано. Я сказал что надо много пилисить, улутшать смысл и тд

namezys ★★★★
() автор топика
Ответ на: комментарий от namezys

> А про CORBA. Раскажите мне, как я могу писать однопоточны GUIвые приложения с ее использованием, чтоб они не весели

А с этим велосипедом это что, можно что-ли? вы каким-то образом гарантируете что каждый из этих func1() выполняется достаточно быстро чтоб его можно было запустить в gui thread'е и он там отработал не вызвав заметную задержку?

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

> При этом хочу код, которые похож по смыслу и простоте понимания на синхронный

ну и приведенный кусок кода уже этим критериям мало удовлетворяет.

gods-little-toy ★★★
()
Ответ на: комментарий от gods-little-toy

> А с этим велосипедом это что, можно что-ли?

Да

> вы каким-то образом гарантируете что каждый из этих func1() выполняется достаточно быстро чтоб его можно было запустить в gui thread'е и он там отработал не вызвав заметную задержку?

Ну только разработчик функции это может гарантировать

> Вообще, тредов бояться уже категорически немодно

Однопоточность проще. При чем если задача не требует и 10% от мощности процессора. Все же обеспечить обработку конкуренции не всегд проще

> ну и приведенный кусок кода уже этим критериям мало удовлетворяет.

Может быть пока. Но последоватлеьный вызов всех методов (или обраотчиков исключений) он гарантирует. А это не маловажно.

А стиль да, стиль можно и надо коректировать

namezys ★★★★
() автор топика
Ответ на: комментарий от namezys

>> вы каким-то образом гарантируете что каждый из этих func1() выполняется достаточно быстро чтоб его можно было запустить в gui thread'е и он там отработал не вызвав заметную задержку?

>Ну только разработчик функции это может гарантировать

то есть на практике придется нашинковывать код на мааааленькие функции, как колбасу... И шарахаться в коде функций от любых потенциально долгих операций... DNS lookup надо сделать? усё, тащим асинхронное API (еще найдите такое) и извращаемся с вызовами и таймаутами.. >> Вообще, тредов бояться уже категорически немодно

> Однопоточность проще. При чем если задача не требует и 10% от мощности процессора.

16-ядерный проц AMD обещала в этом году. если вы хотите использовать 10% мощности - то уже больше одного ядра надо занимать уметь...

> Все же обеспечить обработку конкуренции не всегд проще

ну вам же не надо все конкурентно выполнять... Отдайте gui thread гую, пусть обрабатывает гуй и ждет результата. Одну точку синхронизации - ожидание результата - осилим?

>> ну и приведенный кусок кода уже этим критериям мало удовлетворяет.

>Может быть пока.

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

gods-little-toy ★★★
()
Ответ на: комментарий от gods-little-toy

> то есть на практике придется нашинковывать код на мааааленькие функции, как колбасу... И шарахаться в коде функций от любых потенциально долгих операций... DNS lookup надо сделать? усё, тащим асинхронное API (еще найдите такое) и извращаемся с вызовами и таймаутами..

Код, который это вынесет в отдельный поток, отработает тама, потом отдаст этот результат на обработку, где ее должен перехватить первый потом, дернуть по этому callback,  который тоже дернет осинхронный метод и тд...

Кушали, спасибо.
Логика и последовательность действий размазывается по всему коду, теряются многие вкусные вещи от С++.

Я я хочу вот так:

IP ip;

try {
  ip = getItByDNS("blablabla");
} catch(notfound) {
  ip = localhost
}
try {
  connect(ip);
  makesmth(...);
  getsmthfromuser(...);
  sendsmth(...);
} catch(error) {
  cout << "error in connection: " << error;
}

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

> 16-ядерный проц AMD обещала в этом году. если вы хотите использовать 10% мощности - то уже больше одного ядра надо занимать уметь...

О класс. Дай-те мне 2. Я щас 32 ядра загружу рисованием картинки пользователю. Буду рисовать 10000 кадров в секунду

> Одну точку синхронизации - ожидание результата - осилим?

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

> тут надо говорить "уже"! 

Мюсье не любит С++?

а я без ума от boost

namezys ★★★★
() автор топика
Ответ на: комментарий от gods-little-toy

Кроме того, хороший компиялотор такие сложные конструкции, как показал практика, компилирует в ОЧЕНЬ быстрый код. Стоимость добавления такого решения в код 0....1%, а удоствочтения на порядок выше

namezys ★★★★
() автор топика
Ответ на: комментарий от namezys

>Мюсье не любит С++?

> а я без ума от boost

я тоже когда-то был, потом охладел. На boost'e прикольно писать небольшие примеры.

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

Дебажить код сильно использующий бустовы функции - наказание, понимать и фиксить трудно. Ваш первоначальный пример был живой иллюстрацей - вокруг плавают какие-то _void, try_/catch_ которые чем-то отличаются от dtry/dcatch, и даже такое интуитивное дело как равенство числа try числу catch не выполняется.

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

gods-little-toy ★★★
()
Ответ на: комментарий от gods-little-toy

не спорю

это большая проблема

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

Вот вы приводили пример по поиску в DNS

А теперь перенесем это в отдельный тред. Как оттуда сообщить? Подцепить callback? Отлично, подцепили. А теперь мы хотим обработать ошибку. Мы берем, и вставляем по середине еще один callback, Потом появилась еще одна ошибка, мы еще раз берем и вставляем callback.

А потом через пару месяцев смотрим на средний callback и думаем какого рака он весит между 2мя соседними

Брррр... Ужасть

namezys ★★★★
() автор топика
Ответ на: комментарий от gods-little-toy

То что я написал, широ использется в python'e и тама это не кого не удивляет

namezys ★★★★
() автор топика
Ответ на: комментарий от namezys

> Вот вы приводили пример по поиску в DNS

> А теперь перенесем это в отдельный тред. Как оттуда сообщить? Подцепить callback? Отлично, подцепили. А теперь мы хотим обработать ошибку. Мы берем, и вставляем по середине еще один callback, Потом появилась еще одна ошибка, мы еще раз берем и вставляем callback.

C тредами как раз все очень просто. Утягиваем все взаимодействие с сетью в отдельный тред, и там, не парясь, используем синхронные вызовы. Назад выход один, который передает результат сделанного или ошибку. Получается гораздо проще чем громоздить паттерн реактор с сотней микро-функций on_xxx() оn_yyy() на все возможные состояния (коннектимся/ждем конца передачи/ждем приему/etc/etc).

gods-little-toy ★★★
()
Ответ на: комментарий от gods-little-toy

> Утягиваем все взаимодействие с сетью в отдельный тред, и там, не парясь, используем синхронные вызовы.

А если паралельно 500 взаимодействий надо? 500 тредов?

> Назад выход один, который передает результат сделанного или ошибку.

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

> Получается гораздо проще чем громоздить паттерн реактор с сотней микро-функций on_xxx() оn_yyy() на все возможные состояния

В том то и смысл, что такого не надо.

Сетевой сервер для программиста становится почти домашним синхронным

namezys ★★★★
() автор топика
Ответ на: комментарий от namezys

> Сетевой сервер для программиста становится почти домашним синхронным

но пишется он на каком-то ужоснах-языке cконструированном из огрызков C++ синтаксиса. Даже хуже, ужоснах-язык состоит из вызовов С++ функций, в которых уже нормальный код. Подозреваю очень быстро появится необходимость перекодировать нормальный C++ в ужос-синтаксис (потому что оказалось что функция может много времени жрать) а потом ужос-синтаксис обратно в C++ (потому что потребовалась переменная а ужас ее не поддерживает).

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

gods-little-toy ★★★
()
Ответ на: комментарий от gods-little-toy

А я взял

Отлаживать и понимать что проиходит стало в разы проще

скорость разработки быстрее

и при этом вся логика сконцентрировалась в одном месте

хотя что вы так строго. это только идея. дореализовывать ее надо. тот же boost::lambda тоже не лыком шит

namezys ★★★★
() автор топика

Можно даже на ЛОРе поискать по ключевым словам "с++ асинхронно"

Сразу на ум приходит QT (как они там этот вопрос решают?), sobjectizer, еще тут с++ либа пробегала (совместимая с QT), ну и гугль никто не отменял

Касательно синтаксиса -- с++ можно расширять только с большими синтаксическими уродствами, и вина в этом с++, а не автора библиотеки.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> Сразу на ум приходит QT

Не то все это... не то. Сигналы QT не есть ответ на какой-то вызов. Он не привязан к вызову то есть. А здесь привязан

Все это добра как раз успешно работает в qt, используя на нижнем уровня очередь сообщений qt для асинхронной обработки

> вина в этом с++, а не автора библиотеки.

Не не не... тута как раз моя недороботка. Надо что-то придумать

namezys ★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.