SlideShare ist ein Scribd-Unternehmen logo
1 von 69
Downloaden Sie, um offline zu lesen
Евгений Охотников
Коротко о себе
Профессиональный разработчик с го
● АСУ ТП и т п
● телеком платежные сервисы
● инструментарий для
Автор блога Размышлизмы
Сооснователь ⇛
Автор ряда докладов про Модель Акторов и С
2
Зачем нужен этот доклад?
Чтобы показать насколько
не страшно выглядит
многопоточное программирование с
использованием высокоуровневых
моделей
3
Не грех повторить еще раз:
Многопоточное программирование на
посредством голых нитей ов и
это пот боль и кровь
4
Можно не верить мне...
5
Архитектура мета
сервера мобильного
онлайн шутера
Можно не верить мне...
6
Архитектура мета
сервера мобильного
онлайн шутера
Через пару недель потраченных на
поиск и исправление наиболее
критических багов мы решили что
проще переписать все с нуля чем
пытаться исправить все недостатки
текущего решения
Почему мы ходим по граблям?
Незнание
Лень
синдром
7
Есть много чего
Проверено временем и множеством проектов
●
●
●
●
●
●
Этому вряд ли учат в ВУЗ ах
8
Простая задача
сервер который
● принимает запрос картинки пользователя
● отдает картинку с водяными знаками уникальными для этого
пользователя
9
Что нужно делать?
10
client
our service
user database
image storage
Конкурентность напрашивается...
11
Набор рабочих нитей
12
Http Server
Request
Processing
Http Client
(outgoing
requests)
Image Processing
Disclaimer
Примеры не привязаны к какому то конкретному инструменту
Везде есть некий
13
Попытка №1
14
Модель Акторов. Основные принципы
● актор это некая сущность обладающая поведением
● акторы реагируют на входящие сообщения
● получив сообщение актор может
○ отослать некоторое конечное количество сообщений
другим акторам
○ создать некоторое конечное количество новых акторов
○ определить для себя новое поведение для обработки
последующих сообщений
15
Модель Акторов. Основные принципы
● актор это некая сущность обладающая поведением
● акторы реагируют на входящие сообщения
● получив сообщение актор может
○ отослать некоторое конечное количество сообщений
другим акторам
○ создать некоторое конечное количество новых акторов
○ определить для себя новое поведение для обработки
последующих сообщений
16
Могут быть реализованы сильно по разному
● каждый актор это отдельный поток ОС
● каждый актор это сопрограмма
● каждый актор это объект у которого кто то
вызывает коллбэки
Сейчас будем говорить про акторов виде объектов с
коллбэками
Сопрограммы оставим для разговора про
Один из возможных вариантов
17
Актор request_handler (1)
class request_handler final : public some_basic_type {
const execution_context context_;
const request request_;
optional<user_info> user_info_;
optional<image_loaded> image_;
void on_start();
void on_user_info(user_info info);
void on_image_loaded(image_loaded image);
void on_mixed_image(mixed_image image);
void send_mix_images_request();
... // вся специфическая для фреймворка обвязка.
};
18
Актор request_handler (2)
void request_handler::on_start() {
send(context_.user_checker(), check_user{request_.user_id(), self()});
send(context_.image_downloader(), download_image{request_.image_id(), self()});
}
19
Актор request_handler (3)
void request_handler::on_user_info(user_info info) {
user_info_ = std::move(info);
if(image_)
send_mix_images_request();
}
void request_handler::on_image_loaded(image_loaded image) {
image_ = std::move(image);
if(user_info_)
send_mix_images_request();
}
20
Актор request_handler (4)
void request_handler::send_mix_images_request() {
send(context_.image_mixer(),
mix_images{user_info->watermark_image(), *image_, self()});
}
void request_handler::on_mixed_image(mixed_image image) {
send(context_.http_srv(), reply{..., std::move(image), ...});
}
21
Особенности Модели Акторов (1)
Акторы реактивны
Работают при наличии входящих сообщений
22
Особенности Модели Акторов (2)
Акторы подвержены перегрузкам
Следствие асинхронной природы взаимодействия
не блокирует отправителя
23
Особенности Модели Акторов (3)
Много акторов ≠ решение
Зачастую много акторов ⇒ еще одна проблема
24
Куда смотреть, что брать?
25
Поддержи отечественного
производителя
Попытка №2
26
CSP на пальцах и без матана
Композиция параллельно работающих последовательных
процессов
Взаимодействие посредством асинхронных сообщений
Сообщения доставляются посредством каналов
У каналов есть две операции и
27
CSP на пальцах и без матана
28
Композиция параллельно работающих последовательных
процессов
Взаимодействие посредством асинхронных сообщений
Сообщения доставляются посредством каналов
У каналов есть две операции и
Последовательные процессы внутри одного
процесса ОС могут быть реализованы как
● отдельные нити ОС В этом случае имеем
вытесняющую многозадачность
● сопрограммы
В этом случае имеем кооперативную
многозадачность
Один из возможных вариантов
29
"Процесс" request_handler
void request_handler(const execution_context ctx, const request req)
{
auto user_info_ch = make_chain<user_info>();
auto image_loaded_ch = make_chain<image_loaded>();
ctx.user_checker_ch().write(check_user{req.user_id(), user_info_ch});
ctx.image_downloader_ch().write(download_image{req.image_id(), image_loaded_ch});
auto user = user_info_ch.read();
auto original_image = image_loaded_ch.read();
auto image_mix_ch = make_chain<mixed_image>();
ctx.image_mixer_ch().write(
mix_images{user.watermark_image(), std::move(original_image), image_mix_ch});
auto result_image = image_mix_ch.read();
ctx.http_srv_ch().write(reply{..., std::move(result_image), ...});
}
30
"Процесс" request_handler
void request_handler(const execution_context ctx, const request req)
{
auto user_info_ch = make_chain<user_info>();
auto image_loaded_ch = make_chain<image_loaded>();
ctx.user_checker_ch().write(check_user{req.user_id(), user_info_ch});
ctx.image_downloader_ch().write(download_image{req.image_id(), image_loaded_ch});
auto user = user_info_ch.read();
auto original_image = image_loaded_ch.read();
auto image_mix_ch = make_chain<mixed_image>();
ctx.image_mixer_ch().write(
mix_images{user.watermark_image(), std::move(original_image), image_mix_ch});
auto result_image = image_mix_ch.read();
ctx.http_srv_ch().write(reply{..., std::move(result_image), ...});
}
31
"Процесс" request_handler
void request_handler(const execution_context ctx, const request req)
{
auto user_info_ch = make_chain<user_info>();
auto image_loaded_ch = make_chain<image_loaded>();
ctx.user_checker_ch().write(check_user{req.user_id(), user_info_ch});
ctx.image_downloader_ch().write(download_image{req.image_id(), image_loaded_ch});
auto user = user_info_ch.read();
auto original_image = image_loaded_ch.read();
auto image_mix_ch = make_chain<mixed_image>();
ctx.image_mixer_ch().write(
mix_images{user.watermark_image(), std::move(original_image), image_mix_ch});
auto result_image = image_mix_ch.read();
ctx.http_srv_ch().write(reply{..., std::move(result_image), ...});
}
32
"Процесс" request_handler
void request_handler(const execution_context ctx, const request req)
{
auto user_info_ch = make_chain<user_info>();
auto image_loaded_ch = make_chain<image_loaded>();
ctx.user_checker_ch().write(check_user{req.user_id(), user_info_ch});
ctx.image_downloader_ch().write(download_image{req.image_id(), image_loaded_ch});
auto user = user_info_ch.read();
auto original_image = image_loaded_ch.read();
auto image_mix_ch = make_chain<mixed_image>();
ctx.image_mixer_ch().write(
mix_images{user.watermark_image(), std::move(original_image), image_mix_ch});
auto result_image = image_mix_ch.read();
ctx.http_srv_ch().write(reply{..., std::move(result_image), ...});
}
33
"Процесс" request_handler
void request_handler(const execution_context ctx, const request req)
{
auto user_info_ch = make_chain<user_info>();
auto image_loaded_ch = make_chain<image_loaded>();
ctx.user_checker_ch().write(check_user{req.user_id(), user_info_ch});
ctx.image_downloader_ch().write(download_image{req.image_id(), image_loaded_ch});
auto user = user_info_ch.read();
auto original_image = image_loaded_ch.read();
auto image_mix_ch = make_chain<mixed_image>();
ctx.image_mixer_ch().write(
mix_images{user.watermark_image(), std::move(original_image), image_mix_ch});
auto result_image = image_mix_ch.read();
ctx.http_srv_ch().write(reply{..., std::move(result_image), ...});
}
34
"Процесс" request_handler
void request_handler(const execution_context ctx, const request req)
{
auto user_info_ch = make_chain<user_info>();
auto image_loaded_ch = make_chain<image_loaded>();
ctx.user_checker_ch().write(check_user{req.user_id(), user_info_ch});
ctx.image_downloader_ch().write(download_image{req.image_id(), image_loaded_ch});
auto user = user_info_ch.read();
auto original_image = image_loaded_ch.read();
auto image_mix_ch = make_chain<mixed_image>();
ctx.image_mixer_ch().write(
mix_images{user.watermark_image(), std::move(original_image), image_mix_ch});
auto result_image = image_mix_ch.read();
ctx.http_srv_ch().write(reply{..., std::move(result_image), ...});
}
35
"Процесс" request_handler
void request_handler(const execution_context ctx, const request req)
{
auto user_info_ch = make_chain<user_info>();
auto image_loaded_ch = make_chain<image_loaded>();
ctx.user_checker_ch().write(check_user{req.user_id(), user_info_ch});
ctx.image_downloader_ch().write(download_image{req.image_id(), image_loaded_ch});
auto user = user_info_ch.read();
auto original_image = image_loaded_ch.read();
auto image_mix_ch = make_chain<mixed_image>();
ctx.image_mixer_ch().write(
mix_images{user.watermark_image(), std::move(original_image), image_mix_ch});
auto result_image = image_mix_ch.read();
ctx.http_srv_ch().write(reply{..., std::move(result_image), ...});
}
36
"Процесс" request_handler
void request_handler(const execution_context ctx, const request req)
{
auto user_info_ch = make_chain<user_info>();
auto image_loaded_ch = make_chain<image_loaded>();
ctx.user_checker_ch().write(check_user{req.user_id(), user_info_ch});
ctx.image_downloader_ch().write(download_image{req.image_id(), image_loaded_ch});
auto user = user_info_ch.read();
auto original_image = image_loaded_ch.read();
auto image_mix_ch = make_chain<mixed_image>();
ctx.image_mixer_ch().write(
mix_images{user.watermark_image(), std::move(original_image), image_mix_ch});
auto result_image = image_mix_ch.read();
ctx.http_srv_ch().write(reply{..., std::move(result_image), ...});
}
37
Особенности CSP (1)
Процессы могут вести себя как захотят быть реактивными
проактивными или чередовать реактивность с проактивностью
Процессы могут работать даже в отсутствии сообщений
38
Особенности CSP (2)
Родные механизмы защиты от перегрузки
Каналы могут быть ограничены по размеру
Где то только такими и могут быть
Отправитель блокируется при записи в полный канал
39
Особенности CSP (3)
Процессы в виде нитей ОС ⇒ дорого
Плата за стек Плата за переключение
Но вытесняющая многозадачность
Процессы в виде сопрограмм ⇒ дешево
Но кооперативная многозадачность
Но сюрпризы с например
40
Особенности CSP (4)
Много процессов ≠ решение
Зачастую много процессов ⇒ еще одна проблема
41
Куда смотреть, что брать?
42
Actors vs CSP
один единственный канал
только реактивность
могут быть сложными конечными автоматами
шные процессы
много каналов
и реактивность и проактивность
не очень хорошо с конечными автоматами
лучше когда поддерживаются на уровне языка и
43
Попытка №3
44
Про Task-based подход в двух словах
Решение строится как набор небольших задач
Каждая задача выполняет одну операцию
Задачи запускаются вызовами Результатом является
Задачи провязываются в цепочки посредством
45
Реализация обработки запроса (1)
void handle_request(const execution_context & ctx, request req)
{
auto user_info_ft = async(ctx.http_client_ctx(),
[req] { return retrieve_user_info(req.user_id()); });
auto original_image_ft = async(ctx.http_client_ctx(),
[req] { return download_image(req.image_id()); });
when_all(user_info_ft, original_image_ft).then(
[&ctx, req](tuple<future<user_info>, future<image_loaded>> data) {
async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] {
return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get());
})
.then([req](future<mixed_image> mixed) {
async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); });
});
});
}
46
Реализация обработки запроса (2)
void handle_request(const execution_context & ctx, request req)
{
auto user_info_ft = async(ctx.http_client_ctx(),
[req] { return retrieve_user_info(req.user_id()); });
auto original_image_ft = async(ctx.http_client_ctx(),
[req] { return download_image(req.image_id()); });
when_all(user_info_ft, original_image_ft).then(
[&ctx, req](tuple<future<user_info>, future<image_loaded>> data) {
async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] {
return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get());
})
.then([req](future<mixed_image> mixed) {
async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); });
});
});
}
47
Реализация обработки запроса (3)
void handle_request(const execution_context & ctx, request req)
{
auto user_info_ft = async(ctx.http_client_ctx(),
[req] { return retrieve_user_info(req.user_id()); });
auto original_image_ft = async(ctx.http_client_ctx(),
[req] { return download_image(req.image_id()); });
when_all(user_info_ft, original_image_ft).then(
[&ctx, req](tuple<future<user_info>, future<image_loaded>> data) {
async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] {
return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get());
})
.then([req](future<mixed_image> mixed) {
async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); });
});
});
}
48
Реализация обработки запроса (4)
void handle_request(const execution_context & ctx, request req)
{
auto user_info_ft = async(ctx.http_client_ctx(),
[req] { return retrieve_user_info(req.user_id()); });
auto original_image_ft = async(ctx.http_client_ctx(),
[req] { return download_image(req.image_id()); });
when_all(user_info_ft, original_image_ft).then(
[&ctx, req](tuple<future<user_info>, future<image_loaded>> data) {
async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] {
return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get());
})
.then([req](future<mixed_image> mixed) {
async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); });
});
});
}
49
Реализация обработки запроса (5)
void handle_request(const execution_context & ctx, request req)
{
auto user_info_ft = async(ctx.http_client_ctx(),
[req] { return retrieve_user_info(req.user_id()); });
auto original_image_ft = async(ctx.http_client_ctx(),
[req] { return download_image(req.image_id()); });
when_all(user_info_ft, original_image_ft).then(
[&ctx, req](tuple<future<user_info>, future<image_loaded>> data) {
async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] {
return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get());
})
.then([req](future<mixed_image> mixed) {
async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); });
});
});
}
50
Реализация обработки запроса (6)
void handle_request(const execution_context & ctx, request req)
{
auto user_info_ft = async(ctx.http_client_ctx(),
[req] { return retrieve_user_info(req.user_id()); });
auto original_image_ft = async(ctx.http_client_ctx(),
[req] { return download_image(req.image_id()); });
when_all(user_info_ft, original_image_ft).then(
[&ctx, req](tuple<future<user_info>, future<image_loaded>> data) {
async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] {
return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get());
})
.then([req](future<mixed_image> mixed) {
async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); });
});
});
}
51
Последовательность операций
void handle_request(const execution_context & ctx, request req)
{
auto user_info_ft = async(ctx.http_client_ctx(),
[req] { return retrieve_user_info(req.user_id()); });
auto original_image_ft = async(ctx.http_client_ctx(),
[req] { return download_image(req.image_id()); });
when_all(user_info_ft, original_image_ft).then(
[&ctx, req](tuple<future<user_info>, future<image_loaded>> data) {
async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] {
return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get());
})
.then([req](future<mixed_image> mixed) {
async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); });
});
});
}
52
1
2
3
4
5
Последовательность операций
53
1
2
3
4
5
0
Загрузка
Загрузка изображения
Последовательность операций
54
1
2
3
4
5
0
Загрузка
Загрузка изображения
Есть и
изображение и
Последовательность операций
55
1
2
3
4
5
0
Загрузка
Загрузка изображения
Есть и
изображение и
Микширование
изображения
Последовательность операций
56
1
2
3
4
5
0
Загрузка
Загрузка изображения
Есть и
изображение и
Микширование
изображения
Изображение
смикшировано
Последовательность операций
57
1
2
3
4
5
0
Загрузка
Загрузка изображения
Есть и
изображение и
Микширование
изображения
Изображение
смикшировано
Формирование
ответа на запрос
void handle_request(const execution_context & ctx, request req)
{
auto user_info_ft = async(ctx.http_client_ctx(),
[req] { return retrieve_user_info(req.user_id()); });
auto original_image_ft = async(ctx.http_client_ctx(),
[req] { return download_image(req.image_id()); });
when_all(user_info_ft, original_image_ft).then(
[&ctx, req](tuple<future<user_info>, future<image_loaded>> data) {
async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] {
return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get());
})
.then([req](future<mixed_image> mixed) {
async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); });
});
});
}
Последовательность операций
58
1
2
3
4
5
0
Особенности Task-ов (1)
Обозримость С ней не очень хорошо
И вот это вот все
59
Особенности Task-ов (2)
Обработка ошибок
60
Особенности Task-ов (3)
Отмена ов
Таймеры таймауты
61
Читинг
void handle_request(const execution_context & ctx, request req)
{
auto user_info_ft = async(ctx.http_client_ctx(),
[req] { return retrieve_user_info(req.user_id()); });
auto original_image_ft = async(ctx.http_client_ctx(),
[req] { return download_image(req.image_id()); });
when_all(user_info_ft, original_image_ft).then(
[&ctx, req](tuple<future<user_info>, future<image_loaded>> data) {
async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] {
return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get());
})
.then([req](future<mixed_image> mixed) {
async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); });
});
});
}
62
Actors/CSP vs Tasks
акцент на обмене информацией
акцент на выполняемых действиях
63
Куда смотреть, что брать?
С
64
Еще интересное
Антон Полухин
Готовимся к С на реальном примере
65
And now, the end is near...
Пора переходить к итогам
66
Забудьте про голую многопоточность
67
Голой многопоточности есть место только внутри фреймворков и
библиотек
Есть из чего выбирать
Проверено временем и множеством проектов
●
●
●
●
●
●
Для всего этого в есть готовые инструменты в том числе и
хорошие
68
The (Happy?) End
Спасибо за внимание
69

