SlideShare ist ein Scribd-Unternehmen logo
1 von 43
Асинхронность и
сопрограммы
Демченко Григорий, старший разработчик
C++ User Group, 27 февраля 2015
План рассказа
Реализация сопрограмм
Ожидающие примитивы
Примитивы, использующие планировщик
Заключение
План рассказа
Реализация сопрограмм
Ожидающие примитивы
Примитивы, использующие планировщик
Заключение
Многопоточный сервер
Acceptor acceptor(80);
while (true) {
socket = acceptor.accept();
go([socket] { // запуск в новом потоке
request = socket.read();
response = handleRequest(request);
socket.write(response);
});
}
• Недостатки:
o Большую часть времени потоки ожидают на I/O событиях и не
делают полезной работы => бесполезная трата ресурсов
Асинхронность
action1();
action2();
• Синхронность: action2 не выполняется, пока не закончится
action1.
• Асинхронность: action2 выполняется, даже если action1 не
завершился.
Асинхронность
Когда заканчивается операция?
1. Мы вызываем: периодический опрос состояния - реакторная
модель (select, epoll, kqueue)
2. Нас вызывают: проакторная модель исполнения (UI, IOCP,
javascript):
void onActionComplete(Result) {...}
action1(onActionComplete);
Будем использовать проактор boost.asio
Асинхронный сервер
Acceptor acceptor(80);
acceptor.onAccept([] (socket) {
socket.onRead([&socket](request) {
response = handleRequest(request);
socket.onWrite([&response]() {
// completed
});
});
// continue accepting???
});
• Более бережное использование ресурсов, но…
Асинхронный сервер: обсуждение
• Достоинства
o Производительность
o Относительно простая параллелизация
• Недостатки
o Сложность:
 Передача контекста
 Нелинейная структура кода
 Обработка ошибок
 Время жизни объектов
 Отладка
 С ростом количества операций сложность растет нелинейно
