Дмитрий Жестилевский — Yet another threading framework: асинхронная...
-
Upload
yandex -
Category
Technology
-
view
531 -
download
4
description
Transcript of Дмитрий Жестилевский — Yet another threading framework: асинхронная...
![Page 1: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/1.jpg)
1
![Page 2: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/2.jpg)
2
карты
Асинхронная разработка на C++
Дмитрий Жестилевский
![Page 3: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/3.jpg)
3
Содержание
! Как работает загрузка карты ! Стейт-машина и линейный код
! С++11 concurrency ! Наш вариант concurrency
! Пример реализации загрузки карты
![Page 4: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/4.jpg)
4
![Page 5: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/5.jpg)
5
Тайл
! Можно отменять ! Должен кешироваться ! Должен обновляться ! Один тайл может содержать множество версий
![Page 6: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/6.jpg)
6
Схема загрузки одного тайла Старт
Обновился?
Есть в памяти?
Есть на диске?
Сходить в диск
Сходить в сеть
Конец
Вернуть тайл
Декодировать и положить в память
Вернуть тайл
Вернуть тайл
Декодировать и положить в память
Нет
Да
Да
Да
Нет
Нет
![Page 7: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/7.jpg)
7
Конечный автомат Он же стейт-машина
![Page 8: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/8.jpg)
8
Row<NotInRam , RequestTile , LoadingFromDisk , none , none >, !Row<NotInRam , DiscardTile , none , none , none >, !Row<NotInRam , UpdateTile , none , none , none >, !// +-------------+--------------------------+-----------------+-------------------+-----------------------+ !Row<LoadingFromDisk, RequestTile , none , none , none >, !// this transition will be performed if isTileUpToDate returns false !Row<LoadingFromDisk, TileReady , UpdatingFromNet , NotifyCaller , none >, !Row<LoadingFromDisk, TileReady , UpToDateInRam , NotifyCaller , IsTileUpToDate >, !Row<LoadingFromDisk, TileRequestError , LoadingFromNet , none , none >, !// +-------------+--------------------------+-----------------+-------------------+-----------------------+ !Row<LoadingFromNet , RequestTile , none , none , none >, !Row<LoadingFromNet , TileReady , InRamSyncing , NotifyCaller , none >, !Row<LoadingFromNet , TileRequestError , NotInRam , NotifyCaller , none >, !// +-------------+--------------------------+-----------------+-------------------+-----------------------+ !Row<UpdatingFromNet, RequestTile , none , NotifyCaller , none >, !Row<UpdatingFromNet, TileReady , InRamSyncing , NotifyCaller , none >, !Row<UpdatingFromNet, TileRequestError , OldInRam , none , none >, !// +-------------+--------------------------+-----------------+-------------------+-----------------------+ !Row<InRamSyncing , RequestTile , none , NotifyCaller , none >, !Row<InRamSyncing , DiscardTile , none , none , none >, !Row<InRamSyncing , TileSyncingCompleted , UpToDateInRam , none , none >, !Row<InRamSyncing , TileSyncingError , UpToDateInRam , none , none >, !// +-------------+--------------------------+-----------------+-------------------+-----------------------+ !// May be we don't need this state. !Row<OldInRam , RequestTile , UpdatingFromNet , NotifyCaller , none >, !Row<OldInRam , UpdateTile , UpdatingFromNet , none , none >, !Row<OldInRam , DiscardTile , none , none , none >, !// +-------------+--------------------------+-----------------+-------------------+-----------------------+ !Row<UpToDateInRam , RequestTile , none , NotifyCaller , none >, !Row<UpToDateInRam , UpdateTile , none , none , none >, !Row<UpToDateInRam , UpdateTile , UpdatingFromNet , none , Not_<IsTileUpToDate> >, !Row<UpToDateInRam , DiscardTile , none , none , none >, !// +-------------+--------------------------+-----------------+-------------------+-----------------------+ !Row<AllOk , DiscardTile , CancelledMode , none , none >, !Row<CancelledMode , RequestTile , AllOk , none , none >!
![Page 9: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/9.jpg)
9
Линейный код
void loadTile(int x, int y, output_iterator output) { ! if (auto tile = inMemory(x, y)) { ! output << tile; ! } !! if (auto tile = readFromDisk(x, y)) { ! output << decode(tile); ! prevVersion = tile.version; ! } !! while (true) { ! Tile tile = readFromNet(x, y, prevVersion); ! if (tile.version == prevVersion) continue; ! prevVersion = tile.version; ! output << decode(tile); ! } !} ! !
![Page 10: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/10.jpg)
10
C++11 concurrency
![Page 11: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/11.jpg)
11
Future/Promise
Future Promise
Promise<int> p; !Future<int> f = p.future(); !
promise.set(val); !std::cout << value; !
auto future = startAsync(); !// ... !// ... !int value = future.get(); !
Promise<int> promise; !
int val = calc(); !
![Page 12: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/12.jpg)
12
Использование Future
int meaningOfLife() { ! sleep(100500); ! return 42; !} !!int main() { ! std::future<int> meaningOfLife = std::async([] { ! return meaningOfLife(); ! }); !! std::future<int> calculation = std::async([] { return calcSmth(); }); !! std::cout << meaningOfLife().get() + calculation.get() << std::endl; !} !
{ calcSmth Meaning
Of Life
}
output
![Page 13: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/13.jpg)
13
std::async
Пример реализации std::async в случае создания отдельного потока на каждую операцию
Future<T> async(Function<T()> func) { ! Promise<T> promise; ! auto future = promise.future(); !! std::thread([promise = std::move(promise), func] { ! try { ! promise.setValue(func()); ! } catch (...) { ! promise.setException(std::current_exception()); ! } ! }).detach(); !! return future; !} !
![Page 14: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/14.jpg)
14
IO binding
Использование асинхронной сети в синхронном коде
void NetworkingAPI::httpGet(std::string url, ! std::function<void(Response, Error)>);!!Future<Response> httpGet(const std::string& url) { ! Promise<Response> promise; ! auto future = promise.future(); !! NetworkingAPI::httpGet(url, ! [promise = std::move(promise)] ! (Response response, Error error) { ! if (error) ! promise.setException(error); ! else ! promise.setValue(response); ! }); !} !
![Page 15: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/15.jpg)
15
Чего нет в std::
! Масштабируемость ! Отменяемость асинхронных операций
! Генераторы — функции, возвращающие множество результатов
![Page 16: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/16.jpg)
16
Контексты исполнения
! Потоки ! Процессы
![Page 17: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/17.jpg)
17
Coroutine – user-space thread Пишем асинхронный код синхронно
![Page 18: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/18.jpg)
18
Примитивы
async::Future !async::Promise !
async::Mutex!async::CV !
Coroutines!Coro Scheduler !
std::future !std::promise !
std::mutex!std::cv !
Threads !OS Scheduler !
Future.get() не блокирует поток
Реализованы ~одинаково
![Page 19: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/19.jpg)
19
Модель потоков
Все взаимодействие с IO – в отдельных выделенных потоках (сеть, диск) Все остальное – в глобальном thread pool
![Page 20: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/20.jpg)
20
Отмена операций
! Отмена через exception (Future.reset, ~Future) ! Cancellation points: wait, sleep, get
! Мгновенная отмена или ленивая?
![Page 21: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/21.jpg)
21
Генераторы
![Page 22: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/22.jpg)
22
Поточная десериализация Генератор1: байты Генератор2: байты объекты
MultiFuture<char> networkBytes(); !!MultiFuture<Object> objects(MultiFuture<char> bytesStream) { ! return async<Object>([](MultiPromise<Object>* output) { ! Parser parser(std::move(bytesStream)); !! while (!parser.finished()) { ! output->yield(parser.next()); ! } ! }; !} !!void Parser::read(int size, char* data) { ! while (size > 0) { ! *data = bytes_.get(); ! data++; ! size--; ! } !} !!
![Page 23: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/23.jpg)
23
Схема загрузки одного тайла Старт
Обновился?
Есть в памяти?
Есть на диске?
Сходить в диск
Сходить в сеть
Конец
Вернуть тайл
Декодировать и положить в память
Вернуть тайл
Вернуть тайл
Декодировать и положить в память
Нет
Да
Да
Да
Нет
Нет
![Page 24: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/24.jpg)
24
Загрузка одного тайла
NetTileProvider
Один сырой тайл
Запрос одной версии тайла из сети
RawTileLoader
Поток версий сырых данных
Кеширование на диске Версионирование
TileLoader
Поток версий готовых тайлов
Кеширование в памяти Декодирование
![Page 25: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/25.jpg)
25
RawTileLoader Задача – вернуть поток версий сырых данных
MultiFuture<RawTile> rawTileVersions(int x, y) { ! return async<RawTile>([=](MultiPromise<RawTile>* output) {! std::string currentVer, currentEtag; ! RawTile rawTile; !! if (rawTile = readFromDisk(x, y)) { ! currentVer = rawTile->version; ! currentEtag = rawTile->etag; ! output->yield(rawTile); ! } !! for (const auto& ver : versions_.subscribe()) { ! rawTile = loadFromNetwork(x, y, ver, currentEtag); !! writeToDisk(x, y, rawTile); !! currentVer = rawTile->version; ! currentEtag = rawTile->etag; ! output->yield(rawTile); ! } ! }); // async !} !
![Page 26: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/26.jpg)
26
TileLoader
Задача – вернуть поток версий одного тайла
MultiFuture<Tile> tileVersions(int x, y) { ! return async<Tile>([=](MultiPromise<Tile>* output) { ! Tile tile = memCache->get(x, y); ! if (tile) ! output->yield(tile); !! for (const auto& rawTile : rawTileVersions(x, y)) { ! tile.version = rawTile->version; ! if (tile.etag != rawTile->etag) { ! tile.etag = rawTile->etag; ! tile.data = decoder_(rawTile->rawData); ! } !! output->yield(tile); ! memCache_->set(x, y, tile); ! } ! }); // async !} !
![Page 27: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/27.jpg)
27
Линейный код из примера
void loadTile(int x, int y, output_iterator output) { ! if (auto tile = inMemory(x, y)) { ! output << tile; ! } !! if (auto tile = readFromDisk(x, y)) { ! output << decode(tile); ! prevVersion = tile.version; ! } !! while (true) { ! Tile tile = readFromNet(x, y, prevVersion); ! if (tile.version == prevVersion) continue; ! prevVersion = tile.version; ! output << decode(tile); ! } !} ! !
![Page 28: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/28.jpg)
28
Мы пишем понятный и выразительный код
И вам желаем того жеJ
![Page 29: Дмитрий Жестилевский — Yet another threading framework: асинхронная разработка на C++ под мобильные устройства](https://reader034.fdocuments.in/reader034/viewer/2022042521/54b6fd1e4a79590a338b4586/html5/thumbnails/29.jpg)
29
Спасибо за внимание!