Weitere ähnliche Inhalte

Was ist angesagt?

Фундаментальные основы разработки под iOS. Павел Тайкало
Фундаментальные основы разработки под iOS. Павел ТайкалоФундаментальные основы разработки под iOS. Павел Тайкало
Фундаментальные основы разработки под iOS. Павел Тайкало
Stanfy
 

Was ist angesagt? (10)

Инструменты разные нужны, инструменты разные важны
Инструменты разные нужны, инструменты разные важныИнструменты разные нужны, инструменты разные важны
Инструменты разные нужны, инструменты разные важны
 
"Погружение в Robolectric" Дмитрий Костырев (Avito)
"Погружение в Robolectric"  Дмитрий Костырев (Avito)"Погружение в Robolectric"  Дмитрий Костырев (Avito)
"Погружение в Robolectric" Дмитрий Костырев (Avito)
 
Фундаментальные основы разработки под iOS. Павел Тайкало
Фундаментальные основы разработки под iOS. Павел ТайкалоФундаментальные основы разработки под iOS. Павел Тайкало
Фундаментальные основы разработки под iOS. Павел Тайкало
 
Сергей Константинов — Что интересного готовит нам W3C
Сергей Константинов — Что интересного готовит нам W3CСергей Константинов — Что интересного готовит нам W3C
Сергей Константинов — Что интересного готовит нам W3C
 