Решение
Что бы хотелось?
• У асинхронного взять быстродействие
• У синхронного - простоту
Т.е. объединить достоинства и убрать недостатки, присущие обоим
методам.
Как этого добиться? Ответ: использовать сопрограммы!!!
Сопрограммы
• Подпрограмма: выполняются все действия перед возвратом
управления
• Сопрограмма: частичное выполнение действий перед возвратом
управления
Сопрограмма обобщает понятие подпрограммы, т.е. подпрограмма -
это частный случай сопрограммы.
Пример сопрограммы: генераторы (например, на python)
Для эффективной реализации на С++ будем использовать метод
сохранения контекста исполнения (stackful coroutines).
Реализация сопрограмм
• Проблемы
o Сопрограммы никак не описаны в стандарте
o Необходимо применять низкоуровневые операции =>
зависимость от платформы, архитектуры и даже компилятора.
• Решение: использовать boost.context:
o Используется только ассемблер
o Поддержка платформ: Windows, Linux, MacOSX
o Поддержка мобильных платформ: Windows Phone, Android, IOS,
o Поддержка архитектур: x86, x86_64, ARM, Spark, Spark64, PPC,
PPC64, MIPS
o Поддержка компиляторов: GCC, Clang, Visual Studio
boost.context
Реализует 2 функции:
• make_fcontext: создает контекст и инициализирует стек
сопрограммы
• jump_fcontext: переходит в новый контекст с сохранением текущего
контекста для последующего возврата
Использование:
1. Выделение памяти под стек.
2. Создание контекста
ctx = make_fcontext(stackPtr, stackSize, callback)
3. Переход: jump_fcontext(callerCtx, ctx, ptr)
4. Возврат: jump_fcontext(ctx, callerCtx, ptr)
Реализация сопрограмм: Coro
void coroFn() {
CLOG("Yielding...");
yield();
CLOG("Returning...");
}
CLOG("Starting...");
Coro c(coroFn);
CLOG("Resuming...");
c.resume();
CLOG("Completed");
Выдача:
0: Starting...
1: Yielding...
0: Resuming...
1: Returning...
0: Completed
Использование сопрограмм
• Переделываем асинхронный вызов:
performAsyncOp(completionAction);
• В синхронный с использованием сопрограмм:
performOp();
void performOp() {
auto& coro = currentCoro();
performAsyncOp([&coro] { coro.resume(); });
yield();
}
Использование сопрограмм
• Scheduler:
boost::asio::io_service
• Thread: std::thread
• Coro: реализация с использованием
boost.context
• Network:
boost::asio::read/write/...
Проблема: состояние гонки
Возможно возобновление
работы сопрограммы до
выхода из нее
Варианты решения:
1. std::mutex
2. boost::asio::strand
3. defer
Решение: defer
defer: откладывание асинхронной
операции до выхода из
сопрограммы
typedef
std::function<void()> Action;
void defer(Action);
Использование defer
void performOp() {
auto& coro = currentCoro();
performAsyncOp([&coro] { coro.resume(); });
yield();
}
void performOp() {
auto& coro = currentCoro();
defer([&coro] {
performAsyncOp([&coro] { coro.resume(); });
});
}
Реализация на сопрограммах
Acceptor acceptor(80);
while (true) {
socket = acceptor.accept();
go([socket] { // запуск в сопрограмме
request = socket.read();
response = handleRequest(request);
socket.write(response);
});
}
• Код полностью идентичен синхронному подходу
План рассказа
Реализация сопрограмм
Ожидающие примитивы
Примитивы, использующие планировщик
Заключение
Ожидание завершения операции
• Задача: запустить асинхронно операцию и дождаться её завершения.
void goWait(Action action);
• Проблема обычного подхода: во время ожидания поток остается
заблокированным
• Сопрограммы с легкостью решают эту проблему
Ожидание завершения операции
void goWait(Action action) {
deferProceed([&action](Action proceed) {
go([proceed, &action] { // создаем новую сопрограмму
action();
proceed(); // продолжаем выполнение сопрограммы
});
});
}
void deferProceed(std::function<void(Action)> proceed) {
auto& coro = currentCoro();
defer([&coro, proceed] {
proceed([&coro] { coro.resume(); });
});
}
Ожидание завершения операций
• Задача: запустить асинхронно несколько операций и дождаться их
завершения.
void goWait(std::initializer_list<Action> actions);
• Проблема: во время ожидания поток остается заблокированным
• Сопрограммы с легкостью решают эту проблему
Ожидание завершения операций
void goWait(std::initializer_list<Action> actions) {
deferProceed([&actions](Action proceed) {
std::shared_ptr<void> proceeder(
nullptr, [proceed](void*) { proceed(); });
for (const auto& action: actions) {
go([proceeder, &action] {
action();
});
}
});
}
Ожидание завершения операций
Последовательность вызовов для:
goWait(action1, action2);
Пример: вычисление числа Фибоначчи
int fibo(int v) {
if (v < 2)
return v;
int v1, v2;
goWait({
[v, &v1] { v1 = fibo(v-1); },
[v, &v2] { v2 = fibo(v-2); }
});
return v1 + v2;
}
План рассказа
Реализация сопрограмм
Ожидающие примитивы
Примитивы, использующие планировщик
Заключение
Планировщик
• Интерфейс планировщика:
struct IScheduler {
virtual void schedule(Action action) = 0;
};
• Планировщик отвечает за запуск задач: action
• ThreadPool реализует интерфейс IScheduler с использованием
boost.asio:
struct ThreadPool : IScheduler {
ThreadPool(size_t thread_count) { … }
void schedule(Action action) {
service.post(std::move(action));
}
private:
boost::asio::io_service service;
};
Возобновление сопрограммы
• Возобновление работы сопрограммы происходит с использованием
планировщика:
struct Journey {
void proceed() {
scheduler->schedule([this] {
coro.resume();
onComplete();
});
}
void onComplete(); // вызов action в defer
// или удаление сопрограммы
private:
IScheduler* scheduler;
Coro coro;
};
Телепортация
• Переключение между планировщиками. Внутри сопрограммы:
ThreadPool tp1(1);
ThreadPool tp2(1);
go([&tp2] {
JLOG("Inside tp1");
teleport(tp2);
JLOG("And now inside tp2!!!");
}, tp1);
• Реализация:
void Journey::teleport(IScheduler& s) {
scheduler = &s;
defer(proceedAction());
}
Телепортация
Происходит
переключение
исполнения
сопрограммы с
Scheduler/Thread на
Scheduler2/Thread2
Портал
• Портал - телепортация туда и обратно:
struct Portal {
Portal(IScheduler& destination)
: source(currentScheduler()) {
teleport(destination);
}
~Portal() {
teleport(source);
}
private:
IScheduler& source;
};
Использования портала
• Пример использования портала:
struct Network {
void handleNetworkEvents() {
// долгие и нетривиальные операции
}
};
ThreadPool common(1);
ThreadPool networkPool(1);
portal<Network>().attach(networkPool);
go([] {
JLOG("Execution inside common");
portal<Network>()->handleNetworkEvents();
JLOG("Continue execution inside common");
}, common);
Alone
• Для глобальных объектов часто требуется эксклюзивный доступ.
Обычно используется мьютексы.
• Сопрограммы позволяют ввести новый паттерн: Alone.
struct Alone : IScheduler {
void schedule(Action action) {
strand.post(std::move(action));
}
private:
boost::asio::io_service::strand strand;
};
• Гарантирует выполнение не более одного action в каждый момент
времени.
Интегральный пример
struct DiskCache/MemCache {
boost::optional<std::string> get(const std::string& key);
void set(const std::string& key, const std::string& val);
};
ThreadPool commonPool(3); // общий пул потоков
ThreadPool diskPool(2); // пул для дисковых операций
Alone memAlone(commonPool); // сериализация действий с памятью
portal<DiskCache>().attach(diskPool); // привязка портала для диска
portal< MemCache>().attach(memAlone); // привязка портала для памяти
boost::optional<std::string> result = goAnyResult<std::string>({
[&key] { return portal<DiskCache>()->get(key); },
[&key] { return portal< MemCache>()->get(key); }
});
Обсуждение использования порталов
struct MemCache {
boost::optional<std::string> get(const std::string& key);
void set(const std::string& key, const std::string& val);
};
portal<MemCache>()->set(key, val);
Дружественность к исключениям
Абстракция от контекста исполнения: возможно использование с
различными планировщиками.
Порталы – аналог акторов:
– Типы сообщений → методы
– Сообщение → параметры метода
План рассказа
Реализация сопрограмм
Ожидающие примитивы
Примитивы, использующие планировщик
Заключение
Теорема
Любую асинхронную задачу можно решить с помощью сопрограмм
1. После вызова код отсутствует:
// код до вызова
async(..., action);
// код до вызова
synca(...); action();
2. После вызова код присутствует:
// код до вызова
async(..., action);
// код после вызова
// код до вызова
go { async(..., action); }
// код после вызова
// код до вызова
go { synca(...); action(); }
// код после вызова
Бонус: простой GC
struct A { ~A() { TLOG("~A"); } };
struct B:A { ~B() { TLOG("~B"); } };
struct C { ~C() { TLOG("~C"); } };
go([] {
A* a = gcnew<B>();
C* c = gcnew<C>();
});
Обратите внимание на невиртуальные
деструкторы!
Вывод в консоли:
tp#1: [1] ended
tp#1: ~C
tp#1: ~B
tp#1: ~A
Реализация простого GC
template<typename T, typename... V>
T* gcnew(V&&... v) {
return gc().add(new T(std::forward(v)...));
}
GC& gc() { return journey().gc; }
struct GC {
~GC() {
for (auto& deleter: boost::adaptors::reverse(deleters))
deleter();
}
template<typename T> T* add(T* t) {
deleters.emplace_back([t] { delete t; });
return t;
}
private:
std::vector<Handler> deleters;
};
Выводы
• Простота синхронного подхода
• Эффективность асинхронного подхода
• Бережное использование ресурсов (нет ожиданий)
• Эффективная реализация многопоточных паттернов
• Введение новых паттернов (телепортация, порталы, …)
• Это прикольно!
Код: https://bitbucket.org/gridem/synca
gridem@yandex-team.ru
http://habrahabr.ru/users/gridem
Спасибо за внимание!

