Обновить
22
Алексей@AlexPublic

Пользователь

3
Подписчики
Отправить сообщение
Плата вполне нормальная. И даже цена более менее адекватная (не надо путать интегрированные встраиваемые решения и обычные материнки). Но в таком исполнение она должна была бы выйти года 3 назад. Тогда это было бы супер решение. А во второй половине 2013-го года это смешно на фоне решений от конкурентов.

Сейчас бы я с удовольствием взял за эти деньги полностью аналогичную плату на базе Clover Trail или Medfield. Ну естественно при условии что для них была бы реализована поддержка Linux, а не только Windows/Android.
Не могу ничего сказать про описываемое ПО, может оно действительно очень полезное. Но вот эта статья является классическим наукообразным впариванием, причём рассчитанным на незнакомую с IT аудиторию. Что-то типа «посмотрите какие мы тут мегакрутые вещи сделали (хотя речь о тривиальнейших вещах) — дайте новый грант». Не имею ничего против такого, но не пойму зачем ЭТО на хабре с его проф. аудиторией.
Уловил из статьи мысль, что социальные сети делают нас ближе к пещерным людям… В этом что-то есть. )))
Ну так это равносильно просто запуску — не было же орды запросов на сервер.

Вообще они там явно что-то накосячили. Достаточно взглянуть сколько занимает ресурсов тот же самый diff в самом mercurial.

А написана RB на Python.

Хм, я сам люблю серверные вещи на Питоне по быстрому делать. Он конечно не самый шустрый, но таких диких результатов что-то не припомню. Или взять тот же Django — весьма жирный фреймворк, а на 2 гигах вполне себе летать будет, если не орды пользователей.
Неслабые такие требования у системки… Т.е. я понимаю когда требуется много памяти под большую нагрузку. Но что бы даже не запускалось при двух гигах…

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

Ну и соответственно если остановится на том, что нам не требуется много очередей, то по сути окажется что практически всё уже реализована в стандартной библиотеке.

Не реализованным остался только механизм обработки результатов выполнения дополнительных потоков в основном потоке (UI). В смысле в стандарте C++11 этого нет. В C++14 уже планируют добавить, в Boost'e уже сейчас есть. Ну и естественно можно плодить множество своих велосипедиков, как во всех этих последних статьях.
Вы похоже не понимаете что я спрашиваю. Я не спрашиваю зачем нам многопоточность или зачем нужны пулы потоков в принципе. Мне интересно почему мы не можем написать просто так (в вашей терминологии):
async_queue.async([=]{
    file_data = get_data_from_file( file_name );
    async_queue.async([=]{
        parsed_data = parse( file_data );
        main_queue.async([=]{
            update_ui_with_new_data( parsed_data ) ;
        });
    });
});

или вообще так:
async_queue.async([=]{
    file_data = get_data_from_file( file_name );
    parsed_data = parse( file_data );
    main_queue.async([=]{
        update_ui_with_new_data( parsed_data ) ;
    });
});

Т.е. зачем более одной очереди (отправку исполнения в UI поток рассматриваем как отдельный особый случай).

Ну и безотносительно всего этого… Создание/удаление потока имеют обычно ничтожные затраты на фоне самой задачи (уж точно на фоне перечисленных вами в последнем комментарии задач). И проблема у схемы «по потоку на задачу» совсем не с этим. А с тем, что если наплодить много активных потоков, то эффективность резко уменьшится за счёт накладных расходов на переключение контекста (вот это становится действительно затратная операция с учётом её частоты).

Да, и у вас совсем не легковесные потоки (которые coroutine или fiber), а именно пул потоков с очередями задач, Т.к. для легковесных потоков вам потребовался бы ещё какой-то механизм многозадачности (кооперативной как минимум, т.е. что-то типа yield).
Нууу хорошо, пусть один пул с несколькими очередями (хотя по сути это… ) в него. Всё равно не понятно зачем их несколько. Можно какие-то практические примеры? )

P.S. Как вы понимаете у меня вопросы/претензии не к вашему велосипедику, а к изначальной схеме…
SRP — жеж. Ну и отсутствие возможности для dead-lock'а — если вся работа с одним ресурсом (файловой системой, к примеру) идет через одну очередь.

