SlideShare une entreprise Scribd logo
1  sur  73
Télécharger pour lire hors ligne
CoreHard C++ Autumn 2016
Модель Акторов и C++:
что, зачем и как?
Евгений Охотников
О чем пойдет речь?
Многопоточность и parallel concurrent computing.
Модель Акторов в двух-трех-четырех-...-двенадцати слайдах.
Сегодняшние иконы "Модели Акторов". Все две штуки.
А как же C++ (пока его еще не закопали)?
NIH*-синдром или что есть готового для C++?
2* NIH - Not Invented Here
Многопоточность – это...
инструмент, который активно применяется в двух очень разных областях:
● parallel computing (одновременно выполняются одинаковые операции
над разными наборами однотипных данных);
● concurrent computing (одновременно выполняются совсем разные
операции, возможно, над совершенно разными данными).
Concurrent computing может быть и без многопоточности. Но на базе
многопоточности concurrent computing доставляет больше всего...
3
Далее только о многопоточности...
...применительно к concurrent computing.
Именно здесь Модель Акторов оказывается очень удобной.
А для parallel computing используются другие подходы и другие
инструменты...
4
Итак, многопоточность – это сложно
Таки да, это сложно.
Даже имея 20 лет опыта.
Но почему?
5
Изменяемое разделяемое состояние
Именно изменяемое разделяемое состояние является одним из главных
факторов сложности в многопоточном программировании.
6
Как упростить себе жизнь?
7
Убрать разделяемое состояние
Ничего не разделяем. Ни за что не боремся.
Пусть каждый поток владеет своими собственными данными. И никто кроме
потока-владельца не имеет к этим данным доступа.
Принцип shared nothing* (широко известен в узких кругах).
8* https://en.wikipedia.org/wiki/Shared_nothing_architecture
Убрать разделяемое состояние
Но что делать, если потоку X потребовалась какая-то информация, которая
есть у потока Y?
Что делать, если поток Y хочет, чтобы поток Z обновил какие-то данные у
себя?
9
Потокам нужно общаться, но как?
Кажется, что есть два способа:
1. Синхронно.
2. Асинхронно.
Но это только кажется...
10
На самом-то деле...
...никакой синхронности, только хардкор асинхронное взаимодействие.
Например, на основе отсылки и приема сообщений:
● поток X отсылает сообщение-запрос потоку Y;
● поток Y когда-то получит запрос потока X, обработает запрос и отошлет
потоку X ответ;
● поток Y отсылает сообщение-обновление потоку Z;
● поток Z когда-то получит сообщение-обновление от потока Y и обновит
те данные, которые принадлежат потоку Z.
11
Просто же!
Есть потоки. У каждого есть очередь входящих сообщений.
Поток спит, если очередь входящих сообщений пуста.
Поток просыпается, когда для него появляются входящие сообщения.
Если потоку X нужно что-то от потока Y, то X отсылает сообщение в очередь
входящих сообщений потока Y.
Если поток Y хочет ответить потоку X, то Y отсылает сообщение в очередь
входящих сообщений потока X.
12
А если сообщения несут копию данных...
...то мы получаем очень приятный бонус: прозрачный переход к
распределенности.
Если поток Y передал в сообщении Msg копию данных, а не ссылку на них, то
уже не суть важно, пойдет ли сообщение Msg в локальную очередь
входящих сообщений потока Z. Или же в очередь исходящих данных для
передачи на другой хост.
Сообщение самодостаточно. Поэтому может быть сериализовано, передано
по сети, десериализовано и обработано.
13
Вот и весь фокус :)
Модель акторов именно про это.
Про изолированные потоки управления.
И про их взаимодействие на основе обмена сообщениями.
14
Модель Акторов
Появилась в 1973-ем году благодаря работам Карла Хьюитта (Carl Hewitt).
Была затем развита в 1981-ом Уильямом Клингером (William Clinger).
И в 1985-ом Гулом Агха (Gul Agha).
Это если говорить про формализацию Модели Акторов.
Неформально она открывалась и переоткрывалась множество раз.
15
Модель Акторов
Отправные точки для желающих погрузиться в формальную теорию Модели
Акторов:
https://en.wikipedia.org/wiki/History_of_the_Actor_model
https://en.wikipedia.org/wiki/Actor_model
https://en.wikipedia.org/wiki/Actor_model_theory
16
Модель Акторов. Основные принципы
● актор – это некая сущность, обладающая поведением;
● акторы реагируют на входящие сообщения;
● получив сообщение актор может:
○ отослать некоторое (конечное) количество сообщений другим
акторам;
○ создать некоторое (конечное) количество новых акторов;
○ определить для себя новое поведение для обработки последующих
сообщений.
17
Актор – это некоторая сущность
Не более того.
Актором может быть отдельный процесс. Например, Erlang.
Актором может быть отдельный поток (OS thread, "green" thread, fiber, ...).
Например, goroutine в Go может рассматриваться как актор.
Актором может быть объект, которому кто-то выделяет рабочий контекст.
Например, Akka.
18
Еще раз: актор – это некоторая сущность
Модель Акторов не требует, чтобы актор был процессом или потоком, или
конечным автоматом, или чем-то еще.
Поэтому существующие и востребованные на практике реализации Модели
Акторов очень сильно отличаются друг от друга.
19
Модели Акторов уже более 40 лет
За это время Модель Акторов пережила несколько волн популярности и
забвения*
Сейчас очередная волна популярности. Она началась где-то около 10-12 лет
назад. Основным двигателем интереса стали Erlang, а затем Akka.
20* Why has the actor model not succeeded?
Современные иконы: Erlang
Пожалуй, самая известная реализация – язык Erlang*
http://www.erlang.org/
Не только сам язык, но и Erlang VM, и OTP, и вообще все, что понастроили
вокруг.
21* Я не встречал, чтобы Джо Армстронг говорил, что на Erlang повлияла Модель Акторов
Современные иконы: Erlang
Зародился в одной из исследовательских лабораторий Ericsson-а в 1986-ом
году благодаря Джо Армстронгу (Joe Armstrong).
В 1995-ом году после закрытия неудачного проекта AXE-N (на C++, кстати)
был выбран в качестве основного языка для проекта AXD.
Результатом стал успешный программно-аппаратный продукт AXD301 в
котором было более миллиона строк на Erlang.
22
Современные иконы: Erlang
В конце 1990-х использование Erlang-а для новых проектов в Ericsson Radio
AB было запрещено.
Джо Армстронг покинул Ericsson.
Erlang ушел в OpenSource.
Erlang доказал свою состоятельность вне Ericsson-а. Ericsson одумался.
В 2004-ом году Джо Армстронг возвратился в Ericsson.
23
Современные иконы: Erlang
За последние годы Erlang многократно показывал себя с лучшей стороны в
очень серьезных проектах (например, WhatsApp использует Erlang).
Многие компании убедившись в достоинствах Erlang-а задействуют Erlang в
своих разработках.
Из близких нам примеров: Wargaming.
24
Современные иконы: Erlang
-module(tut15).
-export([start/0, ping/2, pong/0]).
ping(0, Pong_PID) ->
Pong_PID ! finished,
io:format("ping finished~n", []);
ping(N, Pong_PID) ->
Pong_PID ! {ping, self()},
receive
pong ->
io:format("Ping received pong~n", [])
end,
ping(N - 1, Pong_PID).
25
pong() ->
receive
finished ->
io:format("Pong finished~n", []);
{ping, Ping_PID} ->
io:format("Pong received ping~n", []),
Ping_PID ! pong,
pong()
end.
start() ->
Pong_PID = spawn(tut15, pong, []),
spawn(tut15, ping, [3, Pong_PID]).
Современные иконы: Akka
Фреймворк для Java и Scala.
http://akka.io/
История началась в 2006: Филипп Холлер (Philipp Haller) разработал
реализацию Модели Акторов для стандартной библиотеки языка Scala.
В 2008-ом Джонас Бонер (Jonas Bonér) начал делать Erlang-овский OTP для
Scala на базе акторов из Scala-stdlib*. Первая публичная версия Akka вышла
в 2010-ом.
26* http://www.lightbend.com/akka-five-year-anniversary
Современные иконы: Akka
Очень популярна в JVM-мире.
Соответственно, находит широкое применение там, где позиции JVM
традиционно сильны: Web, онлайн-сервисы и суровый энтерпрайз...
Яркие примеры: LinkedIn и Twitter.
Стоящие за Akka люди так же причастны к таким современным buzz-word-ам,
как Reactive Manifesto* и Microservices** :)
27
* http://www.reactivemanifesto.org/
** https://en.wikipedia.org/wiki/Microservices
Современные иконы: Akka
import akka.actor._
case object PingMessage
case object PongMessage
case object StartMessage
case object StopMessage
class Ping(pong: ActorRef) extends Actor {
var count = 0
def incrementAndPrint { count += 1; println("ping") }
def receive = {
case StartMessage =>
incrementAndPrint
pong ! PingMessage
case PongMessage =>
incrementAndPrint
if (count > 99) {
sender ! StopMessage
println("ping stopped")
context.stop(self)
} else {
sender ! PingMessage
}
28
}
}
class Pong extends Actor {
def receive = {
case PingMessage =>
println(" pong")
sender ! PongMessage
case StopMessage =>
println("pong stopped")
context.stop(self)
}
}
object PingPongTest extends App {
val system = ActorSystem("PingPongSystem")
val pong = system.actorOf(Props[Pong], name = "pong")
val ping = system.actorOf(Props(new Ping(pong)), name = "ping")
// start them going
ping ! StartMessage
}
http://alvinalexander.com/scala/scala-akka-actors-ping-pong-simple-example
В чем сила, брат?
Что же такое предлагают своим пользователям Erlang и Akka?
Почему они востребованы и используются в очень серьезных проектах?
29
Вот в чем:
1. Простота. Отсутствие разделяемых данных и взаимодействие
посредством асинхронных сообщений спасают от ужасов
программирования на мьютексах.
2. Масштабирование. Акторов может быть хоть миллион. Даже самую
мелкую задачку можно поручить отдельному актору. Акторов можно
распределять по нескольким процессам и нескольким нодам, при
асинхронном обмене сообщениями это не суть важно.
3. Отказоустойчивость. Какие-то акторы могут "падать", другие акторы
это обнаружат и исправят (см. систему супервизоров Erlang-а*). Shared
nothing + message-passing сильно помогают и тут.
30* http://erlang.org/doc/man/supervisor.html
Так говорил Джо Армстронг
I also suspect that the advent of true parallel CPU cores will make
programming parallel systems using conventional mutexes and
shared data structures almost impossibly difficult, and that the pure
message-passing systems will become the dominant way to program
parallel systems.
Так же я подозреваю, что пришествие настоящих многоядерных CPU сделает
программирование параллельных систем с использованием традиционных мьютексов и
разделяемых структур данных сложным до невозможности, и что именно обмен
сообщениями станет доминирующим способом разработки параллельных систем.
Disclaimer: перевод приблизительный, но основной смысл передан верно.
31A History of Erlang, Joe Armstrong, 2007.
Кстати об отказоустойчивости
Erlang и Java/Scala (речь об Akka) – это безопасные языки, работающие в
управляемых средах (Erlang VM и JVM).
На отказоустойчивость это влияет самым непосредственным образом.
Деление на ноль в одном из процессов внутри Erlang VM и деление на ноль в
одном из потоков большого приложения на C++ – это две большие разницы.
32
А что с C++?
Есть ли смысл в использовании Модели Акторов в C++?
33
Неверный вопрос!
Начинать нужно с более важного вопроса:
А нужен ли вообще C++?
34
Серьезно? И это на CoreHard C++?
Таки да :(
35
Так нужен ли вообще C++?
С++ старый язык (более 30 лет с публичного релиза).
За это время стал настоящим монстром, стандарт которого насчитывает
~1500 страниц. И это еще C++17 не приняли...
Вобрал в себя множество нового (в переводе на русский: стал еще сложнее).
Сохранил при этом совместимость с еще более древним языком С. Так что с
отстрелом конечностей все в порядке.
Каждый большой проект использует собственное подмножество C++.
Огромное количество копролитов мамонта легаси кода.
36
Тем не менее...
...какой еще мейнстримовый нативный язык без GC:
● настолько же быстр и эффективен?
● позволяет работать на самом низком уровне?
● позволяет подниматься на высокие уровни абстракции (ООП,
обобщенное программирование, метапрограммирование)?
● снабжен таким же количеством разнообразного инструментария?
● так же хорошо и досконально описан в огромном количестве книг,
статей, руководств, рекомендаций и пр.?
● обладает таким же большим коммьюнити?
Если объективно посмотреть по сторонам, то альтернатив не так уж и много.
37
Вывод прост: нужен, однозначно!
А раз нужен, то нужны и инструменты, облегчающие жизнь C++
разработчикам.
В том числе и реализации Модели Акторов для C++.
38
Больше фреймворков, хороших и разных!
Более-менее актуальный список инструментов для C++ можно найти здесь:
https://en.wikipedia.org/wiki/Actor_model#Actor_libraries_and_frameworks
Там не все. А часть того, что есть, уже умерло. Но все-таки.
39
Четверо смелых для беглого знакомства
Далее быстрый забег "по верхам" для знакомства с четырьмя C++
фреймворками, которые:
● на C++;
● подают признаки жизни (что уже не мало, на самом-то деле);
● кросс-платформенны;
● интересны с той или иной стороны.
Есть еще, например, OOSMOS* и Asyncronous Agents Library** от MS, но они
не вошли в обзор из-за нарушения каких-то из перечисленных выше пунктов.
40
* http://www.oosmos.com/
** https://msdn.microsoft.com/en-us/library/dd492627.aspx
QP/C++
http://www.state-machine.com/qpcpp/
C++98/03. Предназначен для разработки встраиваемого ПО. В том числе и
для работы на голом железе.
Двойная лицензия.
Более 15 лет развития и эксплуатации.
Декларируется приличный уровень соответствия MISRA C++2008.
41
QP/C++
Акторы в QP/C++ – это иерархические конечные автоматы. Называются
активными объектами.
Код активных объектов можно писать обычным образом. Т.е. вручную
набирать код C++ классов, методов и вот это вот все.
А можно "нарисовать" активный объект в специальном визуальном
инструменте для проектирования и C++ код будет сгенерирован.
Контекст для работы активных объектов предоставляет QP. В зависимости
от окружения активные объекты могут работать на отдельных нитях. А могут
и сообща на одной-единственной.
42
QP/C++ (пример кода: blinky.h)
#ifndef blinky_h
#define blinky_h
using namespace QP;
enum BlinkySignals {
DUMMY_SIG = Q_USER_SIG,
MAX_PUB_SIG, // the last published signal
TIMEOUT_SIG,
MAX_SIG // the last signal
};
extern QMActive * const AO_Blinky; // opaque pointer
#endif // blinky_h
43
QP/C++ (пример кода: main.cpp)
#include "qpcpp.h"
#include "bsp.h"
#include "blinky.h"
int main() {
static QEvt const *blinkyQSto[10]; // Event queue storage for Blinky
BSP_init(); // initialize the Board Support Package
QF::init(); // initialize the framework and the underlying RT kernel
// instantiate and start the active objects...
AO_Blinky->start(1U, // priority
blinkyQSto, Q_DIM(blinkyQSto), // event queue
(void *)0, 0U); // stack (unused)
return QF::run(); // run the QF application
}
44
QP/C++ (пример кода: blinky.cpp, 1)
#include "qpcpp.h"
#include "bsp.h"
#include "blinky.h"
class Blinky : public QActive {
private:
QTimeEvt m_timeEvt;
public:
Blinky();
protected:
static QState initial(Blinky * const me, QEvt const * const e);
static QState off(Blinky * const me, QEvt const * const e);
static QState on(Blinky * const me, QEvt const * const e);
};
Blinky l_blinky;
QMActive * const AO_Blinky = &l_blinky; // opaque pointer
45
QP/C++ (пример кода: blinky.cpp, 2)
Blinky::Blinky()
: QActive(Q_STATE_CAST(&Blinky::initial)),
m_timeEvt(this, TIMEOUT_SIG, 0U)
{}
QState Blinky::initial(Blinky * const me, QEvt const * const e) {
(void)e; // unused parameter
// arm the time event to expire in half a second and every half second
me->m_timeEvt.armX(BSP_TICKS_PER_SEC/2U, BSP_TICKS_PER_SEC/2U);
return Q_TRAN(&Blinky::off);
}
46
QP/C++ (пример кода: blinky.cpp, 3)
QState Blinky::off(Blinky * const me, QEvt const * const e)
{
QState status;
switch (e->sig) {
case Q_ENTRY_SIG: {
BSP_ledOff();
status = Q_HANDLED();
break;
}
case TIMEOUT_SIG: {
status = Q_TRAN(&Blinky::on);
break;
}
default: {
status = Q_SUPER(&QHsm::top);
break;
}
}
return status;
}
47
QState Blinky::on(Blinky * const me, QEvt const * const e)
{
QState status;
switch (e->sig) {
case Q_ENTRY_SIG: {
BSP_ledOn();
status = Q_HANDLED();
break;
}
case TIMEOUT_SIG: {
status = Q_TRAN(&Blinky::off);
break;
}
default: {
status = Q_SUPER(&QHsm::top);
break;
}
}
return status;
}
Just::Thread Pro: Actors Edition
http://www.stdthread.co.uk/pro/
C++11.
Платная библиотека.
Автор – Энтони Уильямс (Anthony Williams). Он же написал книгу "C++
Concurrency in Action".
На этом, пожалуй, достоинства заканчиваются :)
Под каждого актора выделяется отдельный поток ОС.
48
Just::Thread Pro: Actors Edition (ping-pong)
#include <jss/actor.hpp>
#include <iostream>
#include <thread>
int main()
{
struct pingpong {
jss::actor_ref sender;
pingpong(jss::actor_ref sender_): sender(sender_) {}
};
jss::actor pp1(
[]{
for(;;)
{
jss::actor::receive().match<pingpong>(
[](pingpong p){
std::cout<<"pingn";
p.sender.send(pingpong(jss::actor::self()));
});
}
});
49
jss::actor pp2(
[]{
for(;;)
{
jss::actor::receive().match<pingpong>(
[](pingpong p){
std::cout<<"pongn";
p.sender.send(pingpong(jss::actor::self()));
});
}
});
pp1.send(pingpong(pp2));
std::this_thread::sleep_for(std::chrono::seconds(2));
pp1.stop();
pp2.stop();
}
C++ Actor Framework (он же CAF)
http://www.actor-framework.org/
C++11 и выше (чем выше, тем лучше).
OpenSource под BSD-3-CLAUSE лицензией.
Самая распиаренная реализация Модели Акторов для C++.
Позиционирует себя как очень быстрый фреймворк. Не то, чтобы так уж
заслуженно* ;)
Пока еще не стабилизировался.
50* Performance Comparison SO-5.5.15.2 vs CAF-0.14.4
C++ Actor Framework (он же CAF)
Изначально копировал Erlang в C++ настолько близко, насколько это
возможно. Постепенно видоизменяется и приобретает свои уникальные
черты.
Ценой за мимикрию под Erlang являются высокие требования CAF-а к
уровню поддержки стандартов в C++ в компиляторе.
Официальная поддержка Windows/VC++ появилась только после выхода
Visual Studio 2015 update 3.
Есть поддержка распределенности. Собственный протокол с реализацией на
базе Boost::Asio.
51
C++ Actor Framework (fixed_stack, 1)
#include <cassert>
#include <cstdint>
#include <iostream>
#include "caf/all.hpp"
using std::endl;
using namespace caf;
namespace {
using pop_atom = atom_constant<atom("pop")>;
using push_atom = atom_constant<atom("push")>;
enum class fixed_stack_errc : uint8_t { push_to_full = 1, pop_from_empty };
error make_error(fixed_stack_errc x) {
return error{static_cast<uint8_t>(x), atom("FixedStack")};
}
52
C++ Actor Framework (fixed_stack, 2)
class fixed_stack : public event_based_actor {
public:
fixed_stack(actor_config& cfg, size_t stack_size)
: event_based_actor(cfg),
size_(stack_size) {
full_.assign(
[=](push_atom, int) -> error {
return fixed_stack_errc::push_to_full;
},
[=](pop_atom) -> int {
auto result = data_.back();
data_.pop_back();
become(filled_);
return result;
}
);
53
C++ Actor Framework (fixed_stack, 3)
filled_.assign(
[=](push_atom, int what) {
data_.push_back(what);
if (data_.size() == size_)
become(full_);
},
[=](pop_atom) -> int {
auto result = data_.back();
data_.pop_back();
if (data_.empty())
become(empty_);
return result;
}
);
54
C++ Actor Framework (fixed_stack, 4)
empty_.assign(
[=](push_atom, int what) {
data_.push_back(what);
become(filled_);
},
[=](pop_atom) -> error {
return fixed_stack_errc::pop_from_empty;
}
);
}
55
C++ Actor Framework (fixed_stack, 5)
behavior make_behavior() override {
assert(size_ < 2);
return empty_;
}
private:
size_t size_;
std::vector<int> data_;
behavior full_;
behavior filled_;
behavior empty_;
};
56
C++ Actor Framework (fixed_stack, 6)
void caf_main(actor_system& system) {
scoped_actor self{system};
auto st = self->spawn<fixed_stack>(5u);
// fill stack
for (int i = 0; i < 10; ++i) self->send(st, push_atom::value, i);
// drain stack
aout(self) << "stack: { ";
bool stack_empty = false;
while (!stack_empty) {
self->request(st, std::chrono::seconds(10), pop_atom::value).receive(
[&](int x) {
aout(self) << x << " ";
},
[&](const error&) {
stack_empty = true;
}
);
}
aout(self) << "}" << endl;
self->send_exit(st, exit_reason::user_shutdown);
}
} // namespace <anonymous>
CAF_MAIN()
57
SObjectizer-5
https://sourceforge.net/projects/sobjectizer/ или https://github.com/eao197/so-5-5
C++11 (минимальные требования к компилятору: GCC 4.8, MSVC++12.0).
OpenSource под BSD-3-CLAUSE лицензией.
С очень долгой историей:
1995-2000: Гомель, КБ Системного Программирования, проект SCADA Objectizer;
2002-...: Гомель-Москва, Интервэйл, проект SObjectizer-4;
2010-...: Гомель-Москва, Интервэйл, The SObjectizer Team, проект SObjectizer-5.
58
SObjectizer-5
SO-4 в продакшене c 2002-го года. И до сих пор работает.
SO-5 в продакшене с 2011-го года.
Обратная совместимость – must have.
Без фанатизма, но позволить себе вносить ломающие совместимость
изменения в каждый релиз мы не можем. От слова совсем.
Версия SO-5.5.0 вышла в октябре 2014-го. С тех пор в ветке 5.5.* нет ломающих
изменений. Последняя стабильная версия 5.5.18 – сентябрь 2016.
59
SObjectizer-5
Акторы в SO-5 называются агентами. Так сложилось.
Агенты в SO-5 – это иерархические конечные автоматы (вложенные
состояния, обработчики входа-выхода, история, временные лимиты).
Рабочий контекст агентам предоставляют диспетчеры.
Разработчику "из коробки" доступно восемь типов готовых диспетчеров.
Распределенность в SO-5 не поддерживается. Был опыт в SO-4. Поэтому в
SO-5 решили обходиться готовыми сторонними инструментами по задачу
(MQTT, AMQP, HTTP и т.д.).
60
SObjectizer-5
Главное отличие от прочих фреймворков: SO-5 – это симбиоз Модели
Акторов, модели Publish/Subscribe. С элементами CSP*
Сообщения отсылаются не агенту, а в message box (mbox). За mbox-ом
может быть один агент, может быть множество агентов. Или ни одного.
Mbox является аналогом Topic-а из Pub/Sub. Отсылка сообщения – аналогом
Publish-а из Pub/Sub. И, как и в Pub/Sub, агент должен подписаться на
сообщение, чтобы получить его.
61* https://en.wikipedia.org/wiki/Communicating_sequential_processes
SObjectizer-5 (blinking_led, 1)
#include <iostream>
#include <so_5/all.hpp>
class blinking_led final : public so_5::agent_t
{
state_t off{ this }, blinking{ this },
blink_on{ initial_substate_of{ blinking } },
blink_off{ substate_of{ blinking } };
public :
struct turn_on_off : public so_5::signal_t {};
62
SObjectizer-5 (blinking_led, 2)
blinking_led( context_t ctx ) : so_5::agent_t{ ctx }
{
this >>= off;
off.just_switch_to< turn_on_off >( blinking );
blinking.just_switch_to< turn_on_off >( off );
blink_on
.on_enter( []{ std::cout << "ON" << std::endl; } )
.on_exit( []{ std::cout << "off" << std::endl; } )
.time_limit( std::chrono::milliseconds{1250}, blink_off );
blink_off
.time_limit( std::chrono::milliseconds{750}, blink_on );
}
};
63
SObjectizer-5 (blinking_led, 3)
int main() {
so_5::launch( []( so_5::environment_t & env ) {
so_5::mbox_t m;
env.introduce_coop( [&]( so_5::coop_t & coop ) {
auto led = coop.make_agent< blinking_led >();
m = led->so_direct_mbox();
} );
auto pause = []( unsigned int v ) { std::this_thread::sleep_for( std::chrono::seconds{v} ); };
so_5::send< blinking_led::turn_on_off >( m );
pause( 10 );
so_5::send< blinking_led::turn_on_off >( m );
pause( 5 );
so_5::send< blinking_led::turn_on_off >( m );
pause( 5 );
env.stop();
} );
}
64
Заключение 1/3
Модель Акторов – это очень удобный инструмент в случаях, где
использование этой модели уместно1
.
Это уже неоднократно доказывалось успешным применением таких
инструментов, как Erlang и Akka в самых разнообразных проектах.
Да и вообще за асинхронным обменом сообщений между независимыми
сущностями будущее. Прислушайтесь к Джо Армстронгу, он плохого не
посоветует ;)
1)
Не верьте рекламе: уместно не везде.
65
Заключение 2/3
Наш опыт показывает, что при наличии подходящих инструментов Модель
Акторов имеет смысл применять и в C++.
При этом для C++ подходящие готовые инструменты уже есть.
На разный вкус и цвет.
И размер кошелька, конечно же.
В коммерческом проекте за QP/C++ и за Just::Thread Pro придется заплатить.
За SObjectizer и CAF – нет. По крайней мере сразу не придется.
66
Заключение 3/3
Вот чего делать не стоит, так это браться за написание собственного
акторного фреймворка.
Неблагодарное это дело. Проверено. На людях.
Лучше все-таки взять что-то готовое. Hint: купляйце беларускае.
И пусть кто-нибудь другой весело бегает по граблям многопоточности :)
67
Спасибо за терпение!
Вопросы?
68
Bonus track (SO-5's fixed_stack, 1)
#include <iostream>
#include <so_5/all.hpp>
class fixed_stack final : public so_5::agent_t
{
state_t st_empty{ this },
st_filled{ this },
st_full{ this };
const size_t m_max_size;
std::vector< int > m_stack;
public :
class empty_stack final : public std::logic_error
{
public :
using std::logic_error::logic_error;
};
struct push { int m_val; };
struct pop : public so_5::signal_t {};
69* https://bitbucket.org/sobjectizerteam/fixed_stack_example
Bonus track (SO-5's fixed_stack, 2)
fixed_stack( context_t ctx, size_t max_size )
: so_5::agent_t( ctx )
, m_max_size( max_size )
{
this >>= st_empty;
so_subscribe_self()
.in( st_empty )
.in( st_filled )
.event( &fixed_stack::on_push );
so_subscribe_self()
.in( st_filled )
.in( st_full )
.event( &fixed_stack::on_pop_when_not_empty );
so_subscribe_self()
.in( st_empty )
.event( &fixed_stack::on_pop_when_empty );
}
70
Bonus track (SO-5's fixed_stack, 3)
private :
void on_push( const push & w )
{
m_stack.push_back( w.m_val );
this >>= ( m_stack.size() == m_max_size ? st_full : st_filled );
}
int on_pop_when_not_empty( mhood_t< pop > )
{
auto r = m_stack.back();
m_stack.pop_back();
this >>= ( m_stack.empty() ? st_empty : st_filled );
return r;
}
int on_pop_when_empty( mhood_t< pop > )
{
throw empty_stack( "empty_stack" );
}
};
71
Bonus track (SO-5's fixed_stack, 4)
int main() {
try {
so_5::launch( []( so_5::environment_t & env ) {
so_5::mbox_t stack;
env.introduce_coop( [&stack]( so_5::coop_t & coop ) {
stack = coop.make_agent< fixed_stack >( 5u )->so_direct_mbox();
} );
for( int i = 0; i < 10; ++i ) so_5::send< fixed_stack::push >( stack, i );
std::cout << "stack { ";
try {
for(;;)
std::cout << so_5::request_value< int, fixed_stack::pop >( stack, std::chrono::seconds(10) ) << " ";
}
catch( const fixed_stack::empty_stack & ) {}
std::cout << "}" << std::endl;
env.stop();
} );
return 0;
}
catch( const std::exception & x ) {
std::cerr << "Oops! " << x.what() << std::endl;
}
return 2;
}
72
Документация по SObjectizer: https://sourceforge.net/p/sobjectizer/wiki/Home/
Серия статей о SObjectizer на русском:
SObjectizer: что это, для чего это и почему это выглядит именно так? От простого к сложному:
Часть I, Часть II, Часть III. Акторы в виде конечных автоматов – это плохо или хорошо?
Проблема перегрузки агентов и средства борьбы с ней. Нежная дружба агентов и
исключений.
Серия презентаций о SObjectizer на английском "Dive into SObjectizer-5.5":
Intro, Agent's States, More About Coops, Exceptions, Timers, Synchonous Interaction, Message
Limits, Dispatchers, Message Chains.
Блог автора доклада: eao197.blogspot.com
О SObjectizer в блоге: eao197.blogspot.com/search/label/SObjectizer
Почта автора доклада: eao197 на gmail тчк com
73

Contenu connexe

Tendances

Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Yauheni Akhotnikau
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаSergey Platonov
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Sergey Platonov
 
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Sergey Platonov
 
C++ refelection and cats
C++ refelection and catsC++ refelection and cats
C++ refelection and catscorehard_by
 
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Sergey Platonov
 
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Yandex
 
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksMikhail Kurnosov
 
Погружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьПогружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьYauheni Akhotnikau
 
Дизайн больших приложений в ФП
Дизайн больших приложений в ФПДизайн больших приложений в ФП
Дизайн больших приложений в ФПAlexander Granin
 
Память в Java. Garbage Collector
Память в Java. Garbage CollectorПамять в Java. Garbage Collector
Память в Java. Garbage CollectorOlexandra Dmytrenko
 
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptСергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptSergey Platonov
 
Deep Dive C# by Sergey Teplyakov
Deep Dive  C# by Sergey TeplyakovDeep Dive  C# by Sergey Teplyakov
Deep Dive C# by Sergey TeplyakovAlex Tumanoff
 
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMSergey Platonov
 
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловПолухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловSergey Platonov
 
Async clinic by by Sergey Teplyakov
Async clinic by by Sergey TeplyakovAsync clinic by by Sergey Teplyakov
Async clinic by by Sergey TeplyakovAlex Tumanoff
 
64-битная версия Loki
64-битная версия Loki64-битная версия Loki
64-битная версия LokiTatyanazaxarova
 
C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.Igor Shkulipa
 
C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.Igor Shkulipa
 

Tendances (20)

Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладка
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++
 
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
 
C++ refelection and cats
C++ refelection and catsC++ refelection and cats
C++ refelection and cats
 
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
 
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
 
Обзор SObjectizer 5.5
Обзор SObjectizer 5.5Обзор SObjectizer 5.5
Обзор SObjectizer 5.5
 
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
 
Погружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьПогружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная часть
 
Дизайн больших приложений в ФП
Дизайн больших приложений в ФПДизайн больших приложений в ФП
Дизайн больших приложений в ФП
 
Память в Java. Garbage Collector
Память в Java. Garbage CollectorПамять в Java. Garbage Collector
Память в Java. Garbage Collector
 
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptСергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
 
Deep Dive C# by Sergey Teplyakov
Deep Dive  C# by Sergey TeplyakovDeep Dive  C# by Sergey Teplyakov
Deep Dive C# by Sergey Teplyakov
 
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
 
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловПолухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
 
Async clinic by by Sergey Teplyakov
Async clinic by by Sergey TeplyakovAsync clinic by by Sergey Teplyakov
Async clinic by by Sergey Teplyakov
 
64-битная версия Loki
64-битная версия Loki64-битная версия Loki
64-битная версия Loki
 
C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.
 
C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.C++ STL & Qt. Занятие 09.
C++ STL & Qt. Занятие 09.
 

En vedette

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?Yauheni Akhotnikau
 
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017Mikhail Matrosov
 
Антон Бикинеев, Reflection in C++Next
Антон Бикинеев,  Reflection in C++NextАнтон Бикинеев,  Reflection in C++Next
Антон Бикинеев, Reflection in C++NextSergey Platonov
 
Григорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерГригорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерSergey Platonov
 
Использование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработкиИспользование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработкиvictor-yastrebov
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Platonov Sergey
 
Догнать и перегнать 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
 
Василий Сорокин, Простой REST сервер на Qt с рефлексией
Василий Сорокин, Простой REST сервер на Qt с рефлексиейВасилий Сорокин, Простой REST сервер на Qt с рефлексией
Василий Сорокин, Простой REST сервер на Qt с рефлексиейSergey Platonov
 
Потоковая обработка данных с помощью модели акторов (Actor Model)
Потоковая обработка данных с помощью модели акторов (Actor Model)Потоковая обработка данных с помощью модели акторов (Actor Model)
Потоковая обработка данных с помощью модели акторов (Actor Model)Vadim Tsesko
 
C++ Actor Model - You’ve Got Mail ...
C++ Actor Model - You’ve Got Mail ...C++ Actor Model - You’ve Got Mail ...
C++ Actor Model - You’ve Got Mail ...Gianluca Padovani
 

En vedette (17)

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?
 
Clang tidy
Clang tidyClang tidy
Clang tidy
 
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
 
Антон Бикинеев, Reflection in C++Next
Антон Бикинеев,  Reflection in C++NextАнтон Бикинеев,  Reflection in C++Next
Антон Бикинеев, Reflection in C++Next
 
Григорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерГригорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптер
 
Использование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработкиИспользование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработки
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
 
Parallel STL
Parallel STLParallel STL
Parallel STL
 
Догнать и перегнать 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
 
Василий Сорокин, Простой REST сервер на Qt с рефлексией
Василий Сорокин, Простой REST сервер на Qt с рефлексиейВасилий Сорокин, Простой REST сервер на Qt с рефлексией
Василий Сорокин, Простой REST сервер на Qt с рефлексией
 
Потоковая обработка данных с помощью модели акторов (Actor Model)
Потоковая обработка данных с помощью модели акторов (Actor Model)Потоковая обработка данных с помощью модели акторов (Actor Model)
Потоковая обработка данных с помощью модели акторов (Actor Model)
 
C++ Actor Model - You’ve Got Mail ...
C++ Actor Model - You’ve Got Mail ...C++ Actor Model - You’ve Got Mail ...
C++ Actor Model - You’ve Got Mail ...
 

Similaire à Модель акторов и C++ что, зачем и как?

Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Yandex
 
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)ScalaNsk
 
лекция1
лекция1лекция1
лекция1shagore
 
Большой брат помогает тебе
Большой брат помогает тебеБольшой брат помогает тебе
Большой брат помогает тебеTatyanazaxarova
 
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...Yauheni Akhotnikau
 
Как жить в согласии с SOLID?
Как жить в согласии с SOLID?Как жить в согласии с SOLID?
Как жить в согласии с SOLID?etyumentcev
 
Denys Samoylenko ''JS learning lifehacks: common programmer's mistake''
Denys Samoylenko ''JS learning lifehacks: common programmer's mistake''Denys Samoylenko ''JS learning lifehacks: common programmer's mistake''
Denys Samoylenko ''JS learning lifehacks: common programmer's mistake''OdessaJS Conf
 
Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013ScalaNsk
 
#noBackend, или Как выжить в эпоху толстеющих клиентов
#noBackend, или Как выжить в эпоху толстеющих клиентов#noBackend, или Как выжить в эпоху толстеющих клиентов
#noBackend, или Как выжить в эпоху толстеющих клиентовNikolay Samokhvalov
 
noBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов Николай
noBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов НиколайnoBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов Николай
noBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов НиколайOntico
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU
 
Как приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMКак приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMTech Talks @NSU
 
Discovering Lambdas in Java 8
Discovering Lambdas in Java 8Discovering Lambdas in Java 8
Discovering Lambdas in Java 8Stfalcon Meetups
 
C++ теория
C++ теорияC++ теория
C++ теорияtank1975
 
C++ теория
C++ теорияC++ теория
C++ теорияtank1975
 
C++ теория
C++ теорияC++ теория
C++ теорияtank1975
 

Similaire à Модель акторов и C++ что, зачем и как? (20)

Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
Руслан Гроховецкий "Как Python стал делать погоду в Яндексе"
 
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
 
лекция1
лекция1лекция1
лекция1
 
Уроки Scratch
Уроки Scratch Уроки Scratch
Уроки Scratch
 
Большой брат помогает тебе
Большой брат помогает тебеБольшой брат помогает тебе
Большой брат помогает тебе
 
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
Акторы в C++: взгляд старого практикующего актородела (St. Petersburg C++ Use...
 
Как жить в согласии с SOLID?
Как жить в согласии с SOLID?Как жить в согласии с SOLID?
Как жить в согласии с SOLID?
 
Denys Samoylenko ''JS learning lifehacks: common programmer's mistake''
Denys Samoylenko ''JS learning lifehacks: common programmer's mistake''Denys Samoylenko ''JS learning lifehacks: common programmer's mistake''
Denys Samoylenko ''JS learning lifehacks: common programmer's mistake''
 
Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013
 
C sharp deep dive
C sharp deep diveC sharp deep dive
C sharp deep dive
 
C# Deep Dive
C# Deep DiveC# Deep Dive
C# Deep Dive
 
#noBackend, или Как выжить в эпоху толстеющих клиентов
#noBackend, или Как выжить в эпоху толстеющих клиентов#noBackend, или Как выжить в эпоху толстеющих клиентов
#noBackend, или Как выжить в эпоху толстеющих клиентов
 
noBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов Николай
noBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов НиколайnoBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов Николай
noBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов Николай
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVM
 
Как приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMКак приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVM
 
KL10TCH: Paver.js + T.js
KL10TCH: Paver.js + T.jsKL10TCH: Paver.js + T.js
KL10TCH: Paver.js + T.js
 
Discovering Lambdas in Java 8
Discovering Lambdas in Java 8Discovering Lambdas in Java 8
Discovering Lambdas in Java 8
 
C++ теория
C++ теорияC++ теория
C++ теория
 
C++ теория
C++ теорияC++ теория
C++ теория
 
C++ теория
C++ теорияC++ теория
C++ теория
 

Plus de Yauheni Akhotnikau

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 exampleYauheni Akhotnikau
 
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)Yauheni Akhotnikau
 
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)Yauheni Akhotnikau
 
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)Yauheni Akhotnikau
 
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...Yauheni Akhotnikau
 
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...Yauheni Akhotnikau
 
Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Yauheni Akhotnikau
 
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 EyesYauheni Akhotnikau
 
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 allYauheni Akhotnikau
 
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 MessagesYauheni Akhotnikau
 
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 ChainsYauheni Akhotnikau
 
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: DispatchersYauheni Akhotnikau
 
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.9Yauheni Akhotnikau
 
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 LimitsYauheni Akhotnikau
 
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 InteractionYauheni Akhotnikau
 
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: TimersYauheni Akhotnikau
 
What’s new in SObjectizer 5.5.8
What’s new in SObjectizer 5.5.8What’s new in SObjectizer 5.5.8
What’s new in SObjectizer 5.5.8Yauheni Akhotnikau
 
Dive into SObjectizer 5.5. Fourth part. Exception
Dive into SObjectizer 5.5. Fourth part. ExceptionDive into SObjectizer 5.5. Fourth part. Exception
Dive into SObjectizer 5.5. Fourth part. ExceptionYauheni Akhotnikau
 
Dive into SObjectizer 5.5. Third part. Coops
Dive into SObjectizer 5.5. Third part. CoopsDive into SObjectizer 5.5. Third part. Coops
Dive into SObjectizer 5.5. Third part. CoopsYauheni Akhotnikau
 
Dive into SObjectizer 5.5. Introductory part
Dive into SObjectizer 5.5. Introductory partDive into SObjectizer 5.5. Introductory part
Dive into SObjectizer 5.5. Introductory partYauheni Akhotnikau
 

Plus de 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)
 
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
[C++ CoreHard Autumn 2018] Actors vs CSP vs Task...
 
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++: стоило ли оно того?
Акторы на 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
 
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
 