Weitere ähnliche Inhalte

Was ist angesagt?

Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Yauheni Akhotnikau
 
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMSergey Platonov
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаSergey Platonov
 
Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Sergey Platonov
 
Современный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыСовременный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыcorehard_by
 
Евгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияЕвгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияPlatonov Sergey
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Sergey Platonov
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Yauheni Akhotnikau
 
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловПолухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловSergey Platonov
 
Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Dima Dzuba
 
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#Andrey Karpov
 
C++ Core Guidelines
C++ Core Guidelines C++ Core Guidelines
C++ Core Guidelines Sergey Zubkov
 
C++ refelection and cats
C++ refelection and catsC++ refelection and cats
C++ refelection and catscorehard_by
 
Основы и применение статического анализа кода при разработке лекция 1
Основы и применение статического анализа кода при разработке лекция 1Основы и применение статического анализа кода при разработке лекция 1
Основы и применение статического анализа кода при разработке лекция 1m2rus
 
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...Alexey Paznikov
 
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на LinuxПавел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на LinuxPlatonov Sergey
 
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...Alexey Paznikov
 
Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++Sergey Platonov
 

Was ist angesagt? (20)

Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?
 
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладка
 
Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++
 
Современный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыСовременный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтеры
 
Евгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияЕвгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализация
 
Parallel STL
Parallel STLParallel STL
Parallel STL
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++
 
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловПолухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
 
Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6
 
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
 
C++ Core Guidelines
C++ Core Guidelines C++ Core Guidelines
C++ Core Guidelines
 
C++ refelection and cats
C++ refelection and catsC++ refelection and cats
C++ refelection and cats
 
Основы и применение статического анализа кода при разработке лекция 1
Основы и применение статического анализа кода при разработке лекция 1Основы и применение статического анализа кода при разработке лекция 1
Основы и применение статического анализа кода при разработке лекция 1
 
Component Inspector
Component InspectorComponent Inspector
Component Inspector
 
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
 
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на LinuxПавел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
 
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
 
Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++
 

Andere mochten auch

CiklumCPPSat: Eugene Kulak "Stackless/stackfull coroutines and boost.asio"
CiklumCPPSat: Eugene Kulak "Stackless/stackfull coroutines and boost.asio"CiklumCPPSat: Eugene Kulak "Stackless/stackfull coroutines and boost.asio"
CiklumCPPSat: Eugene Kulak "Stackless/stackfull coroutines and boost.asio"Ciklum Ukraine
 
High quality library from scratch
High quality library from scratchHigh quality library from scratch
High quality library from scratchPlatonov Sergey
 
Debugging and Profiling C++ Template Metaprograms
Debugging and Profiling C++ Template MetaprogramsDebugging and Profiling C++ Template Metaprograms
Debugging and Profiling C++ Template MetaprogramsPlatonov Sergey
 
Конверсия управляемых языков в неуправляемые
Конверсия управляемых языков в неуправляемыеКонверсия управляемых языков в неуправляемые
Конверсия управляемых языков в неуправляемыеPlatonov Sergey
 
Address/Thread/Memory Sanitizer
Address/Thread/Memory SanitizerAddress/Thread/Memory Sanitizer
Address/Thread/Memory SanitizerPlatonov Sergey
 
Практика Lock-free. RealTime-сервер
Практика Lock-free. RealTime-серверПрактика Lock-free. RealTime-сервер
Практика Lock-free. RealTime-серверPlatonov Sergey
 
С++ without new and delete
С++ without new and deleteС++ without new and delete
С++ without new and deletePlatonov Sergey
 
Конкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнерыКонкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнерыPlatonov Sergey
 
Тененёв Анатолий, Boost.Asio в алгоритмической торговле
Тененёв Анатолий, Boost.Asio в алгоритмической торговлеТененёв Анатолий, Boost.Asio в алгоритмической торговле
Тененёв Анатолий, Boost.Asio в алгоритмической торговлеPlatonov Sergey
 
Multithreading done right
Multithreading done rightMultithreading done right
Multithreading done rightPlatonov Sergey
 
Антон Бикинеев, Reflection in C++Next
Антон Бикинеев,  Reflection in C++NextАнтон Бикинеев,  Reflection in C++Next
Антон Бикинеев, Reflection in C++NextSergey Platonov
 
Григорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерГригорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерSergey Platonov
 
Использование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработкиИспользование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработкиvictor-yastrebov
 
Догнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castRoman Orlov
 
