Подтвердить что ты не робот

Отложенный/обещающий шаблон в С++

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

Я только что закончил рефакторинг кода AS3, чтобы использовать отличную библиотеку CodeCatalyst/prom-as3 (https://github.com/CodeCatalyst/promise-as3), и поэтому начал думать о том, чтобы вернуться к моему С++-коду и увидеть, как я могу реализовать шаблон там.

Прежде чем я начал кодировать это сам, я проверил, было ли это сделано раньше, и обнаружил std::future/std::promise (и эквиваленты повышения), но они очень тяжелы (они, похоже, используют реальные потоки и т.д. и иметь синтаксис сильного шаблона).

Итак, мой вопрос: есть ли легкая, чистая реализация на С++ шаблона "Отложенный/обещающий", стиль jQuery?

рефов:

4b9b3361

Ответ 1

Извините, что я играю в некромант, но мне тоже было очень интересно использовать A + style promises в С++ и потратил годы на разработку лучшего способа его реализации. В конце концов, я добился успеха, и вы можете увидеть мою реализацию здесь.

Использование довольно прямолинейно, но сильно использует шаблонизацию и метапрограммирование шаблонов. Вот пример:

Promise<int> promise;

promise.future().then([](int i){
    std::cout << "i = " << i << std::endl;
    return "foobar";
}).then([](const std::string& str){
    std::cout << "str = " << str << std::endl;
});

promise.resolve(10);

Это напечатает:

i = 10
str = foobar

Ответ 2

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

Ответ 3

Есть несколько причин, по которым я думаю, что то, о чем вы просите, практически невозможно в С++.

Прежде всего, для использования С++ 11 нового синтаксиса лямбда для объявления встроенной функции (эквивалент которой тривиален и очень легкий в JavaScript), вы все же должны использовать шаблоны для их потребления.

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

Что еще вы имеете в виду, когда говорите "чистый С++" и "легкий" (и неявно безрезультатно)?

Ответ 4

Вы можете использовать кооперативный многозадачник. Я использую один в своем приложении. Единственная проблема, с которой я столкнулся, состоит в том, что захваченные переменные получают nuked, если я храню лямбда внутри списка < > и назову позже. Я до сих пор не понял решения, но я вполне уверен, что это можно сделать.

Ответ 5

Я знаю, что этот вопрос старый, но я полагаю, что стоит упомянуть и Rili, который, вероятно, реализует именно то, что вы хотите.

Есть несколько примеров и документации.

Так же, как и lifewanted (liblw), он в значительной степени основан на шаблонах. Одной из основных функций этой библиотеки является реализация A+ Promises - включая Then (с одним и двумя параметрами), Catch и Наконец.

Ссылки:

Ответ 6

Просто используйте библиотеку Facebook Folly: https://github.com/facebook/folly/blob/master/folly/docs/Futures.md

Boost.Thread и C++ 17 (еще даже не поддерживают комбинаторы) не предлагают такой большой функциональности, как Folly. В Folly вы даже можете получить успешные результаты вместо Try, как показано в ответе пользователя Oz. Вы можете ограничить количество потоков с помощью исполнителя пула потоков (ранее он был частью Wangle, но теперь является частью Folly) или даже встроенного исполнителя. Без шаблонов вы не доберетесь до C++, и они гарантируют безопасность типов, что хорошо.

Помните, что вы должны использовать семантику перемещения для фьючерсов, но вы можете использовать folly :: SharedPromise для создания нескольких фьючерсов из одного обещания.

Вы также можете посмотреть этот список: https://en.wikipedia.org/wiki/Futures_and_promises#List_of_implementations ("Нестандартные реализации фьючерсов на основе библиотек:").