JavaScript Базовый. Занятие 09.
JavaScript Базовый. Занятие 09.JavaScript Базовый. Занятие 09.
JavaScript Базовый. Занятие 09.
 
Создание графического интерфейса пользователя мобильных Android приложений (ч...
Создание графического интерфейса пользователя мобильных Android приложений (ч...Создание графического интерфейса пользователя мобильных Android приложений (ч...
Создание графического интерфейса пользователя мобильных Android приложений (ч...
 
C# Web. Занятие 11.
C# Web. Занятие 11.C# Web. Занятие 11.
C# Web. Занятие 11.
 
Методики «Inversion of Control» и «Dependency Injection». Применение в Spring.
Методики «Inversion of Control» и «Dependency Injection». Применение в Spring.Методики «Inversion of Control» и «Dependency Injection». Применение в Spring.
Методики «Inversion of Control» и «Dependency Injection». Применение в Spring.
 
Парсим и кодогенерируем для С++ с использованием clang
Парсим и кодогенерируем для С++ с использованием clangПарсим и кодогенерируем для С++ с использованием clang
Парсим и кодогенерируем для С++ с использованием clang
 
Самодельная параметризация и параллелизация тестов на Webdriver (JS)
Самодельная параметризация и параллелизация тестов на Webdriver (JS) Самодельная параметризация и параллелизация тестов на Webdriver (JS)
Самодельная параметризация и параллелизация тестов на Webdriver (JS)
 

Ähnlich wie [C++ CoreHard Autumn 2018] Actors vs CSP vs Task...

CodeFest 2011. Бусыгин Р. — Создание кастомных интерфейсов для iOS
CodeFest 2011. Бусыгин Р. — Создание кастомных интерфейсов для iOSCodeFest 2011. Бусыгин Р. — Создание кастомных интерфейсов для iOS
CodeFest 2011. Бусыгин Р. — Создание кастомных интерфейсов для iOS
CodeFest
 
белогорцев глеб белогорцев
белогорцев глеб белогорцевбелогорцев глеб белогорцев
белогорцев глеб белогорцев
rit2010
 
Remote (dev)tools своими руками
Remote (dev)tools своими рукамиRemote (dev)tools своими руками
Remote (dev)tools своими руками
Roman Dvornov
 
Расчетная работа по дисциплине МАПО (Кондратюк Т.А.)
Расчетная работа по дисциплине МАПО (Кондратюк Т.А.)Расчетная работа по дисциплине МАПО (Кондратюк Т.А.)
Расчетная работа по дисциплине МАПО (Кондратюк Т.А.)
Lita Ford
 
RR_Dima_Shm
RR_Dima_ShmRR_Dima_Shm
RR_Dima_Shm
Dima_Shm
 
23may 1300 valday антон сапожников 'еще один недостаток современных клиент се...
23may 1300 valday антон сапожников 'еще один недостаток современных клиент се...23may 1300 valday антон сапожников 'еще один недостаток современных клиент се...
23may 1300 valday антон сапожников 'еще один недостаток современных клиент се...
Positive Hack Days
 
Эволюционный дизайн. Joker Students Day 2016
Эволюционный дизайн. Joker Students Day 2016Эволюционный дизайн. Joker Students Day 2016
Эволюционный дизайн. Joker Students Day 2016
Кирилл Толкачёв
 
Антон Сапожников. Еще один недостаток современных клиент-серверных приложений
Антон Сапожников. Еще один недостаток современных клиент-серверных приложенийАнтон Сапожников. Еще один недостаток современных клиент-серверных приложений
Антон Сапожников. Еще один недостаток современных клиент-серверных приложений
Positive Hack Days
 
Уменьшение влияния человеческого фактора при разработке бизнес приложений
Уменьшение влияния человеческого фактора при разработке бизнес приложенийУменьшение влияния человеческого фактора при разработке бизнес приложений
Уменьшение влияния человеческого фактора при разработке бизнес приложений
ngrebnev
 

Ähnlich wie [C++ CoreHard Autumn 2018] Actors vs CSP vs Task... (20)

CodeFest 2011. Бусыгин Р. — Создание кастомных интерфейсов для iOS
CodeFest 2011. Бусыгин Р. — Создание кастомных интерфейсов для iOSCodeFest 2011. Бусыгин Р. — Создание кастомных интерфейсов для iOS
CodeFest 2011. Бусыгин Р. — Создание кастомных интерфейсов для iOS
 
Лабораторная работа № 3. МАПО - idef0 и dfd диаграммы
Лабораторная работа № 3. МАПО - idef0 и dfd диаграммыЛабораторная работа № 3. МАПО - idef0 и dfd диаграммы
Лабораторная работа № 3. МАПО - idef0 и dfd диаграммы
 
Технический задел
Технический заделТехнический задел
Технический задел
 
Разработка надежных параллельных, распределенных приложений: быстро и дешево
Разработка надежных параллельных, распределенных приложений: быстро и дешевоРазработка надежных параллельных, распределенных приложений: быстро и дешево
Разработка надежных параллельных, распределенных приложений: быстро и дешево
 
белогорцев глеб белогорцев
белогорцев глеб белогорцевбелогорцев глеб белогорцев
белогорцев глеб белогорцев
 
Remote (dev)tools своими руками
Remote (dev)tools своими рукамиRemote (dev)tools своими руками
Remote (dev)tools своими руками
 
"API «Битрикс24» — разбор с пристрастием". Александр Сербул, 1С-Битрикс
"API «Битрикс24» — разбор с пристрастием". Александр Сербул, 1С-Битрикс"API «Битрикс24» — разбор с пристрастием". Александр Сербул, 1С-Битрикс
"API «Битрикс24» — разбор с пристрастием". Александр Сербул, 1С-Битрикс
 
Расчетная работа по дисциплине МАПО (Кондратюк Т.А.)
Расчетная работа по дисциплине МАПО (Кондратюк Т.А.)Расчетная работа по дисциплине МАПО (Кондратюк Т.А.)
Расчетная работа по дисциплине МАПО (Кондратюк Т.А.)
 
ПРОГРАММНО-АППАРАТНЫЙ КОМПЛЕКС ДЛЯ ИССЛЕДОВАНИЯ АВТОМАТНОГО УПРАВЛЕНИЯ МОБИЛЬ...
ПРОГРАММНО-АППАРАТНЫЙ КОМПЛЕКС ДЛЯ ИССЛЕДОВАНИЯ АВТОМАТНОГО УПРАВЛЕНИЯ МОБИЛЬ...ПРОГРАММНО-АППАРАТНЫЙ КОМПЛЕКС ДЛЯ ИССЛЕДОВАНИЯ АВТОМАТНОГО УПРАВЛЕНИЯ МОБИЛЬ...
ПРОГРАММНО-АППАРАТНЫЙ КОМПЛЕКС ДЛЯ ИССЛЕДОВАНИЯ АВТОМАТНОГО УПРАВЛЕНИЯ МОБИЛЬ...
 
Антон Валюх - Использование паттерна Mvvm в android
Антон Валюх - Использование паттерна Mvvm в androidАнтон Валюх - Использование паттерна Mvvm в android
Антон Валюх - Использование паттерна Mvvm в android
 
"Жизнь без интернета" Кувалдин Артём, Яндекс
"Жизнь без интернета" Кувалдин Артём, Яндекс"Жизнь без интернета" Кувалдин Артём, Яндекс
"Жизнь без интернета" Кувалдин Артём, Яндекс
 
Лабораторная работа № 4. МАПО - диаграммы uml
Лабораторная работа № 4. МАПО - диаграммы umlЛабораторная работа № 4. МАПО - диаграммы uml
Лабораторная работа № 4. МАПО - диаграммы uml
 
RR_Dima_Shm
RR_Dima_ShmRR_Dima_Shm
RR_Dima_Shm
 
23may 1300 valday антон сапожников 'еще один недостаток современных клиент се...
23may 1300 valday антон сапожников 'еще один недостаток современных клиент се...23may 1300 valday антон сапожников 'еще один недостаток современных клиент се...
23may 1300 valday антон сапожников 'еще один недостаток современных клиент се...
 
Эволюционный дизайн. Joker Students Day 2016
Эволюционный дизайн. Joker Students Day 2016Эволюционный дизайн. Joker Students Day 2016
Эволюционный дизайн. Joker Students Day 2016
 
Lime.JS
Lime.JSLime.JS
Lime.JS
 
Антон Сапожников. Еще один недостаток современных клиент-серверных приложений
Антон Сапожников. Еще один недостаток современных клиент-серверных приложенийАнтон Сапожников. Еще один недостаток современных клиент-серверных приложений
Антон Сапожников. Еще один недостаток современных клиент-серверных приложений
 
Алексей Андросов - Debugger: Отладка кода
Алексей Андросов - Debugger: Отладка кодаАлексей Андросов - Debugger: Отладка кода
Алексей Андросов - Debugger: Отладка кода
 
Уменьшение влияния человеческого фактора при разработке бизнес приложений
Уменьшение влияния человеческого фактора при разработке бизнес приложенийУменьшение влияния человеческого фактора при разработке бизнес приложений
Уменьшение влияния человеческого фактора при разработке бизнес приложений
 
Ф'Yii'лософия
Ф'Yii'лософияФ'Yii'лософия
Ф'Yii'лософия
 

Mehr von Yauheni Akhotnikau

Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Yauheni Akhotnikau
 

Mehr von Yauheni Akhotnikau (20)

arataga. SObjectizer and RESTinio in action: a real-world example
arataga. SObjectizer and RESTinio in action: a real-world examplearataga. SObjectizer and RESTinio in action: a real-world example
arataga. SObjectizer and RESTinio in action: a real-world example
 
Actor Model and C++: what, why and how? (March 2020 Edition)
Actor Model and C++: what, why and how? (March 2020 Edition)Actor Model and C++: what, why and how? (March 2020 Edition)
Actor Model and C++: what, why and how? (March 2020 Edition)
 
What is SObjectizer 5.7 (at v.5.7.0)
What is SObjectizer 5.7 (at v.5.7.0)What is SObjectizer 5.7 (at v.5.7.0)
What is SObjectizer 5.7 (at v.5.7.0)
 
What is SObjectizer 5.6 (at v.5.6.0)
What is SObjectizer 5.6 (at v.5.6.0)What is SObjectizer 5.6 (at v.5.6.0)
What is SObjectizer 5.6 (at v.5.6.0)
 
Shrimp: A Rather Practical Example Of Application Development With RESTinio a...
Shrimp: A Rather Practical Example Of Application Development With RESTinio a...Shrimp: A Rather Practical Example Of Application Development With RESTinio a...
Shrimp: A Rather Practical Example Of Application Development With RESTinio a...
 
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
 
Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?
 
25 Years of C++ History Flashed in Front of My Eyes
25 Years of C++ History Flashed in Front of My Eyes25 Years of C++ History Flashed in Front of My Eyes
25 Years of C++ History Flashed in Front of My Eyes
 
GECon 2017: C++ - a Monster that no one likes but that will outlast them all
GECon 2017: C++ - a Monster that no one likes but that will outlast them allGECon 2017: C++ - a Monster that no one likes but that will outlast them all
GECon 2017: C++ - a Monster that no one likes but that will outlast them all
 
Dive into SObjectizer 5.5. Tenth part: Mutable Messages
Dive into SObjectizer 5.5. Tenth part: Mutable MessagesDive into SObjectizer 5.5. Tenth part: Mutable Messages
Dive into SObjectizer 5.5. Tenth part: Mutable Messages
 
Actor Model and C++: what, why and how?
Actor Model and C++: what, why and how?Actor Model and C++: what, why and how?
Actor Model and C++: what, why and how?
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?
 
Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?Модель акторов и C++ что, зачем и как?
Модель акторов и C++ что, зачем и как?
 
Dive into SObjectizer 5.5. Ninth Part: Message Chains
Dive into SObjectizer 5.5. Ninth Part: Message ChainsDive into SObjectizer 5.5. Ninth Part: Message Chains
Dive into SObjectizer 5.5. Ninth Part: Message Chains
 
Dive into SObjectizer 5.5. Eighth Part: Dispatchers
Dive into SObjectizer 5.5. Eighth Part: DispatchersDive into SObjectizer 5.5. Eighth Part: Dispatchers
Dive into SObjectizer 5.5. Eighth Part: Dispatchers
 
What's new in SObjectizer 5.5.9
What's new in SObjectizer 5.5.9What's new in SObjectizer 5.5.9
What's new in SObjectizer 5.5.9
 
Dive into SObjectizer 5.5. Seventh part: Message Limits
Dive into SObjectizer 5.5. Seventh part: Message LimitsDive into SObjectizer 5.5. Seventh part: Message Limits
Dive into SObjectizer 5.5. Seventh part: Message Limits
 
Dive into SObjectizer-5.5. Sixth part: Synchronous Interaction
Dive into SObjectizer-5.5. Sixth part: Synchronous InteractionDive into SObjectizer-5.5. Sixth part: Synchronous Interaction
Dive into SObjectizer-5.5. Sixth part: Synchronous Interaction
 
Dive into SObjectizer 5.5. Fifth part: Timers
Dive into SObjectizer 5.5. Fifth part: TimersDive into SObjectizer 5.5. Fifth part: Timers
Dive into SObjectizer 5.5. Fifth part: Timers
 

[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...

  • 2. Коротко о себе Профессиональный разработчик с го ● АСУ ТП и т п ● телеком платежные сервисы ● инструментарий для Автор блога Размышлизмы Сооснователь ⇛ Автор ряда докладов про Модель Акторов и С 2
  • 3. Зачем нужен этот доклад? Чтобы показать насколько не страшно выглядит многопоточное программирование с использованием высокоуровневых моделей 3
  • 4. Не грех повторить еще раз: Многопоточное программирование на посредством голых нитей ов и это пот боль и кровь 4
  • 5. Можно не верить мне... 5 Архитектура мета сервера мобильного онлайн шутера
  • 6. Можно не верить мне... 6 Архитектура мета сервера мобильного онлайн шутера Через пару недель потраченных на поиск и исправление наиболее критических багов мы решили что проще переписать все с нуля чем пытаться исправить все недостатки текущего решения
  • 7. Почему мы ходим по граблям? Незнание Лень синдром 7
  • 8. Есть много чего Проверено временем и множеством проектов ● ● ● ● ● ● Этому вряд ли учат в ВУЗ ах 8
  • 9. Простая задача сервер который ● принимает запрос картинки пользователя ● отдает картинку с водяными знаками уникальными для этого пользователя 9
  • 10. Что нужно делать? 10 client our service user database image storage
  • 12. Набор рабочих нитей 12 Http Server Request Processing Http Client (outgoing requests) Image Processing
  • 13. Disclaimer Примеры не привязаны к какому то конкретному инструменту Везде есть некий 13
  • 15. Модель Акторов. Основные принципы ● актор это некая сущность обладающая поведением ● акторы реагируют на входящие сообщения ● получив сообщение актор может ○ отослать некоторое конечное количество сообщений другим акторам ○ создать некоторое конечное количество новых акторов ○ определить для себя новое поведение для обработки последующих сообщений 15
  • 16. Модель Акторов. Основные принципы ● актор это некая сущность обладающая поведением ● акторы реагируют на входящие сообщения ● получив сообщение актор может ○ отослать некоторое конечное количество сообщений другим акторам ○ создать некоторое конечное количество новых акторов ○ определить для себя новое поведение для обработки последующих сообщений 16 Могут быть реализованы сильно по разному ● каждый актор это отдельный поток ОС ● каждый актор это сопрограмма ● каждый актор это объект у которого кто то вызывает коллбэки Сейчас будем говорить про акторов виде объектов с коллбэками Сопрограммы оставим для разговора про
  • 17. Один из возможных вариантов 17
  • 18. Актор request_handler (1) class request_handler final : public some_basic_type { const execution_context context_; const request request_; optional<user_info> user_info_; optional<image_loaded> image_; void on_start(); void on_user_info(user_info info); void on_image_loaded(image_loaded image); void on_mixed_image(mixed_image image); void send_mix_images_request(); ... // вся специфическая для фреймворка обвязка. }; 18
  • 19. Актор request_handler (2) void request_handler::on_start() { send(context_.user_checker(), check_user{request_.user_id(), self()}); send(context_.image_downloader(), download_image{request_.image_id(), self()}); } 19
  • 20. Актор request_handler (3) void request_handler::on_user_info(user_info info) { user_info_ = std::move(info); if(image_) send_mix_images_request(); } void request_handler::on_image_loaded(image_loaded image) { image_ = std::move(image); if(user_info_) send_mix_images_request(); } 20
  • 21. Актор request_handler (4) void request_handler::send_mix_images_request() { send(context_.image_mixer(), mix_images{user_info->watermark_image(), *image_, self()}); } void request_handler::on_mixed_image(mixed_image image) { send(context_.http_srv(), reply{..., std::move(image), ...}); } 21
  • 22. Особенности Модели Акторов (1) Акторы реактивны Работают при наличии входящих сообщений 22
  • 23. Особенности Модели Акторов (2) Акторы подвержены перегрузкам Следствие асинхронной природы взаимодействия не блокирует отправителя 23
  • 24. Особенности Модели Акторов (3) Много акторов ≠ решение Зачастую много акторов ⇒ еще одна проблема 24
  • 25. Куда смотреть, что брать? 25 Поддержи отечественного производителя
  • 27. CSP на пальцах и без матана Композиция параллельно работающих последовательных процессов Взаимодействие посредством асинхронных сообщений Сообщения доставляются посредством каналов У каналов есть две операции и 27
  • 28. CSP на пальцах и без матана 28 Композиция параллельно работающих последовательных процессов Взаимодействие посредством асинхронных сообщений Сообщения доставляются посредством каналов У каналов есть две операции и Последовательные процессы внутри одного процесса ОС могут быть реализованы как ● отдельные нити ОС В этом случае имеем вытесняющую многозадачность ● сопрограммы В этом случае имеем кооперативную многозадачность
  • 29. Один из возможных вариантов 29
  • 30. "Процесс" request_handler void request_handler(const execution_context ctx, const request req) { auto user_info_ch = make_chain<user_info>(); auto image_loaded_ch = make_chain<image_loaded>(); ctx.user_checker_ch().write(check_user{req.user_id(), user_info_ch}); ctx.image_downloader_ch().write(download_image{req.image_id(), image_loaded_ch}); auto user = user_info_ch.read(); auto original_image = image_loaded_ch.read(); auto image_mix_ch = make_chain<mixed_image>(); ctx.image_mixer_ch().write( mix_images{user.watermark_image(), std::move(original_image), image_mix_ch}); auto result_image = image_mix_ch.read(); ctx.http_srv_ch().write(reply{..., std::move(result_image), ...}); } 30
  • 31. "Процесс" request_handler void request_handler(const execution_context ctx, const request req) { auto user_info_ch = make_chain<user_info>(); auto image_loaded_ch = make_chain<image_loaded>(); ctx.user_checker_ch().write(check_user{req.user_id(), user_info_ch}); ctx.image_downloader_ch().write(download_image{req.image_id(), image_loaded_ch}); auto user = user_info_ch.read(); auto original_image = image_loaded_ch.read(); auto image_mix_ch = make_chain<mixed_image>(); ctx.image_mixer_ch().write( mix_images{user.watermark_image(), std::move(original_image), image_mix_ch}); auto result_image = image_mix_ch.read(); ctx.http_srv_ch().write(reply{..., std::move(result_image), ...}); } 31
  • 32. "Процесс" request_handler void request_handler(const execution_context ctx, const request req) { auto user_info_ch = make_chain<user_info>(); auto image_loaded_ch = make_chain<image_loaded>(); ctx.user_checker_ch().write(check_user{req.user_id(), user_info_ch}); ctx.image_downloader_ch().write(download_image{req.image_id(), image_loaded_ch}); auto user = user_info_ch.read(); auto original_image = image_loaded_ch.read(); auto image_mix_ch = make_chain<mixed_image>(); ctx.image_mixer_ch().write( mix_images{user.watermark_image(), std::move(original_image), image_mix_ch}); auto result_image = image_mix_ch.read(); ctx.http_srv_ch().write(reply{..., std::move(result_image), ...}); } 32
  • 33. "Процесс" request_handler void request_handler(const execution_context ctx, const request req) { auto user_info_ch = make_chain<user_info>(); auto image_loaded_ch = make_chain<image_loaded>(); ctx.user_checker_ch().write(check_user{req.user_id(), user_info_ch}); ctx.image_downloader_ch().write(download_image{req.image_id(), image_loaded_ch}); auto user = user_info_ch.read(); auto original_image = image_loaded_ch.read(); auto image_mix_ch = make_chain<mixed_image>(); ctx.image_mixer_ch().write( mix_images{user.watermark_image(), std::move(original_image), image_mix_ch}); auto result_image = image_mix_ch.read(); ctx.http_srv_ch().write(reply{..., std::move(result_image), ...}); } 33
  • 34. "Процесс" request_handler void request_handler(const execution_context ctx, const request req) { auto user_info_ch = make_chain<user_info>(); auto image_loaded_ch = make_chain<image_loaded>(); ctx.user_checker_ch().write(check_user{req.user_id(), user_info_ch}); ctx.image_downloader_ch().write(download_image{req.image_id(), image_loaded_ch}); auto user = user_info_ch.read(); auto original_image = image_loaded_ch.read(); auto image_mix_ch = make_chain<mixed_image>(); ctx.image_mixer_ch().write( mix_images{user.watermark_image(), std::move(original_image), image_mix_ch}); auto result_image = image_mix_ch.read(); ctx.http_srv_ch().write(reply{..., std::move(result_image), ...}); } 34
  • 35. "Процесс" request_handler void request_handler(const execution_context ctx, const request req) { auto user_info_ch = make_chain<user_info>(); auto image_loaded_ch = make_chain<image_loaded>(); ctx.user_checker_ch().write(check_user{req.user_id(), user_info_ch}); ctx.image_downloader_ch().write(download_image{req.image_id(), image_loaded_ch}); auto user = user_info_ch.read(); auto original_image = image_loaded_ch.read(); auto image_mix_ch = make_chain<mixed_image>(); ctx.image_mixer_ch().write( mix_images{user.watermark_image(), std::move(original_image), image_mix_ch}); auto result_image = image_mix_ch.read(); ctx.http_srv_ch().write(reply{..., std::move(result_image), ...}); } 35
  • 36. "Процесс" request_handler void request_handler(const execution_context ctx, const request req) { auto user_info_ch = make_chain<user_info>(); auto image_loaded_ch = make_chain<image_loaded>(); ctx.user_checker_ch().write(check_user{req.user_id(), user_info_ch}); ctx.image_downloader_ch().write(download_image{req.image_id(), image_loaded_ch}); auto user = user_info_ch.read(); auto original_image = image_loaded_ch.read(); auto image_mix_ch = make_chain<mixed_image>(); ctx.image_mixer_ch().write( mix_images{user.watermark_image(), std::move(original_image), image_mix_ch}); auto result_image = image_mix_ch.read(); ctx.http_srv_ch().write(reply{..., std::move(result_image), ...}); } 36
  • 37. "Процесс" request_handler void request_handler(const execution_context ctx, const request req) { auto user_info_ch = make_chain<user_info>(); auto image_loaded_ch = make_chain<image_loaded>(); ctx.user_checker_ch().write(check_user{req.user_id(), user_info_ch}); ctx.image_downloader_ch().write(download_image{req.image_id(), image_loaded_ch}); auto user = user_info_ch.read(); auto original_image = image_loaded_ch.read(); auto image_mix_ch = make_chain<mixed_image>(); ctx.image_mixer_ch().write( mix_images{user.watermark_image(), std::move(original_image), image_mix_ch}); auto result_image = image_mix_ch.read(); ctx.http_srv_ch().write(reply{..., std::move(result_image), ...}); } 37
  • 38. Особенности CSP (1) Процессы могут вести себя как захотят быть реактивными проактивными или чередовать реактивность с проактивностью Процессы могут работать даже в отсутствии сообщений 38
  • 39. Особенности CSP (2) Родные механизмы защиты от перегрузки Каналы могут быть ограничены по размеру Где то только такими и могут быть Отправитель блокируется при записи в полный канал 39
  • 40. Особенности CSP (3) Процессы в виде нитей ОС ⇒ дорого Плата за стек Плата за переключение Но вытесняющая многозадачность Процессы в виде сопрограмм ⇒ дешево Но кооперативная многозадачность Но сюрпризы с например 40
  • 41. Особенности CSP (4) Много процессов ≠ решение Зачастую много процессов ⇒ еще одна проблема 41
  • 43. Actors vs CSP один единственный канал только реактивность могут быть сложными конечными автоматами шные процессы много каналов и реактивность и проактивность не очень хорошо с конечными автоматами лучше когда поддерживаются на уровне языка и 43
  • 45. Про Task-based подход в двух словах Решение строится как набор небольших задач Каждая задача выполняет одну операцию Задачи запускаются вызовами Результатом является Задачи провязываются в цепочки посредством 45
  • 46. Реализация обработки запроса (1) void handle_request(const execution_context & ctx, request req) { auto user_info_ft = async(ctx.http_client_ctx(), [req] { return retrieve_user_info(req.user_id()); }); auto original_image_ft = async(ctx.http_client_ctx(), [req] { return download_image(req.image_id()); }); when_all(user_info_ft, original_image_ft).then( [&ctx, req](tuple<future<user_info>, future<image_loaded>> data) { async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] { return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get()); }) .then([req](future<mixed_image> mixed) { async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); }); }); }); } 46
  • 47. Реализация обработки запроса (2) void handle_request(const execution_context & ctx, request req) { auto user_info_ft = async(ctx.http_client_ctx(), [req] { return retrieve_user_info(req.user_id()); }); auto original_image_ft = async(ctx.http_client_ctx(), [req] { return download_image(req.image_id()); }); when_all(user_info_ft, original_image_ft).then( [&ctx, req](tuple<future<user_info>, future<image_loaded>> data) { async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] { return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get()); }) .then([req](future<mixed_image> mixed) { async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); }); }); }); } 47
  • 48. Реализация обработки запроса (3) void handle_request(const execution_context & ctx, request req) { auto user_info_ft = async(ctx.http_client_ctx(), [req] { return retrieve_user_info(req.user_id()); }); auto original_image_ft = async(ctx.http_client_ctx(), [req] { return download_image(req.image_id()); }); when_all(user_info_ft, original_image_ft).then( [&ctx, req](tuple<future<user_info>, future<image_loaded>> data) { async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] { return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get()); }) .then([req](future<mixed_image> mixed) { async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); }); }); }); } 48
  • 49. Реализация обработки запроса (4) void handle_request(const execution_context & ctx, request req) { auto user_info_ft = async(ctx.http_client_ctx(), [req] { return retrieve_user_info(req.user_id()); }); auto original_image_ft = async(ctx.http_client_ctx(), [req] { return download_image(req.image_id()); }); when_all(user_info_ft, original_image_ft).then( [&ctx, req](tuple<future<user_info>, future<image_loaded>> data) { async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] { return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get()); }) .then([req](future<mixed_image> mixed) { async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); }); }); }); } 49
  • 50. Реализация обработки запроса (5) void handle_request(const execution_context & ctx, request req) { auto user_info_ft = async(ctx.http_client_ctx(), [req] { return retrieve_user_info(req.user_id()); }); auto original_image_ft = async(ctx.http_client_ctx(), [req] { return download_image(req.image_id()); }); when_all(user_info_ft, original_image_ft).then( [&ctx, req](tuple<future<user_info>, future<image_loaded>> data) { async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] { return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get()); }) .then([req](future<mixed_image> mixed) { async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); }); }); }); } 50
  • 51. Реализация обработки запроса (6) void handle_request(const execution_context & ctx, request req) { auto user_info_ft = async(ctx.http_client_ctx(), [req] { return retrieve_user_info(req.user_id()); }); auto original_image_ft = async(ctx.http_client_ctx(), [req] { return download_image(req.image_id()); }); when_all(user_info_ft, original_image_ft).then( [&ctx, req](tuple<future<user_info>, future<image_loaded>> data) { async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] { return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get()); }) .then([req](future<mixed_image> mixed) { async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); }); }); }); } 51
  • 52. Последовательность операций void handle_request(const execution_context & ctx, request req) { auto user_info_ft = async(ctx.http_client_ctx(), [req] { return retrieve_user_info(req.user_id()); }); auto original_image_ft = async(ctx.http_client_ctx(), [req] { return download_image(req.image_id()); }); when_all(user_info_ft, original_image_ft).then( [&ctx, req](tuple<future<user_info>, future<image_loaded>> data) { async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] { return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get()); }) .then([req](future<mixed_image> mixed) { async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); }); }); }); } 52 1 2 3 4 5
  • 56. Последовательность операций 56 1 2 3 4 5 0 Загрузка Загрузка изображения Есть и изображение и Микширование изображения Изображение смикшировано
  • 57. Последовательность операций 57 1 2 3 4 5 0 Загрузка Загрузка изображения Есть и изображение и Микширование изображения Изображение смикшировано Формирование ответа на запрос
  • 58. void handle_request(const execution_context & ctx, request req) { auto user_info_ft = async(ctx.http_client_ctx(), [req] { return retrieve_user_info(req.user_id()); }); auto original_image_ft = async(ctx.http_client_ctx(), [req] { return download_image(req.image_id()); }); when_all(user_info_ft, original_image_ft).then( [&ctx, req](tuple<future<user_info>, future<image_loaded>> data) { async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] { return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get()); }) .then([req](future<mixed_image> mixed) { async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); }); }); }); } Последовательность операций 58 1 2 3 4 5 0
  • 59. Особенности Task-ов (1) Обозримость С ней не очень хорошо И вот это вот все 59
  • 61. Особенности Task-ов (3) Отмена ов Таймеры таймауты 61
  • 62. Читинг void handle_request(const execution_context & ctx, request req) { auto user_info_ft = async(ctx.http_client_ctx(), [req] { return retrieve_user_info(req.user_id()); }); auto original_image_ft = async(ctx.http_client_ctx(), [req] { return download_image(req.image_id()); }); when_all(user_info_ft, original_image_ft).then( [&ctx, req](tuple<future<user_info>, future<image_loaded>> data) { async(ctx.image_mixer_ctx(), [&ctx, req, d=std::move(data)] { return mix_image(get<0>(d).get().watermark_image(), get<1>(d).get()); }) .then([req](future<mixed_image> mixed) { async(ctx.http_srv_ctx(), [req, im=std::move(mixed)] { make_reply(...); }); }); }); } 62
  • 63. Actors/CSP vs Tasks акцент на обмене информацией акцент на выполняемых действиях 63
  • 65. Еще интересное Антон Полухин Готовимся к С на реальном примере 65
  • 66. And now, the end is near... Пора переходить к итогам 66
  • 67. Забудьте про голую многопоточность 67 Голой многопоточности есть место только внутри фреймворков и библиотек
  • 68. Есть из чего выбирать Проверено временем и множеством проектов ● ● ● ● ● ● Для всего этого в есть готовые инструменты в том числе и хорошие 68
  • 69. The (Happy?) End Спасибо за внимание 69