Алексей Кутумов, C++ без исключений, часть 3
Алексей Кутумов,  C++ без исключений, часть 3Алексей Кутумов,  C++ без исключений, часть 3
Алексей Кутумов, C++ без исключений, часть 3Platonov Sergey
 
Фитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в формеФитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в формеIlia Shishkov
 
Evgeniy Muralev, Mark Vince, Working with the compiler, not against it
Evgeniy Muralev, Mark Vince, Working with the compiler, not against itEvgeniy Muralev, Mark Vince, Working with the compiler, not against it
Evgeniy Muralev, Mark Vince, Working with the compiler, not against itSergey Platonov
 
Quality assurance of large c++ projects
Quality assurance of large c++ projectsQuality assurance of large c++ projects
Quality assurance of large c++ projectscorehard_by
 
Fuzzing: The New Unit Testing
Fuzzing: The New Unit TestingFuzzing: The New Unit Testing
Fuzzing: The New Unit TestingDmitry Vyukov
 

Andere mochten auch (20)

CiklumCPPSat: Eugene Kulak "Stackless/stackfull coroutines and boost.asio"
CiklumCPPSat: Eugene Kulak "Stackless/stackfull coroutines and boost.asio"CiklumCPPSat: Eugene Kulak "Stackless/stackfull coroutines and boost.asio"
CiklumCPPSat: Eugene Kulak "Stackless/stackfull coroutines and boost.asio"
 
High quality library from scratch
High quality library from scratchHigh quality library from scratch
High quality library from scratch
 
Debugging and Profiling C++ Template Metaprograms
Debugging and Profiling C++ Template MetaprogramsDebugging and Profiling C++ Template Metaprograms
Debugging and Profiling C++ Template Metaprograms
 
Конверсия управляемых языков в неуправляемые
Конверсия управляемых языков в неуправляемыеКонверсия управляемых языков в неуправляемые
Конверсия управляемых языков в неуправляемые
 
Address/Thread/Memory Sanitizer
Address/Thread/Memory SanitizerAddress/Thread/Memory Sanitizer
Address/Thread/Memory Sanitizer
 
Практика Lock-free. RealTime-сервер
Практика Lock-free. RealTime-серверПрактика Lock-free. RealTime-сервер
Практика Lock-free. RealTime-сервер
 
С++ without new and delete
С++ without new and deleteС++ without new and delete
С++ without new and delete
 
Конкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнерыКонкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнеры
 
Тененёв Анатолий, Boost.Asio в алгоритмической торговле
Тененёв Анатолий, Boost.Asio в алгоритмической торговлеТененёв Анатолий, Boost.Asio в алгоритмической торговле
Тененёв Анатолий, Boost.Asio в алгоритмической торговле
 
Multithreading done right
Multithreading done rightMultithreading done right
Multithreading done right
 
Антон Бикинеев, Reflection in C++Next
Антон Бикинеев,  Reflection in C++NextАнтон Бикинеев,  Reflection in C++Next
Антон Бикинеев, Reflection in C++Next
 
Григорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерГригорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптер
 
Использование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработкиИспользование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработки
 
Clang tidy
Clang tidyClang tidy
Clang tidy
 
Догнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_cast
 
Алексей Кутумов, C++ без исключений, часть 3
Алексей Кутумов,  C++ без исключений, часть 3Алексей Кутумов,  C++ без исключений, часть 3
Алексей Кутумов, C++ без исключений, часть 3
 
Фитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в формеФитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в форме
 
Evgeniy Muralev, Mark Vince, Working with the compiler, not against it
Evgeniy Muralev, Mark Vince, Working with the compiler, not against itEvgeniy Muralev, Mark Vince, Working with the compiler, not against it
Evgeniy Muralev, Mark Vince, Working with the compiler, not against it
 
Quality assurance of large c++ projects
Quality assurance of large c++ projectsQuality assurance of large c++ projects
Quality assurance of large c++ projects
 
Fuzzing: The New Unit Testing
Fuzzing: The New Unit TestingFuzzing: The New Unit Testing
Fuzzing: The New Unit Testing
 

Ähnlich wie Асинхронность и сопрограммы

Asynchrony and coroutines
Asynchrony and coroutinesAsynchrony and coroutines
Asynchrony and coroutinescorehard_by
 
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияГригорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияSergey Platonov
 
Froglogic Squish
Froglogic Squish Froglogic Squish
Froglogic Squish SQALab
 
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...Yandex
 
Node.js введение в технологию, КПИ #ITmeetingKPI
Node.js введение в технологию, КПИ  #ITmeetingKPINode.js введение в технологию, КПИ  #ITmeetingKPI
Node.js введение в технологию, КПИ #ITmeetingKPITimur Shemsedinov
 
IT-инфраструктура. FAQ для разработчика
IT-инфраструктура. FAQ для разработчикаIT-инфраструктура. FAQ для разработчика
IT-инфраструктура. FAQ для разработчикаMikhail Chinkov
 