Согласно SRP нам нужна отдельная сущность «пул потоков». Зачем нам надо много пулов потоков я пока так и не понял. Насчёт dead-lock'a… Во-первых это не так просто, т.к. ресурс у пула потоков наверняка не один (как минимум по числу аппаратных потоков). Ну и если всё же есть его вероятность (т.е. имеем много спящих потоков), то зачем тогда вообще использовать пул, а не просто отдельные потоки на каждую задачу?
std::async — это тот еще костыль ИМХО. Получение значения оттуда через std::future полностью блокирует текущий поток (что для Main Thread не приемлемо в принципе). А я не хочу блокироваться, я хочу получить уведомление о том, что все закончилось в контексте текущей очереди тогда, когда данные будут получены.

Ничего подобного. При использование std::async совершенно не обязательно блокировать вызывающий поток. Блокирование — это всего лишь один из сценариев. Можно и опрашивать, а можно и ждать уведомления. Кстати, как раз в той статье, на которую вы поместили ссылку в начале, были явно показаны все 3 варианта.
Удобно, чтобы для каждой из этих операций была своя очередь.

А в чём именно удобство? Мне это совершенно не очевидно.

Очевидное решение — реализация шаблона пулл потоков.

Нуу например std::async в реализации MS именно так и работает.
ГМО нормально, если это разработка каких-то наших институтов, а не от печально известной Монсанто. Если уж кто и стоит в этом мире звания «копирастов», то как раз эти товарищи. )))
А где вариант «у меня нет смартфона потому что он мне не нужен»? Мне кажется это намного более вероятный вариант чем «не знаю что это такое» или «слишком сложный».
Вот лучше бы они добавили в C++14 полноценные сопроцедуры! Они мощнее — позволяют реализовать и любой await и ещё много всего другого интересного.
По поводу cast'а… В данном случае мы передаём свои данных (в виде указателя) через очередь сообщений ОС — типизацию при этом сохранить невозможно в принципе.

Да, и кстати, все наши красивые и формальные ООП библиотеки внутри работают именно через подобные cast'ы, потому что иначе работать с функциями ОС невозможно.
А где там запуск новых потоков? ) Вложенность же от них идёт…

Ну и в любом случае, а если нам if или вообще for понадобится? )

Да и вообще, я же ещё в самом самом начале статьи написал что в принципе у нас давно есть полный набор инструментов для написания асинхронного кода. Т.е. формально мы можем записать что угодно (и даже без then ещё) давным давно. Так что вопрос остаётся только в простоте и удобстве кода — по сути синтаксическом сахаре.
Первый раз вижу эту ссылку, но судя по описанию в ней, это как раз самые классические сопроцедуры, причём не такие ограниченные как await/async, а больше похоже на Boost'ие. Это в смысле сценария использования. А в смысле внутренней реализации надо смотреть уже более подробное описание/исходники.
then же работает только как однократное поствыполнение. А с await у нас произвольная сложность, т.е. это просто обобщение then до полного подобия линейного кода. Вот смотрите пример:
void Handler(const URL url) async_code
(
    log_window+="Downloading "+url;
    auto xml=ParseXML(await_async([&]{return Download(url);}));
    log_window+="Downloading "+xml.GetValue("/update/text/url ");
    result_window+=await_async([&]{return Download(xml.GetValue("/update/text/url "));});
)

В нём такая последовательность исполнения:
1. «log_window+= в UI потоке и потом возврат из функции Handler
2. Download(url) в отдельном потоке
3. ParseXML и log_window+= снова в UI потоке
4. Download(xml.GetValue(»/update/text/url ")) в отдельном потоке
5. result_window+= снова в UI потоке.

Теперь представьте себе как некрасиво выглядел бы подобный код на вложенных then'ах.
Сделал небольшое дополнение к статье. )))
Ээээ, async_code — это не функции, а блоки асинхронного кода. Аналогом этого является всё тело async функции (причём самой первой по стеку вызова) в C# варианте. Возвращать из них какое-то значение (сразу) не имеет никакого смысла, т.к. ещё ничего не вычислено. Поэтому в моей реализации никаких возвратов нет, хотя реализация сопроцедур в Boost и поддерживает такое. Если же речь идёт о том, что бы возвращать значение после отработки всего асинхронного кода, то это просто означает что и предыдущая по стеку вызовов функция должна быть асинхронной и соответственно надо просто переставить asyn_code в неё.
Boost реализация сопроцедур корректно перекидывает исключение в родительский стек: www.boost.org/doc/libs/1_54_0/libs/coroutine/doc/html/coroutine/coroutine.html#coroutine.coroutine.exceptions_in__emphasis_coroutine_function__emphasis_

Информация

В рейтинге
Не участвует
Откуда
Москва, Москва и Московская обл., Россия
Зарегистрирован
Активность