What’s new in SObjectizer 5.5.8
What’s new in SObjectizer 5.5.8What’s new in SObjectizer 5.5.8
What’s new in SObjectizer 5.5.8
 
Dive into SObjectizer 5.5. Fourth part. Exception
Dive into SObjectizer 5.5. Fourth part. ExceptionDive into SObjectizer 5.5. Fourth part. Exception
Dive into SObjectizer 5.5. Fourth part. Exception
 
Dive into SObjectizer 5.5. Third part. Coops
Dive into SObjectizer 5.5. Third part. CoopsDive into SObjectizer 5.5. Third part. Coops
Dive into SObjectizer 5.5. Third part. Coops
 
Dive into SObjectizer 5.5. Introductory part
Dive into SObjectizer 5.5. Introductory partDive into SObjectizer 5.5. Introductory part
Dive into SObjectizer 5.5. Introductory part
 

Модель акторов и C++ что, зачем и как?

  • 1. CoreHard C++ Autumn 2016 Модель Акторов и C++: что, зачем и как? Евгений Охотников
  • 2. О чем пойдет речь? Многопоточность и parallel concurrent computing. Модель Акторов в двух-трех-четырех-...-двенадцати слайдах. Сегодняшние иконы "Модели Акторов". Все две штуки. А как же C++ (пока его еще не закопали)? NIH*-синдром или что есть готового для C++? 2* NIH - Not Invented Here
  • 3. Многопоточность – это... инструмент, который активно применяется в двух очень разных областях: ● parallel computing (одновременно выполняются одинаковые операции над разными наборами однотипных данных); ● concurrent computing (одновременно выполняются совсем разные операции, возможно, над совершенно разными данными). Concurrent computing может быть и без многопоточности. Но на базе многопоточности concurrent computing доставляет больше всего... 3
  • 4. Далее только о многопоточности... ...применительно к concurrent computing. Именно здесь Модель Акторов оказывается очень удобной. А для parallel computing используются другие подходы и другие инструменты... 4
  • 5. Итак, многопоточность – это сложно Таки да, это сложно. Даже имея 20 лет опыта. Но почему? 5
  • 6. Изменяемое разделяемое состояние Именно изменяемое разделяемое состояние является одним из главных факторов сложности в многопоточном программировании. 6
  • 8. Убрать разделяемое состояние Ничего не разделяем. Ни за что не боремся. Пусть каждый поток владеет своими собственными данными. И никто кроме потока-владельца не имеет к этим данным доступа. Принцип shared nothing* (широко известен в узких кругах). 8* https://en.wikipedia.org/wiki/Shared_nothing_architecture
  • 9. Убрать разделяемое состояние Но что делать, если потоку X потребовалась какая-то информация, которая есть у потока Y? Что делать, если поток Y хочет, чтобы поток Z обновил какие-то данные у себя? 9
  • 10. Потокам нужно общаться, но как? Кажется, что есть два способа: 1. Синхронно. 2. Асинхронно. Но это только кажется... 10
  • 11. На самом-то деле... ...никакой синхронности, только хардкор асинхронное взаимодействие. Например, на основе отсылки и приема сообщений: ● поток X отсылает сообщение-запрос потоку Y; ● поток Y когда-то получит запрос потока X, обработает запрос и отошлет потоку X ответ; ● поток Y отсылает сообщение-обновление потоку Z; ● поток Z когда-то получит сообщение-обновление от потока Y и обновит те данные, которые принадлежат потоку Z. 11
  • 12. Просто же! Есть потоки. У каждого есть очередь входящих сообщений. Поток спит, если очередь входящих сообщений пуста. Поток просыпается, когда для него появляются входящие сообщения. Если потоку X нужно что-то от потока Y, то X отсылает сообщение в очередь входящих сообщений потока Y. Если поток Y хочет ответить потоку X, то Y отсылает сообщение в очередь входящих сообщений потока X. 12
  • 13. А если сообщения несут копию данных... ...то мы получаем очень приятный бонус: прозрачный переход к распределенности. Если поток Y передал в сообщении Msg копию данных, а не ссылку на них, то уже не суть важно, пойдет ли сообщение Msg в локальную очередь входящих сообщений потока Z. Или же в очередь исходящих данных для передачи на другой хост. Сообщение самодостаточно. Поэтому может быть сериализовано, передано по сети, десериализовано и обработано. 13
  • 14. Вот и весь фокус :) Модель акторов именно про это. Про изолированные потоки управления. И про их взаимодействие на основе обмена сообщениями. 14
  • 15. Модель Акторов Появилась в 1973-ем году благодаря работам Карла Хьюитта (Carl Hewitt). Была затем развита в 1981-ом Уильямом Клингером (William Clinger). И в 1985-ом Гулом Агха (Gul Agha). Это если говорить про формализацию Модели Акторов. Неформально она открывалась и переоткрывалась множество раз. 15
  • 16. Модель Акторов Отправные точки для желающих погрузиться в формальную теорию Модели Акторов: https://en.wikipedia.org/wiki/History_of_the_Actor_model https://en.wikipedia.org/wiki/Actor_model https://en.wikipedia.org/wiki/Actor_model_theory 16
  • 17. Модель Акторов. Основные принципы ● актор – это некая сущность, обладающая поведением; ● акторы реагируют на входящие сообщения; ● получив сообщение актор может: ○ отослать некоторое (конечное) количество сообщений другим акторам; ○ создать некоторое (конечное) количество новых акторов; ○ определить для себя новое поведение для обработки последующих сообщений. 17
  • 18. Актор – это некоторая сущность Не более того. Актором может быть отдельный процесс. Например, Erlang. Актором может быть отдельный поток (OS thread, "green" thread, fiber, ...). Например, goroutine в Go может рассматриваться как актор. Актором может быть объект, которому кто-то выделяет рабочий контекст. Например, Akka. 18
  • 19. Еще раз: актор – это некоторая сущность Модель Акторов не требует, чтобы актор был процессом или потоком, или конечным автоматом, или чем-то еще. Поэтому существующие и востребованные на практике реализации Модели Акторов очень сильно отличаются друг от друга. 19
  • 20. Модели Акторов уже более 40 лет За это время Модель Акторов пережила несколько волн популярности и забвения* Сейчас очередная волна популярности. Она началась где-то около 10-12 лет назад. Основным двигателем интереса стали Erlang, а затем Akka. 20* Why has the actor model not succeeded?
  • 21. Современные иконы: Erlang Пожалуй, самая известная реализация – язык Erlang* http://www.erlang.org/ Не только сам язык, но и Erlang VM, и OTP, и вообще все, что понастроили вокруг. 21* Я не встречал, чтобы Джо Армстронг говорил, что на Erlang повлияла Модель Акторов
  • 22. Современные иконы: Erlang Зародился в одной из исследовательских лабораторий Ericsson-а в 1986-ом году благодаря Джо Армстронгу (Joe Armstrong). В 1995-ом году после закрытия неудачного проекта AXE-N (на C++, кстати) был выбран в качестве основного языка для проекта AXD. Результатом стал успешный программно-аппаратный продукт AXD301 в котором было более миллиона строк на Erlang. 22
  • 23. Современные иконы: Erlang В конце 1990-х использование Erlang-а для новых проектов в Ericsson Radio AB было запрещено. Джо Армстронг покинул Ericsson. Erlang ушел в OpenSource. Erlang доказал свою состоятельность вне Ericsson-а. Ericsson одумался. В 2004-ом году Джо Армстронг возвратился в Ericsson. 23
  • 24. Современные иконы: Erlang За последние годы Erlang многократно показывал себя с лучшей стороны в очень серьезных проектах (например, WhatsApp использует Erlang). Многие компании убедившись в достоинствах Erlang-а задействуют Erlang в своих разработках. Из близких нам примеров: Wargaming. 24
  • 25. Современные иконы: Erlang -module(tut15). -export([start/0, ping/2, pong/0]). ping(0, Pong_PID) -> Pong_PID ! finished, io:format("ping finished~n", []); ping(N, Pong_PID) -> Pong_PID ! {ping, self()}, receive pong -> io:format("Ping received pong~n", []) end, ping(N - 1, Pong_PID). 25 pong() -> receive finished -> io:format("Pong finished~n", []); {ping, Ping_PID} -> io:format("Pong received ping~n", []), Ping_PID ! pong, pong() end. start() -> Pong_PID = spawn(tut15, pong, []), spawn(tut15, ping, [3, Pong_PID]).
  • 26. Современные иконы: Akka Фреймворк для Java и Scala. http://akka.io/ История началась в 2006: Филипп Холлер (Philipp Haller) разработал реализацию Модели Акторов для стандартной библиотеки языка Scala. В 2008-ом Джонас Бонер (Jonas Bonér) начал делать Erlang-овский OTP для Scala на базе акторов из Scala-stdlib*. Первая публичная версия Akka вышла в 2010-ом. 26* http://www.lightbend.com/akka-five-year-anniversary
  • 27. Современные иконы: Akka Очень популярна в JVM-мире. Соответственно, находит широкое применение там, где позиции JVM традиционно сильны: Web, онлайн-сервисы и суровый энтерпрайз... Яркие примеры: LinkedIn и Twitter. Стоящие за Akka люди так же причастны к таким современным buzz-word-ам, как Reactive Manifesto* и Microservices** :) 27 * http://www.reactivemanifesto.org/ ** https://en.wikipedia.org/wiki/Microservices
  • 28. Современные иконы: Akka import akka.actor._ case object PingMessage case object PongMessage case object StartMessage case object StopMessage class Ping(pong: ActorRef) extends Actor { var count = 0 def incrementAndPrint { count += 1; println("ping") } def receive = { case StartMessage => incrementAndPrint pong ! PingMessage case PongMessage => incrementAndPrint if (count > 99) { sender ! StopMessage println("ping stopped") context.stop(self) } else { sender ! PingMessage } 28 } } class Pong extends Actor { def receive = { case PingMessage => println(" pong") sender ! PongMessage case StopMessage => println("pong stopped") context.stop(self) } } object PingPongTest extends App { val system = ActorSystem("PingPongSystem") val pong = system.actorOf(Props[Pong], name = "pong") val ping = system.actorOf(Props(new Ping(pong)), name = "ping") // start them going ping ! StartMessage } http://alvinalexander.com/scala/scala-akka-actors-ping-pong-simple-example
  • 29. В чем сила, брат? Что же такое предлагают своим пользователям Erlang и Akka? Почему они востребованы и используются в очень серьезных проектах? 29
  • 30. Вот в чем: 1. Простота. Отсутствие разделяемых данных и взаимодействие посредством асинхронных сообщений спасают от ужасов программирования на мьютексах. 2. Масштабирование. Акторов может быть хоть миллион. Даже самую мелкую задачку можно поручить отдельному актору. Акторов можно распределять по нескольким процессам и нескольким нодам, при асинхронном обмене сообщениями это не суть важно. 3. Отказоустойчивость. Какие-то акторы могут "падать", другие акторы это обнаружат и исправят (см. систему супервизоров Erlang-а*). Shared nothing + message-passing сильно помогают и тут. 30* http://erlang.org/doc/man/supervisor.html
  • 31. Так говорил Джо Армстронг I also suspect that the advent of true parallel CPU cores will make programming parallel systems using conventional mutexes and shared data structures almost impossibly difficult, and that the pure message-passing systems will become the dominant way to program parallel systems. Так же я подозреваю, что пришествие настоящих многоядерных CPU сделает программирование параллельных систем с использованием традиционных мьютексов и разделяемых структур данных сложным до невозможности, и что именно обмен сообщениями станет доминирующим способом разработки параллельных систем. Disclaimer: перевод приблизительный, но основной смысл передан верно. 31A History of Erlang, Joe Armstrong, 2007.
  • 32. Кстати об отказоустойчивости Erlang и Java/Scala (речь об Akka) – это безопасные языки, работающие в управляемых средах (Erlang VM и JVM). На отказоустойчивость это влияет самым непосредственным образом. Деление на ноль в одном из процессов внутри Erlang VM и деление на ноль в одном из потоков большого приложения на C++ – это две большие разницы. 32
  • 33. А что с C++? Есть ли смысл в использовании Модели Акторов в C++? 33
  • 34. Неверный вопрос! Начинать нужно с более важного вопроса: А нужен ли вообще C++? 34
  • 35. Серьезно? И это на CoreHard C++? Таки да :( 35
  • 36. Так нужен ли вообще C++? С++ старый язык (более 30 лет с публичного релиза). За это время стал настоящим монстром, стандарт которого насчитывает ~1500 страниц. И это еще C++17 не приняли... Вобрал в себя множество нового (в переводе на русский: стал еще сложнее). Сохранил при этом совместимость с еще более древним языком С. Так что с отстрелом конечностей все в порядке. Каждый большой проект использует собственное подмножество C++. Огромное количество копролитов мамонта легаси кода. 36
  • 37. Тем не менее... ...какой еще мейнстримовый нативный язык без GC: ● настолько же быстр и эффективен? ● позволяет работать на самом низком уровне? ● позволяет подниматься на высокие уровни абстракции (ООП, обобщенное программирование, метапрограммирование)? ● снабжен таким же количеством разнообразного инструментария? ● так же хорошо и досконально описан в огромном количестве книг, статей, руководств, рекомендаций и пр.? ● обладает таким же большим коммьюнити? Если объективно посмотреть по сторонам, то альтернатив не так уж и много. 37
  • 38. Вывод прост: нужен, однозначно! А раз нужен, то нужны и инструменты, облегчающие жизнь C++ разработчикам. В том числе и реализации Модели Акторов для C++. 38
  • 39. Больше фреймворков, хороших и разных! Более-менее актуальный список инструментов для C++ можно найти здесь: https://en.wikipedia.org/wiki/Actor_model#Actor_libraries_and_frameworks Там не все. А часть того, что есть, уже умерло. Но все-таки. 39
  • 40. Четверо смелых для беглого знакомства Далее быстрый забег "по верхам" для знакомства с четырьмя C++ фреймворками, которые: ● на C++; ● подают признаки жизни (что уже не мало, на самом-то деле); ● кросс-платформенны; ● интересны с той или иной стороны. Есть еще, например, OOSMOS* и Asyncronous Agents Library** от MS, но они не вошли в обзор из-за нарушения каких-то из перечисленных выше пунктов. 40 * http://www.oosmos.com/ ** https://msdn.microsoft.com/en-us/library/dd492627.aspx
  • 41. QP/C++ http://www.state-machine.com/qpcpp/ C++98/03. Предназначен для разработки встраиваемого ПО. В том числе и для работы на голом железе. Двойная лицензия. Более 15 лет развития и эксплуатации. Декларируется приличный уровень соответствия MISRA C++2008. 41
  • 42. QP/C++ Акторы в QP/C++ – это иерархические конечные автоматы. Называются активными объектами. Код активных объектов можно писать обычным образом. Т.е. вручную набирать код C++ классов, методов и вот это вот все. А можно "нарисовать" активный объект в специальном визуальном инструменте для проектирования и C++ код будет сгенерирован. Контекст для работы активных объектов предоставляет QP. В зависимости от окружения активные объекты могут работать на отдельных нитях. А могут и сообща на одной-единственной. 42
  • 43. QP/C++ (пример кода: blinky.h) #ifndef blinky_h #define blinky_h using namespace QP; enum BlinkySignals { DUMMY_SIG = Q_USER_SIG, MAX_PUB_SIG, // the last published signal TIMEOUT_SIG, MAX_SIG // the last signal }; extern QMActive * const AO_Blinky; // opaque pointer #endif // blinky_h 43
  • 44. QP/C++ (пример кода: main.cpp) #include "qpcpp.h" #include "bsp.h" #include "blinky.h" int main() { static QEvt const *blinkyQSto[10]; // Event queue storage for Blinky BSP_init(); // initialize the Board Support Package QF::init(); // initialize the framework and the underlying RT kernel // instantiate and start the active objects... AO_Blinky->start(1U, // priority blinkyQSto, Q_DIM(blinkyQSto), // event queue (void *)0, 0U); // stack (unused) return QF::run(); // run the QF application } 44
  • 45. QP/C++ (пример кода: blinky.cpp, 1) #include "qpcpp.h" #include "bsp.h" #include "blinky.h" class Blinky : public QActive { private: QTimeEvt m_timeEvt; public: Blinky(); protected: static QState initial(Blinky * const me, QEvt const * const e); static QState off(Blinky * const me, QEvt const * const e); static QState on(Blinky * const me, QEvt const * const e); }; Blinky l_blinky; QMActive * const AO_Blinky = &l_blinky; // opaque pointer 45
  • 46. QP/C++ (пример кода: blinky.cpp, 2) Blinky::Blinky() : QActive(Q_STATE_CAST(&Blinky::initial)), m_timeEvt(this, TIMEOUT_SIG, 0U) {} QState Blinky::initial(Blinky * const me, QEvt const * const e) { (void)e; // unused parameter // arm the time event to expire in half a second and every half second me->m_timeEvt.armX(BSP_TICKS_PER_SEC/2U, BSP_TICKS_PER_SEC/2U); return Q_TRAN(&Blinky::off); } 46
  • 47. QP/C++ (пример кода: blinky.cpp, 3) QState Blinky::off(Blinky * const me, QEvt const * const e) { QState status; switch (e->sig) { case Q_ENTRY_SIG: { BSP_ledOff(); status = Q_HANDLED(); break; } case TIMEOUT_SIG: { status = Q_TRAN(&Blinky::on); break; } default: { status = Q_SUPER(&QHsm::top); break; } } return status; } 47 QState Blinky::on(Blinky * const me, QEvt const * const e) { QState status; switch (e->sig) { case Q_ENTRY_SIG: { BSP_ledOn(); status = Q_HANDLED(); break; } case TIMEOUT_SIG: { status = Q_TRAN(&Blinky::off); break; } default: { status = Q_SUPER(&QHsm::top); break; } } return status; }
  • 48. Just::Thread Pro: Actors Edition http://www.stdthread.co.uk/pro/ C++11. Платная библиотека. Автор – Энтони Уильямс (Anthony Williams). Он же написал книгу "C++ Concurrency in Action". На этом, пожалуй, достоинства заканчиваются :) Под каждого актора выделяется отдельный поток ОС. 48
  • 49. Just::Thread Pro: Actors Edition (ping-pong) #include <jss/actor.hpp> #include <iostream> #include <thread> int main() { struct pingpong { jss::actor_ref sender; pingpong(jss::actor_ref sender_): sender(sender_) {} }; jss::actor pp1( []{ for(;;) { jss::actor::receive().match<pingpong>( [](pingpong p){ std::cout<<"pingn"; p.sender.send(pingpong(jss::actor::self())); }); } }); 49 jss::actor pp2( []{ for(;;) { jss::actor::receive().match<pingpong>( [](pingpong p){ std::cout<<"pongn"; p.sender.send(pingpong(jss::actor::self())); }); } }); pp1.send(pingpong(pp2)); std::this_thread::sleep_for(std::chrono::seconds(2)); pp1.stop(); pp2.stop(); }
  • 50. C++ Actor Framework (он же CAF) http://www.actor-framework.org/ C++11 и выше (чем выше, тем лучше). OpenSource под BSD-3-CLAUSE лицензией. Самая распиаренная реализация Модели Акторов для C++. Позиционирует себя как очень быстрый фреймворк. Не то, чтобы так уж заслуженно* ;) Пока еще не стабилизировался. 50* Performance Comparison SO-5.5.15.2 vs CAF-0.14.4
  • 51. C++ Actor Framework (он же CAF) Изначально копировал Erlang в C++ настолько близко, насколько это возможно. Постепенно видоизменяется и приобретает свои уникальные черты. Ценой за мимикрию под Erlang являются высокие требования CAF-а к уровню поддержки стандартов в C++ в компиляторе. Официальная поддержка Windows/VC++ появилась только после выхода Visual Studio 2015 update 3. Есть поддержка распределенности. Собственный протокол с реализацией на базе Boost::Asio. 51
  • 52. C++ Actor Framework (fixed_stack, 1) #include <cassert> #include <cstdint> #include <iostream> #include "caf/all.hpp" using std::endl; using namespace caf; namespace { using pop_atom = atom_constant<atom("pop")>; using push_atom = atom_constant<atom("push")>; enum class fixed_stack_errc : uint8_t { push_to_full = 1, pop_from_empty }; error make_error(fixed_stack_errc x) { return error{static_cast<uint8_t>(x), atom("FixedStack")}; } 52
  • 53. C++ Actor Framework (fixed_stack, 2) class fixed_stack : public event_based_actor { public: fixed_stack(actor_config& cfg, size_t stack_size) : event_based_actor(cfg), size_(stack_size) { full_.assign( [=](push_atom, int) -> error { return fixed_stack_errc::push_to_full; }, [=](pop_atom) -> int { auto result = data_.back(); data_.pop_back(); become(filled_); return result; } ); 53
  • 54. C++ Actor Framework (fixed_stack, 3) filled_.assign( [=](push_atom, int what) { data_.push_back(what); if (data_.size() == size_) become(full_); }, [=](pop_atom) -> int { auto result = data_.back(); data_.pop_back(); if (data_.empty()) become(empty_); return result; } ); 54
  • 55. C++ Actor Framework (fixed_stack, 4) empty_.assign( [=](push_atom, int what) { data_.push_back(what); become(filled_); }, [=](pop_atom) -> error { return fixed_stack_errc::pop_from_empty; } ); } 55
  • 56. C++ Actor Framework (fixed_stack, 5) behavior make_behavior() override { assert(size_ < 2); return empty_; } private: size_t size_; std::vector<int> data_; behavior full_; behavior filled_; behavior empty_; }; 56
  • 57. C++ Actor Framework (fixed_stack, 6) void caf_main(actor_system& system) { scoped_actor self{system}; auto st = self->spawn<fixed_stack>(5u); // fill stack for (int i = 0; i < 10; ++i) self->send(st, push_atom::value, i); // drain stack aout(self) << "stack: { "; bool stack_empty = false; while (!stack_empty) { self->request(st, std::chrono::seconds(10), pop_atom::value).receive( [&](int x) { aout(self) << x << " "; }, [&](const error&) { stack_empty = true; } ); } aout(self) << "}" << endl; self->send_exit(st, exit_reason::user_shutdown); } } // namespace <anonymous> CAF_MAIN() 57
  • 58. SObjectizer-5 https://sourceforge.net/projects/sobjectizer/ или https://github.com/eao197/so-5-5 C++11 (минимальные требования к компилятору: GCC 4.8, MSVC++12.0). OpenSource под BSD-3-CLAUSE лицензией. С очень долгой историей: 1995-2000: Гомель, КБ Системного Программирования, проект SCADA Objectizer; 2002-...: Гомель-Москва, Интервэйл, проект SObjectizer-4; 2010-...: Гомель-Москва, Интервэйл, The SObjectizer Team, проект SObjectizer-5. 58
  • 59. SObjectizer-5 SO-4 в продакшене c 2002-го года. И до сих пор работает. SO-5 в продакшене с 2011-го года. Обратная совместимость – must have. Без фанатизма, но позволить себе вносить ломающие совместимость изменения в каждый релиз мы не можем. От слова совсем. Версия SO-5.5.0 вышла в октябре 2014-го. С тех пор в ветке 5.5.* нет ломающих изменений. Последняя стабильная версия 5.5.18 – сентябрь 2016. 59
  • 60. SObjectizer-5 Акторы в SO-5 называются агентами. Так сложилось. Агенты в SO-5 – это иерархические конечные автоматы (вложенные состояния, обработчики входа-выхода, история, временные лимиты). Рабочий контекст агентам предоставляют диспетчеры. Разработчику "из коробки" доступно восемь типов готовых диспетчеров. Распределенность в SO-5 не поддерживается. Был опыт в SO-4. Поэтому в SO-5 решили обходиться готовыми сторонними инструментами по задачу (MQTT, AMQP, HTTP и т.д.). 60
  • 61. SObjectizer-5 Главное отличие от прочих фреймворков: SO-5 – это симбиоз Модели Акторов, модели Publish/Subscribe. С элементами CSP* Сообщения отсылаются не агенту, а в message box (mbox). За mbox-ом может быть один агент, может быть множество агентов. Или ни одного. Mbox является аналогом Topic-а из Pub/Sub. Отсылка сообщения – аналогом Publish-а из Pub/Sub. И, как и в Pub/Sub, агент должен подписаться на сообщение, чтобы получить его. 61* https://en.wikipedia.org/wiki/Communicating_sequential_processes
  • 62. SObjectizer-5 (blinking_led, 1) #include <iostream> #include <so_5/all.hpp> class blinking_led final : public so_5::agent_t { state_t off{ this }, blinking{ this }, blink_on{ initial_substate_of{ blinking } }, blink_off{ substate_of{ blinking } }; public : struct turn_on_off : public so_5::signal_t {}; 62
  • 63. SObjectizer-5 (blinking_led, 2) blinking_led( context_t ctx ) : so_5::agent_t{ ctx } { this >>= off; off.just_switch_to< turn_on_off >( blinking ); blinking.just_switch_to< turn_on_off >( off ); blink_on .on_enter( []{ std::cout << "ON" << std::endl; } ) .on_exit( []{ std::cout << "off" << std::endl; } ) .time_limit( std::chrono::milliseconds{1250}, blink_off ); blink_off .time_limit( std::chrono::milliseconds{750}, blink_on ); } }; 63
  • 64. SObjectizer-5 (blinking_led, 3) int main() { so_5::launch( []( so_5::environment_t & env ) { so_5::mbox_t m; env.introduce_coop( [&]( so_5::coop_t & coop ) { auto led = coop.make_agent< blinking_led >(); m = led->so_direct_mbox(); } ); auto pause = []( unsigned int v ) { std::this_thread::sleep_for( std::chrono::seconds{v} ); }; so_5::send< blinking_led::turn_on_off >( m ); pause( 10 ); so_5::send< blinking_led::turn_on_off >( m ); pause( 5 ); so_5::send< blinking_led::turn_on_off >( m ); pause( 5 ); env.stop(); } ); } 64
  • 65. Заключение 1/3 Модель Акторов – это очень удобный инструмент в случаях, где использование этой модели уместно1 . Это уже неоднократно доказывалось успешным применением таких инструментов, как Erlang и Akka в самых разнообразных проектах. Да и вообще за асинхронным обменом сообщений между независимыми сущностями будущее. Прислушайтесь к Джо Армстронгу, он плохого не посоветует ;) 1) Не верьте рекламе: уместно не везде. 65
  • 66. Заключение 2/3 Наш опыт показывает, что при наличии подходящих инструментов Модель Акторов имеет смысл применять и в C++. При этом для C++ подходящие готовые инструменты уже есть. На разный вкус и цвет. И размер кошелька, конечно же. В коммерческом проекте за QP/C++ и за Just::Thread Pro придется заплатить. За SObjectizer и CAF – нет. По крайней мере сразу не придется. 66
  • 67. Заключение 3/3 Вот чего делать не стоит, так это браться за написание собственного акторного фреймворка. Неблагодарное это дело. Проверено. На людях. Лучше все-таки взять что-то готовое. Hint: купляйце беларускае. И пусть кто-нибудь другой весело бегает по граблям многопоточности :) 67
  • 69. Bonus track (SO-5's fixed_stack, 1) #include <iostream> #include <so_5/all.hpp> class fixed_stack final : public so_5::agent_t { state_t st_empty{ this }, st_filled{ this }, st_full{ this }; const size_t m_max_size; std::vector< int > m_stack; public : class empty_stack final : public std::logic_error { public : using std::logic_error::logic_error; }; struct push { int m_val; }; struct pop : public so_5::signal_t {}; 69* https://bitbucket.org/sobjectizerteam/fixed_stack_example
  • 70. Bonus track (SO-5's fixed_stack, 2) fixed_stack( context_t ctx, size_t max_size ) : so_5::agent_t( ctx ) , m_max_size( max_size ) { this >>= st_empty; so_subscribe_self() .in( st_empty ) .in( st_filled ) .event( &fixed_stack::on_push ); so_subscribe_self() .in( st_filled ) .in( st_full ) .event( &fixed_stack::on_pop_when_not_empty ); so_subscribe_self() .in( st_empty ) .event( &fixed_stack::on_pop_when_empty ); } 70
  • 71. Bonus track (SO-5's fixed_stack, 3) private : void on_push( const push & w ) { m_stack.push_back( w.m_val ); this >>= ( m_stack.size() == m_max_size ? st_full : st_filled ); } int on_pop_when_not_empty( mhood_t< pop > ) { auto r = m_stack.back(); m_stack.pop_back(); this >>= ( m_stack.empty() ? st_empty : st_filled ); return r; } int on_pop_when_empty( mhood_t< pop > ) { throw empty_stack( "empty_stack" ); } }; 71
  • 72. Bonus track (SO-5's fixed_stack, 4) int main() { try { so_5::launch( []( so_5::environment_t & env ) { so_5::mbox_t stack; env.introduce_coop( [&stack]( so_5::coop_t & coop ) { stack = coop.make_agent< fixed_stack >( 5u )->so_direct_mbox(); } ); for( int i = 0; i < 10; ++i ) so_5::send< fixed_stack::push >( stack, i ); std::cout << "stack { "; try { for(;;) std::cout << so_5::request_value< int, fixed_stack::pop >( stack, std::chrono::seconds(10) ) << " "; } catch( const fixed_stack::empty_stack & ) {} std::cout << "}" << std::endl; env.stop(); } ); return 0; } catch( const std::exception & x ) { std::cerr << "Oops! " << x.what() << std::endl; } return 2; } 72
  • 73. Документация по SObjectizer: https://sourceforge.net/p/sobjectizer/wiki/Home/ Серия статей о SObjectizer на русском: SObjectizer: что это, для чего это и почему это выглядит именно так? От простого к сложному: Часть I, Часть II, Часть III. Акторы в виде конечных автоматов – это плохо или хорошо? Проблема перегрузки агентов и средства борьбы с ней. Нежная дружба агентов и исключений. Серия презентаций о SObjectizer на английском "Dive into SObjectizer-5.5": Intro, Agent's States, More About Coops, Exceptions, Timers, Synchonous Interaction, Message Limits, Dispatchers, Message Chains. Блог автора доклада: eao197.blogspot.com О SObjectizer в блоге: eao197.blogspot.com/search/label/SObjectizer Почта автора доклада: eao197 на gmail тчк com 73