OpenStack - Python Project with 12 Million Lines of code (RUS, Moscow Python ...
OpenStack - Python Project with 12 Million Lines of code (RUS, Moscow Python ...OpenStack - Python Project with 12 Million Lines of code (RUS, Moscow Python ...
OpenStack - Python Project with 12 Million Lines of code (RUS, Moscow Python ...Vadim Ponomarev
 
ПВТ - осень 2014 - Лекция 3 - Стандарт POSIX Threads
ПВТ - осень 2014 - Лекция 3 - Стандарт POSIX ThreadsПВТ - осень 2014 - Лекция 3 - Стандарт POSIX Threads
ПВТ - осень 2014 - Лекция 3 - Стандарт POSIX ThreadsAlexey Paznikov
 
20090720 hpc exercise1
20090720 hpc exercise120090720 hpc exercise1
20090720 hpc exercise1Michael Karpov
 
ВВЕДЕНИЕ В NODE.JS
ВВЕДЕНИЕ В NODE.JS ВВЕДЕНИЕ В NODE.JS
ВВЕДЕНИЕ В NODE.JS Pavel Tsukanov
 
JavaScript. Event Loop and Timers (in russian)
JavaScript. Event Loop and Timers (in russian)JavaScript. Event Loop and Timers (in russian)
JavaScript. Event Loop and Timers (in russian)Mikhail Davydov
 
Zero Downtime PHP Deployment with Envoyer And Forge
Zero Downtime PHP Deployment with Envoyer And ForgeZero Downtime PHP Deployment with Envoyer And Forge
Zero Downtime PHP Deployment with Envoyer And ForgeYehor Herasymchuk
 
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полнойОмские ИТ-субботники
 
2012 03 14_parallel_programming_lecture05
2012 03 14_parallel_programming_lecture052012 03 14_parallel_programming_lecture05
2012 03 14_parallel_programming_lecture05Computer Science Club
 
Асинхронные вызовы в .NET
Асинхронные вызовы в .NETАсинхронные вызовы в .NET
Асинхронные вызовы в .NETBonart
 
Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"Yandex
 
Система обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на GroovyСистема обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на GroovyRegn
 

Ähnlich wie Асинхронность и сопрограммы (20)

Asynchrony and coroutines
Asynchrony and coroutinesAsynchrony and coroutines
Asynchrony and coroutines
 
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияГригорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизация
 
Froglogic Squish
Froglogic Squish Froglogic Squish
Froglogic Squish
 
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
Подходы и технологии, используемые в разработке iOS-клиента Viber, Кирилл Лаш...
 
Node.js введение в технологию, КПИ #ITmeetingKPI
Node.js введение в технологию, КПИ  #ITmeetingKPINode.js введение в технологию, КПИ  #ITmeetingKPI
Node.js введение в технологию, КПИ #ITmeetingKPI
 
IT-инфраструктура. FAQ для разработчика
IT-инфраструктура. FAQ для разработчикаIT-инфраструктура. FAQ для разработчика
IT-инфраструктура. FAQ для разработчика
 
Async
AsyncAsync
Async
 
Luxoft async.net
Luxoft async.netLuxoft async.net
Luxoft async.net
 
OpenStack - Python Project with 12 Million Lines of code (RUS, Moscow Python ...
OpenStack - Python Project with 12 Million Lines of code (RUS, Moscow Python ...OpenStack - Python Project with 12 Million Lines of code (RUS, Moscow Python ...
OpenStack - Python Project with 12 Million Lines of code (RUS, Moscow Python ...
 
JavaDay'14
JavaDay'14JavaDay'14
JavaDay'14
 
ПВТ - осень 2014 - Лекция 3 - Стандарт POSIX Threads
ПВТ - осень 2014 - Лекция 3 - Стандарт POSIX ThreadsПВТ - осень 2014 - Лекция 3 - Стандарт POSIX Threads
ПВТ - осень 2014 - Лекция 3 - Стандарт POSIX Threads
 
20090720 hpc exercise1
20090720 hpc exercise120090720 hpc exercise1
20090720 hpc exercise1
 
ВВЕДЕНИЕ В NODE.JS
ВВЕДЕНИЕ В NODE.JS ВВЕДЕНИЕ В NODE.JS
ВВЕДЕНИЕ В NODE.JS
 
JavaScript. Event Loop and Timers (in russian)
JavaScript. Event Loop and Timers (in russian)JavaScript. Event Loop and Timers (in russian)
JavaScript. Event Loop and Timers (in russian)
 
Zero Downtime PHP Deployment with Envoyer And Forge
Zero Downtime PHP Deployment with Envoyer And ForgeZero Downtime PHP Deployment with Envoyer And Forge
Zero Downtime PHP Deployment with Envoyer And Forge
 
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
 
2012 03 14_parallel_programming_lecture05
2012 03 14_parallel_programming_lecture052012 03 14_parallel_programming_lecture05
2012 03 14_parallel_programming_lecture05
 
Асинхронные вызовы в .NET
Асинхронные вызовы в .NETАсинхронные вызовы в .NET
Асинхронные вызовы в .NET
 
Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"
 
Система обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на GroovyСистема обработки бизнес-логики server-side приложения на Groovy
Система обработки бизнес-логики server-side приложения на Groovy
 

Mehr von Platonov Sergey

Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.Platonov Sergey
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках II
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IIДмитрий Кашицын, Вывод типов в динамических и не очень языках II
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IIPlatonov Sergey
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IДмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IPlatonov Sergey
 
QML\Qt Quick на практике
QML\Qt Quick на практикеQML\Qt Quick на практике
QML\Qt Quick на практикеPlatonov Sergey
 
Визуализация автомобильных маршрутов
Визуализация автомобильных маршрутовВизуализация автомобильных маршрутов
Визуализация автомобильных маршрутовPlatonov Sergey
 
Функциональный микроскоп: линзы в C++
Функциональный микроскоп: линзы в C++Функциональный микроскоп: линзы в C++
Функциональный микроскоп: линзы в C++Platonov Sergey
 
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...Platonov Sergey
 
HPX: C++11 runtime система для параллельных и распределённых вычислений
HPX: C++11 runtime система для параллельных и распределённых вычисленийHPX: C++11 runtime система для параллельных и распределённых вычислений
HPX: C++11 runtime система для параллельных и распределённых вычисленийPlatonov Sergey
 
Ranges calendar-novosibirsk-2015-08
Ranges calendar-novosibirsk-2015-08Ranges calendar-novosibirsk-2015-08
Ranges calendar-novosibirsk-2015-08Platonov Sergey
 
Использование maven для сборки больших модульных c++ проектов на примере Odin...
Использование maven для сборки больших модульных c++ проектов на примере Odin...Использование maven для сборки больших модульных c++ проектов на примере Odin...
Использование maven для сборки больших модульных c++ проектов на примере Odin...Platonov Sergey
 
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведенияДракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведенияPlatonov Sergey
 
One definition rule - что это такое, и как с этим жить
One definition rule - что это такое, и как с этим житьOne definition rule - что это такое, и как с этим жить
One definition rule - что это такое, и как с этим житьPlatonov Sergey
 
DI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыDI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыPlatonov Sergey
 
Аскетичная разработка браузера
Аскетичная разработка браузераАскетичная разработка браузера
Аскетичная разработка браузераPlatonov Sergey
 
Денис Кормалев Метаобъектная система Qt
Денис Кормалев Метаобъектная система QtДенис Кормалев Метаобъектная система Qt
Денис Кормалев Метаобъектная система QtPlatonov Sergey
 
Максим Хижинский Lock-free maps
Максим Хижинский Lock-free mapsМаксим Хижинский Lock-free maps
Максим Хижинский Lock-free mapsPlatonov Sergey
 
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...Platonov Sergey
 
Categories for the Working C++ Programmer
Categories for the Working C++ ProgrammerCategories for the Working C++ Programmer
Categories for the Working C++ ProgrammerPlatonov Sergey
 

Mehr von Platonov Sergey (20)

Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках II
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IIДмитрий Кашицын, Вывод типов в динамических и не очень языках II
Дмитрий Кашицын, Вывод типов в динамических и не очень языках II
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IДмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
 
QML\Qt Quick на практике
QML\Qt Quick на практикеQML\Qt Quick на практике
QML\Qt Quick на практике
 
Визуализация автомобильных маршрутов
Визуализация автомобильных маршрутовВизуализация автомобильных маршрутов
Визуализация автомобильных маршрутов
 
Функциональный микроскоп: линзы в C++
Функциональный микроскоп: линзы в C++Функциональный микроскоп: линзы в C++
Функциональный микроскоп: линзы в C++
 
C++ exceptions
C++ exceptionsC++ exceptions
C++ exceptions
 
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
 
HPX: C++11 runtime система для параллельных и распределённых вычислений
HPX: C++11 runtime система для параллельных и распределённых вычисленийHPX: C++11 runtime система для параллельных и распределённых вычислений
HPX: C++11 runtime система для параллельных и распределённых вычислений
 
Ranges calendar-novosibirsk-2015-08
Ranges calendar-novosibirsk-2015-08Ranges calendar-novosibirsk-2015-08
Ranges calendar-novosibirsk-2015-08
 
Использование maven для сборки больших модульных c++ проектов на примере Odin...
Использование maven для сборки больших модульных c++ проектов на примере Odin...Использование maven для сборки больших модульных c++ проектов на примере Odin...
Использование maven для сборки больших модульных c++ проектов на примере Odin...
 
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведенияДракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
 
One definition rule - что это такое, и как с этим жить
One definition rule - что это такое, и как с этим житьOne definition rule - что это такое, и как с этим жить
One definition rule - что это такое, и как с этим жить
 
DI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыDI в C++ тонкости и нюансы
DI в C++ тонкости и нюансы
 
Аскетичная разработка браузера
Аскетичная разработка браузераАскетичная разработка браузера
Аскетичная разработка браузера
 
Concepts lite
Concepts liteConcepts lite
Concepts lite
 
Денис Кормалев Метаобъектная система Qt
Денис Кормалев Метаобъектная система QtДенис Кормалев Метаобъектная система Qt
Денис Кормалев Метаобъектная система Qt
 
Максим Хижинский Lock-free maps
Максим Хижинский Lock-free mapsМаксим Хижинский Lock-free maps
Максим Хижинский Lock-free maps
 
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
 
Categories for the Working C++ Programmer
Categories for the Working C++ ProgrammerCategories for the Working C++ Programmer
Categories for the Working C++ Programmer
 

Асинхронность и сопрограммы

  • 1.
  • 2. Асинхронность и сопрограммы Демченко Григорий, старший разработчик C++ User Group, 27 февраля 2015
  • 3. План рассказа Реализация сопрограмм Ожидающие примитивы Примитивы, использующие планировщик Заключение
  • 4. План рассказа Реализация сопрограмм Ожидающие примитивы Примитивы, использующие планировщик Заключение
  • 5. Многопоточный сервер Acceptor acceptor(80); while (true) { socket = acceptor.accept(); go([socket] { // запуск в новом потоке request = socket.read(); response = handleRequest(request); socket.write(response); }); } • Недостатки: o Большую часть времени потоки ожидают на I/O событиях и не делают полезной работы => бесполезная трата ресурсов
  • 6. Асинхронность action1(); action2(); • Синхронность: action2 не выполняется, пока не закончится action1. • Асинхронность: action2 выполняется, даже если action1 не завершился.
  • 7. Асинхронность Когда заканчивается операция? 1. Мы вызываем: периодический опрос состояния - реакторная модель (select, epoll, kqueue) 2. Нас вызывают: проакторная модель исполнения (UI, IOCP, javascript): void onActionComplete(Result) {...} action1(onActionComplete); Будем использовать проактор boost.asio
  • 8. Асинхронный сервер Acceptor acceptor(80); acceptor.onAccept([] (socket) { socket.onRead([&socket](request) { response = handleRequest(request); socket.onWrite([&response]() { // completed }); }); // continue accepting??? }); • Более бережное использование ресурсов, но…
  • 9. Асинхронный сервер: обсуждение • Достоинства o Производительность o Относительно простая параллелизация • Недостатки o Сложность:  Передача контекста  Нелинейная структура кода  Обработка ошибок  Время жизни объектов  Отладка  С ростом количества операций сложность растет нелинейно
  • 10. Решение Что бы хотелось? • У асинхронного взять быстродействие • У синхронного - простоту Т.е. объединить достоинства и убрать недостатки, присущие обоим методам. Как этого добиться? Ответ: использовать сопрограммы!!!
  • 11. Сопрограммы • Подпрограмма: выполняются все действия перед возвратом управления • Сопрограмма: частичное выполнение действий перед возвратом управления Сопрограмма обобщает понятие подпрограммы, т.е. подпрограмма - это частный случай сопрограммы. Пример сопрограммы: генераторы (например, на python) Для эффективной реализации на С++ будем использовать метод сохранения контекста исполнения (stackful coroutines).
  • 12. Реализация сопрограмм • Проблемы o Сопрограммы никак не описаны в стандарте o Необходимо применять низкоуровневые операции => зависимость от платформы, архитектуры и даже компилятора. • Решение: использовать boost.context: o Используется только ассемблер o Поддержка платформ: Windows, Linux, MacOSX o Поддержка мобильных платформ: Windows Phone, Android, IOS, o Поддержка архитектур: x86, x86_64, ARM, Spark, Spark64, PPC, PPC64, MIPS o Поддержка компиляторов: GCC, Clang, Visual Studio
  • 13. boost.context Реализует 2 функции: • make_fcontext: создает контекст и инициализирует стек сопрограммы • jump_fcontext: переходит в новый контекст с сохранением текущего контекста для последующего возврата Использование: 1. Выделение памяти под стек. 2. Создание контекста ctx = make_fcontext(stackPtr, stackSize, callback) 3. Переход: jump_fcontext(callerCtx, ctx, ptr) 4. Возврат: jump_fcontext(ctx, callerCtx, ptr)
  • 14. Реализация сопрограмм: Coro void coroFn() { CLOG("Yielding..."); yield(); CLOG("Returning..."); } CLOG("Starting..."); Coro c(coroFn); CLOG("Resuming..."); c.resume(); CLOG("Completed"); Выдача: 0: Starting... 1: Yielding... 0: Resuming... 1: Returning... 0: Completed
  • 15. Использование сопрограмм • Переделываем асинхронный вызов: performAsyncOp(completionAction); • В синхронный с использованием сопрограмм: performOp(); void performOp() { auto& coro = currentCoro(); performAsyncOp([&coro] { coro.resume(); }); yield(); }
  • 16. Использование сопрограмм • Scheduler: boost::asio::io_service • Thread: std::thread • Coro: реализация с использованием boost.context • Network: boost::asio::read/write/...
  • 17. Проблема: состояние гонки Возможно возобновление работы сопрограммы до выхода из нее Варианты решения: 1. std::mutex 2. boost::asio::strand 3. defer
  • 18. Решение: defer defer: откладывание асинхронной операции до выхода из сопрограммы typedef std::function<void()> Action; void defer(Action);
  • 19. Использование defer void performOp() { auto& coro = currentCoro(); performAsyncOp([&coro] { coro.resume(); }); yield(); } void performOp() { auto& coro = currentCoro(); defer([&coro] { performAsyncOp([&coro] { coro.resume(); }); }); }
  • 20. Реализация на сопрограммах Acceptor acceptor(80); while (true) { socket = acceptor.accept(); go([socket] { // запуск в сопрограмме request = socket.read(); response = handleRequest(request); socket.write(response); }); } • Код полностью идентичен синхронному подходу
  • 21. План рассказа Реализация сопрограмм Ожидающие примитивы Примитивы, использующие планировщик Заключение
  • 22. Ожидание завершения операции • Задача: запустить асинхронно операцию и дождаться её завершения. void goWait(Action action); • Проблема обычного подхода: во время ожидания поток остается заблокированным • Сопрограммы с легкостью решают эту проблему
  • 23. Ожидание завершения операции void goWait(Action action) { deferProceed([&action](Action proceed) { go([proceed, &action] { // создаем новую сопрограмму action(); proceed(); // продолжаем выполнение сопрограммы }); }); } void deferProceed(std::function<void(Action)> proceed) { auto& coro = currentCoro(); defer([&coro, proceed] { proceed([&coro] { coro.resume(); }); }); }
  • 24. Ожидание завершения операций • Задача: запустить асинхронно несколько операций и дождаться их завершения. void goWait(std::initializer_list<Action> actions); • Проблема: во время ожидания поток остается заблокированным • Сопрограммы с легкостью решают эту проблему
  • 25. Ожидание завершения операций void goWait(std::initializer_list<Action> actions) { deferProceed([&actions](Action proceed) { std::shared_ptr<void> proceeder( nullptr, [proceed](void*) { proceed(); }); for (const auto& action: actions) { go([proceeder, &action] { action(); }); } }); }
  • 27. Пример: вычисление числа Фибоначчи int fibo(int v) { if (v < 2) return v; int v1, v2; goWait({ [v, &v1] { v1 = fibo(v-1); }, [v, &v2] { v2 = fibo(v-2); } }); return v1 + v2; }
  • 28. План рассказа Реализация сопрограмм Ожидающие примитивы Примитивы, использующие планировщик Заключение
  • 29. Планировщик • Интерфейс планировщика: struct IScheduler { virtual void schedule(Action action) = 0; }; • Планировщик отвечает за запуск задач: action • ThreadPool реализует интерфейс IScheduler с использованием boost.asio: struct ThreadPool : IScheduler { ThreadPool(size_t thread_count) { … } void schedule(Action action) { service.post(std::move(action)); } private: boost::asio::io_service service; };
  • 30. Возобновление сопрограммы • Возобновление работы сопрограммы происходит с использованием планировщика: struct Journey { void proceed() { scheduler->schedule([this] { coro.resume(); onComplete(); }); } void onComplete(); // вызов action в defer // или удаление сопрограммы private: IScheduler* scheduler; Coro coro; };
  • 31. Телепортация • Переключение между планировщиками. Внутри сопрограммы: ThreadPool tp1(1); ThreadPool tp2(1); go([&tp2] { JLOG("Inside tp1"); teleport(tp2); JLOG("And now inside tp2!!!"); }, tp1); • Реализация: void Journey::teleport(IScheduler& s) { scheduler = &s; defer(proceedAction()); }
  • 33. Портал • Портал - телепортация туда и обратно: struct Portal { Portal(IScheduler& destination) : source(currentScheduler()) { teleport(destination); } ~Portal() { teleport(source); } private: IScheduler& source; };
  • 34. Использования портала • Пример использования портала: struct Network { void handleNetworkEvents() { // долгие и нетривиальные операции } }; ThreadPool common(1); ThreadPool networkPool(1); portal<Network>().attach(networkPool); go([] { JLOG("Execution inside common"); portal<Network>()->handleNetworkEvents(); JLOG("Continue execution inside common"); }, common);
  • 35. Alone • Для глобальных объектов часто требуется эксклюзивный доступ. Обычно используется мьютексы. • Сопрограммы позволяют ввести новый паттерн: Alone. struct Alone : IScheduler { void schedule(Action action) { strand.post(std::move(action)); } private: boost::asio::io_service::strand strand; }; • Гарантирует выполнение не более одного action в каждый момент времени.
  • 36. Интегральный пример struct DiskCache/MemCache { boost::optional<std::string> get(const std::string& key); void set(const std::string& key, const std::string& val); }; ThreadPool commonPool(3); // общий пул потоков ThreadPool diskPool(2); // пул для дисковых операций Alone memAlone(commonPool); // сериализация действий с памятью portal<DiskCache>().attach(diskPool); // привязка портала для диска portal< MemCache>().attach(memAlone); // привязка портала для памяти boost::optional<std::string> result = goAnyResult<std::string>({ [&key] { return portal<DiskCache>()->get(key); }, [&key] { return portal< MemCache>()->get(key); } });
  • 37. Обсуждение использования порталов struct MemCache { boost::optional<std::string> get(const std::string& key); void set(const std::string& key, const std::string& val); }; portal<MemCache>()->set(key, val); Дружественность к исключениям Абстракция от контекста исполнения: возможно использование с различными планировщиками. Порталы – аналог акторов: – Типы сообщений → методы – Сообщение → параметры метода
  • 38. План рассказа Реализация сопрограмм Ожидающие примитивы Примитивы, использующие планировщик Заключение
  • 39. Теорема Любую асинхронную задачу можно решить с помощью сопрограмм 1. После вызова код отсутствует: // код до вызова async(..., action); // код до вызова synca(...); action(); 2. После вызова код присутствует: // код до вызова async(..., action); // код после вызова // код до вызова go { async(..., action); } // код после вызова // код до вызова go { synca(...); action(); } // код после вызова
  • 40. Бонус: простой GC struct A { ~A() { TLOG("~A"); } }; struct B:A { ~B() { TLOG("~B"); } }; struct C { ~C() { TLOG("~C"); } }; go([] { A* a = gcnew<B>(); C* c = gcnew<C>(); }); Обратите внимание на невиртуальные деструкторы! Вывод в консоли: tp#1: [1] ended tp#1: ~C tp#1: ~B tp#1: ~A
  • 41. Реализация простого GC template<typename T, typename... V> T* gcnew(V&&... v) { return gc().add(new T(std::forward(v)...)); } GC& gc() { return journey().gc; } struct GC { ~GC() { for (auto& deleter: boost::adaptors::reverse(deleters)) deleter(); } template<typename T> T* add(T* t) { deleters.emplace_back([t] { delete t; }); return t; } private: std::vector<Handler> deleters; };
  • 42. Выводы • Простота синхронного подхода • Эффективность асинхронного подхода • Бережное использование ресурсов (нет ожиданий) • Эффективная реализация многопоточных паттернов • Введение новых паттернов (телепортация, порталы, …) • Это прикольно! Код: https://bitbucket.org/gridem/synca gridem@yandex-team.ru http://habrahabr.ru/users/gridem

Hinweis der Redaktion

  1. из-за этого не скейлится
  2. не показано: время жизни обработка ошибок проблема с зацикливанием
  3. -> создается прокси-класс Portal с исключениями тоже работает!
  4. -- отличие: пассивность: исполняет вызывающий, а не вызываемый! Аналог - лопата и тот, кто копает, можно делать параллельно, что в случае актора - достаточно затруднительно
  5. легко прикручивается аллокация из пулов памяти!!!
  6. легко прикручивается аллокация из пулов памяти!!!
  7. прикольно: расширение языка для решения своих задач иной подход и взгляд на вещи, расширение кругозора всякие бонусы