SlideShare a Scribd company logo
1 of 29
Download to read offline
Qt × Reactive Extensions
2019-02-20 C++ MIX #2
Tetsuro Matsumura
目次
1. Reactive Extensionsの紹介
2. Observableを作る
3. Qtの紹介
4. SignalからObservableへ
5. RxQtの内側
1
Reactive Extensionsの紹介
2
Reactive Extensions(Rx)とは
3
The Reactive Extensions for C++ (RxCpp) is
a library of algorithms for values-distributed-in-time.
The Range-v3 library does the same for values-distributed-in-space.
ReactiveX/RxCpp
ReactiveX is a combination of the best ideas from the Observer pattern, the
Iterator pattern, and functional programming
ReactiveX
values-distributed-in-space vs time
4
values-distributed-in-space
(メモリー)空間上に広がった値。
string, array, vector, list, mapなど。
values-distributed-in-time
時間軸上に広がった値。
イベントなど。
'C' '+' '+' 0
a[0] a[1] a[2] a[3]
C + +
Range is composable
5
vector v = {1,2,3};
auto twice = [](auto x){ return x => x*2; };
v | reverse; // 3,2,1
v | transform(twice); // 2,4,6
v | transform(twice) | reverse; // 6,4,2
C++では、空間上に広がった値をRangeとして扱うことができる。
Rangeはアダプターによってさまざまに組み合わせられる。
Reactive Extensions(Rx)は、これの時間軸バージョン。
時間軸に広がった値をコンポーザブルに扱うライブラリ。
Observable
6
// マウスイベントの定義
struct MouseEvent { Point pos; Button button; …… };
observable<MouseEvent> clicked;
// clickedイベントを処理する
clicked | subscrive([](MouseEvent e){ cout << e.pos << '¥n'; });
Rxでは、時間軸に広がった値をObservableという型で扱う。
Observableに配送されてきた値をSubscribeで受け取る。
* 紙面の都合で引数がconst参照でないことがあります
* |>演算子が欲しい
Observable is composable
7
// マウスイベントの定義
struct MouseEvent { Point pos; Button button; …… };
observable<MouseEvent> clicked;
// 先にposを取り出す
clicked
| map([](MouseEvent e){ return e.pos; })
| subscrive([](Point p){ cout << p << '¥n'; });
// クリックした1秒後に表示する
clicked
| map([](MouseEvent e){ return e.pos; })
| delay(millisecond(1000))
| subscrive([](Point p){ cout << p << '¥n'; });
ObservableはRxのオペレーターで様々に組み合わせられる。
Run Loop
8
C++では妥当なメインループというものが考えにくいので、
RxCppの利用者が各自でメインループを回す必要がある。
// run_loopオブジェクトを1つ作っておく
rxcpp::schedulers::run_loop run_loop;
// 一定間隔で実行して溜まったイベントを処理する
// どうやって一定間隔で実行するかは様々
while(!run_loop.empty() && run_loop.peek().when < run_loop.now()) {
run_loop.dispatch();
}
Rxを使うと何が嬉しいのか
9
 イベントをコンポーザブルに扱うことができる。
 特に、遅延、バッファリングなど、時間に関するオペレーターが豊富。
 エラー処理や完了処理の方法が統一されている。
 他の言語でもほぼ同じように使える。
 Rxが移植されている言語:
C#, C++, Clojure, Dart, Elixir, Go, Groovy, Java, JavaScript, Kotlin, Lua,
PHP, Python, Ruby, Scala, Swift
ReactiveX http://reactivex.io/
10
言語横断的なRxのドキュメント。
オペレーターの一覧やそれぞれの図解がわかりやすい。
Marble diagram
11
Observableを作る
12
Observableを作る
13
auto print = [](const auto& x){ cout << x << endl; };
// 1から10をすぐに表示
observable<>::range(1, 11) | subscribe<int>(print);
observable<>::range(1) | take(10) | subscribe<int>(print);
Rxに用意されているファクトリー関数を使ってObservableを作る。
1 2 3
// 1から10をゆっくり表示
const auto period = chrono::milliseconds(500);
observable<>::interval(period) | take(10) | subscribe<int>(print);
1
2
3
Observableを作る 2
14
auto print = [](const auto& x){ cout << x << endl; };
// subscribeされたときのコールバックで手続き的に生成
auto on_subscribe = [](subscriber<char> s) {
s.on_next('C'); s.on_next('+'); s.on_next('+’); s.on_complete();
};
observable<>::create<char>(on_subscribe) | subscribe<char>(print);
// 何かのコールバック関数内でon_nextを呼べば、
// どんなイベントでもobservableにできる
observable<>::create<T>([](subscriber<T> s){
on_something([](T t){ s.on_next(t); });
});
外部のイベントもObservableに
Qtの紹介
15
Qtとは
16
クロスプラットフォームなGUIライブラリ。
最近ではStackOverflowでも「C++でGUIライブラリと言えば?」と質問が上がると
9割は「Qt」という答えが返ってくる。
C++日本語リファレンス
 イベント処理のシグナル/スロット機構が有名。
 付属コードジェネレーターの利用がほぼ前提となっている。
 シグナルを作るには必須。
 他にも色々C++を拡張している(プロパティ、リフレクションなど)。
シグナル/スロット
17
QPushButton* exitButton;
QApplication* app;
// ボタンをクリックしたら終了
connect(exitButton, &QPushButton::clicked, app, &QApplication::quit);
シグナル関数を呼ぶと、接続しているスロット関数が一斉に呼ばれる。
QLineEdit* editor;
QLabel* label1, label2;
// 編集したらラベルに反映
connect(editor, &QLineEdit::textChanged, label1, &QLabel::setText);
connect(editor, &QLineEdit::textChanged, label2, &QLabel::setText);
引数も転送される。
シグナル/スロットの問題
18
 Composabilityが低い
 シグナルは必ずメンバー関数で、実装はコード生成される。
 新しいシグナルを追加するにはクラス定義の変更または派生が必要。
 一応、スロットの代わりに関数オブジェクトに接続できるが……
 時間が絡むとコールバック地獄になりやすい。
 GUIでは時間が絡む処理がよくある(連打防止など)
SignalからObservableへ
19
SignalからObservableへ
20
シグナル関数からObservableを構築すればcomposabilityの大幅な向上が期待できる
QLineEdit* lineedit;
auto on_subscribe = [lineedit](subscriber<QString> s){
// textChangedがemitされたときにラムダ式を実行
QObject::connect(
lineedit,
&QLineEdit::textChanged,
// emitされた値をsubscriberに渡す
[s](const QString& v){ s.on_next(v); }
);
};
auto textChanged = observable<>::create<QString>(on_subscribe);
RxQt
21
Signal/Observable変換を毎回書くと大変なので、ライブラリ化した。
https://github.com/tetsurom/rxqt
QLineEdit* lineedit; QLable* label;
// 普通のconnect
connect(editor, &QLineEdit::textChanged, label, &QLabel::setText);
// connectと同じ動作
rxqt::from_signal(lineedit, &QLineEdit::textChanged)
| subscribe([](const QString& s){ label->setText(s); });
// 500ms以上変更が無かったらラベルに反映
rxqt::from_signal(lineedit, &QLineEdit::textChanged)
| debounce(milliseconds(500))
| subscribe([](const QString& s){ label->setText(s); });
RxQt
22
// connectと同じ動作
rxqt::from_signal(lineedit, &QLineEdit::textChanged)
| subscribe([](const QString& s){ label->setText(s); });
// 500ms以上変更が無かったらラベルに反映
rxqt::from_signal(lineedit, &QLineEdit::textChanged)
| debounce(milliseconds(500))
| subscribe([](const QString& s){ label->setText(s); });
RxQtの機能
23
 QtシグナルからObservableを構築
 QtイベントからObservableを構築
 QTimerベースのrun_loopの提供
シンプルなヘッダーオンリーライブラリとして提供中。
https://github.com/tetsurom/rxqt
RxQtの内側
24
ObservableとSignalの差の吸収
25
Signalは0個以上のパラメーターを持てる一方、Observableのパラメーターは必ず1個。
 0個のときはon_nextされた回数をパラメーターにする
 1個のときはそのまま
 2個以上のときはtupleに入れる
Signal Observable
signal(void) observable<long>
signal(T) observable<T>
signal(Ts...) observable<tuple<Ts...>>
この分岐は部分的特殊化で行う。
型引数の省略
26
QtのConnectでは、Signalのパラメーターの型は書かなくてよい。
template <class P, class Q, class R, class ...Args>
auto from_signal(const P* qobject, R(Q::*signal)(Args...))
{ …… }
この関数テンプレートでシグナルの引数リストの型を得ることができる。
connect(editor, &QLineEdit::textChanged, label, &QLabel::setText);
Observableを構築するときも書かなくていいようにしたい。
Observable構築(汎用版)
27
using value_type = tuple<remove_cv_t<remove_reference_t<Args>>...>;
template <class S>
static observable<value_type>
create(const Q* qobject, S signal) {
if(!qobject) return never<value_type>();
return observable<>::create<value_type>(
[qobject, signal](const subscriber<value_type>& s){
QObject::connect(qobject, signal, [s](const Args&... values){
s.on_next(make_tuple(values...));
});
QObject::connect(qobject, &QObject::destroyed, [s](){
s.on_completed();
});
}
);
}
QObjectは破棄するとdestroyedシグナルをemitするので、observableを完了できる。
28
まとめ
 Rxを使うとイベントなどをコンポーサブルに取り扱うことができる
 Rx以外の既存イベントソースからObservableを構築できる
 QtのシグナルをObservableに変換するライブラリ RxQt 公開中

More Related Content

What's hot

ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14Ryo Suzuki
 
できる!並列・並行プログラミング
できる!並列・並行プログラミングできる!並列・並行プログラミング
できる!並列・並行プログラミングPreferred Networks
 
MagicOnion~C#でゲームサーバを開発しよう~
MagicOnion~C#でゲームサーバを開発しよう~MagicOnion~C#でゲームサーバを開発しよう~
MagicOnion~C#でゲームサーバを開発しよう~torisoup
 
メタプログラミングって何だろう
メタプログラミングって何だろうメタプログラミングって何だろう
メタプログラミングって何だろうKota Mizushima
 
SAMURAI JACK開発事例:海外むけアクションゲームをオーソドックスに作ってみた UNREAL FEST EXTREME 2021 SUMMER
SAMURAI JACK開発事例:海外むけアクションゲームをオーソドックスに作ってみた UNREAL FEST EXTREME 2021 SUMMERSAMURAI JACK開発事例:海外むけアクションゲームをオーソドックスに作ってみた UNREAL FEST EXTREME 2021 SUMMER
SAMURAI JACK開発事例:海外むけアクションゲームをオーソドックスに作ってみた UNREAL FEST EXTREME 2021 SUMMERエピック・ゲームズ・ジャパン Epic Games Japan
 
MagicOnion入門
MagicOnion入門MagicOnion入門
MagicOnion入門torisoup
 
そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 1 <Shader Compile, PSO Cache編>
  そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 1 <Shader Compile, PSO Cache編>  そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 1 <Shader Compile, PSO Cache編>
そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 1 <Shader Compile, PSO Cache編>エピック・ゲームズ・ジャパン Epic Games Japan
 
なぜなにリアルタイムレンダリング
なぜなにリアルタイムレンダリングなぜなにリアルタイムレンダリング
なぜなにリアルタイムレンダリングSatoshi Kodaira
 
リアルタイムサーバー 〜Erlang/OTPで作るPubSubサーバー〜
リアルタイムサーバー 〜Erlang/OTPで作るPubSubサーバー〜 リアルタイムサーバー 〜Erlang/OTPで作るPubSubサーバー〜
リアルタイムサーバー 〜Erlang/OTPで作るPubSubサーバー〜 Yugo Shimizu
 
Game Creators Conference 2019 Keiji Kikuchi
Game Creators Conference 2019 Keiji KikuchiGame Creators Conference 2019 Keiji Kikuchi
Game Creators Conference 2019 Keiji KikuchiKeiji Kikuchi
 

What's hot (20)

ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14
 
できる!並列・並行プログラミング
できる!並列・並行プログラミングできる!並列・並行プログラミング
できる!並列・並行プログラミング
 
[CEDEC2018] UE4で多数のキャラクターを生かすためのテクニック
[CEDEC2018] UE4で多数のキャラクターを生かすためのテクニック[CEDEC2018] UE4で多数のキャラクターを生かすためのテクニック
[CEDEC2018] UE4で多数のキャラクターを生かすためのテクニック
 
MagicOnion~C#でゲームサーバを開発しよう~
MagicOnion~C#でゲームサーバを開発しよう~MagicOnion~C#でゲームサーバを開発しよう~
MagicOnion~C#でゲームサーバを開発しよう~
 
バイキング流UE4活用術 ~BPとお別れするまでの18ヶ月~
バイキング流UE4活用術 ~BPとお別れするまでの18ヶ月~バイキング流UE4活用術 ~BPとお別れするまでの18ヶ月~
バイキング流UE4活用術 ~BPとお別れするまでの18ヶ月~
 
60fpsアクションを実現する秘訣を伝授 解析編
60fpsアクションを実現する秘訣を伝授 解析編60fpsアクションを実現する秘訣を伝授 解析編
60fpsアクションを実現する秘訣を伝授 解析編
 
Robo Recallで使われている 最新のVR開発テクニックをご紹介!
Robo Recallで使われている最新のVR開発テクニックをご紹介!Robo Recallで使われている最新のVR開発テクニックをご紹介!
Robo Recallで使われている 最新のVR開発テクニックをご紹介!
 
UE4 MultiPlayer Online Deep Dive 基礎編2 -Traveling- (historia様ご講演) #ue4dd
UE4 MultiPlayer Online Deep Dive 基礎編2 -Traveling-  (historia様ご講演)  #ue4ddUE4 MultiPlayer Online Deep Dive 基礎編2 -Traveling-  (historia様ご講演)  #ue4dd
UE4 MultiPlayer Online Deep Dive 基礎編2 -Traveling- (historia様ご講演) #ue4dd
 
メタプログラミングって何だろう
メタプログラミングって何だろうメタプログラミングって何だろう
メタプログラミングって何だろう
 
Unreal Engine 5 早期アクセスの注目機能総おさらい Part 2
Unreal Engine 5 早期アクセスの注目機能総おさらい Part 2Unreal Engine 5 早期アクセスの注目機能総おさらい Part 2
Unreal Engine 5 早期アクセスの注目機能総おさらい Part 2
 
SAMURAI JACK開発事例:海外むけアクションゲームをオーソドックスに作ってみた UNREAL FEST EXTREME 2021 SUMMER
SAMURAI JACK開発事例:海外むけアクションゲームをオーソドックスに作ってみた UNREAL FEST EXTREME 2021 SUMMERSAMURAI JACK開発事例:海外むけアクションゲームをオーソドックスに作ってみた UNREAL FEST EXTREME 2021 SUMMER
SAMURAI JACK開発事例:海外むけアクションゲームをオーソドックスに作ってみた UNREAL FEST EXTREME 2021 SUMMER
 
Riderはいいぞ!
Riderはいいぞ!Riderはいいぞ!
Riderはいいぞ!
 
MagicOnion入門
MagicOnion入門MagicOnion入門
MagicOnion入門
 
そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 1 <Shader Compile, PSO Cache編>
  そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 1 <Shader Compile, PSO Cache編>  そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 1 <Shader Compile, PSO Cache編>
そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 1 <Shader Compile, PSO Cache編>
 
なぜなにリアルタイムレンダリング
なぜなにリアルタイムレンダリングなぜなにリアルタイムレンダリング
なぜなにリアルタイムレンダリング
 
リアルタイムサーバー 〜Erlang/OTPで作るPubSubサーバー〜
リアルタイムサーバー 〜Erlang/OTPで作るPubSubサーバー〜 リアルタイムサーバー 〜Erlang/OTPで作るPubSubサーバー〜
リアルタイムサーバー 〜Erlang/OTPで作るPubSubサーバー〜
 
脱Unity!? UE4でVR開発のここが変わった
脱Unity!? UE4でVR開発のここが変わった脱Unity!? UE4でVR開発のここが変わった
脱Unity!? UE4でVR開発のここが変わった
 
UE4とUnrealC++について
UE4とUnrealC++についてUE4とUnrealC++について
UE4とUnrealC++について
 
実行速度の最適化のあれこれ プラス おまけ
実行速度の最適化のあれこれ プラス おまけ  実行速度の最適化のあれこれ プラス おまけ
実行速度の最適化のあれこれ プラス おまけ
 
Game Creators Conference 2019 Keiji Kikuchi
Game Creators Conference 2019 Keiji KikuchiGame Creators Conference 2019 Keiji Kikuchi
Game Creators Conference 2019 Keiji Kikuchi
 

Similar to Qt × Reactive Extensions

ぱっと見でわかるC++11
ぱっと見でわかるC++11ぱっと見でわかるC++11
ぱっと見でわかるC++11えぴ 福田
 
Rx swift,Repro framewolrk
Rx swift,Repro framewolrkRx swift,Repro framewolrk
Rx swift,Repro framewolrkDaisuke Nagata
 
linq.js - Linq to Objects for JavaScript
linq.js - Linq to Objects for JavaScriptlinq.js - Linq to Objects for JavaScript
linq.js - Linq to Objects for JavaScriptYoshifumi Kawai
 
C#次世代非同期処理概観 - Task vs Reactive Extensions
C#次世代非同期処理概観 - Task vs Reactive ExtensionsC#次世代非同期処理概観 - Task vs Reactive Extensions
C#次世代非同期処理概観 - Task vs Reactive ExtensionsYoshifumi Kawai
 
Swift 2.0 大域関数の行方から #swift2symposium
Swift 2.0 大域関数の行方から #swift2symposiumSwift 2.0 大域関数の行方から #swift2symposium
Swift 2.0 大域関数の行方から #swift2symposiumTomohiro Kumagai
 
PFDS 8.4.3 Real-Time Deques
PFDS 8.4.3 Real-Time DequesPFDS 8.4.3 Real-Time Deques
PFDS 8.4.3 Real-Time Deques昌平 村山
 
YugabyteDBの実行計画を眺める(NewSQL/分散SQLデータベースよろず勉強会 #3 発表資料)
YugabyteDBの実行計画を眺める(NewSQL/分散SQLデータベースよろず勉強会 #3 発表資料)YugabyteDBの実行計画を眺める(NewSQL/分散SQLデータベースよろず勉強会 #3 発表資料)
YugabyteDBの実行計画を眺める(NewSQL/分散SQLデータベースよろず勉強会 #3 発表資料)NTT DATA Technology & Innovation
 
関東第2回r勉強会
関東第2回r勉強会関東第2回r勉強会
関東第2回r勉強会Paweł Rusin
 
Linux 対応だけじゃない!! sql server 2017 こんな機能が追加されています。
Linux 対応だけじゃない!! sql server 2017 こんな機能が追加されています。Linux 対応だけじゃない!! sql server 2017 こんな機能が追加されています。
Linux 対応だけじゃない!! sql server 2017 こんな機能が追加されています。Masayuki Ozawa
 
Sansan様 登壇資料
Sansan様 登壇資料Sansan様 登壇資料
Sansan様 登壇資料Daisuke Nagata
 
Reactive Extensionsで非同期処理を簡単に
Reactive Extensionsで非同期処理を簡単にReactive Extensionsで非同期処理を簡単に
Reactive Extensionsで非同期処理を簡単にYoshifumi Kawai
 
サービス開発における フロントエンド・ドメイン駆動設計の実践
サービス開発における フロントエンド・ドメイン駆動設計の実践サービス開発における フロントエンド・ドメイン駆動設計の実践
サービス開発における フロントエンド・ドメイン駆動設計の実践TakefumiYoshii
 

Similar to Qt × Reactive Extensions (20)

MlnagoyaRx
MlnagoyaRxMlnagoyaRx
MlnagoyaRx
 
ぱっと見でわかるC++11
ぱっと見でわかるC++11ぱっと見でわかるC++11
ぱっと見でわかるC++11
 
Rx swift,Repro framewolrk
Rx swift,Repro framewolrkRx swift,Repro framewolrk
Rx swift,Repro framewolrk
 
linq.js - Linq to Objects for JavaScript
linq.js - Linq to Objects for JavaScriptlinq.js - Linq to Objects for JavaScript
linq.js - Linq to Objects for JavaScript
 
Boost Tour 1.50.0 All
Boost Tour 1.50.0 AllBoost Tour 1.50.0 All
Boost Tour 1.50.0 All
 
C#次世代非同期処理概観 - Task vs Reactive Extensions
C#次世代非同期処理概観 - Task vs Reactive ExtensionsC#次世代非同期処理概観 - Task vs Reactive Extensions
C#次世代非同期処理概観 - Task vs Reactive Extensions
 
Swift 2.0 大域関数の行方から #swift2symposium
Swift 2.0 大域関数の行方から #swift2symposiumSwift 2.0 大域関数の行方から #swift2symposium
Swift 2.0 大域関数の行方から #swift2symposium
 
PFDS 8.4.3 Real-Time Deques
PFDS 8.4.3 Real-Time DequesPFDS 8.4.3 Real-Time Deques
PFDS 8.4.3 Real-Time Deques
 
ReactiveSignalR
ReactiveSignalRReactiveSignalR
ReactiveSignalR
 
YugabyteDBの実行計画を眺める(NewSQL/分散SQLデータベースよろず勉強会 #3 発表資料)
YugabyteDBの実行計画を眺める(NewSQL/分散SQLデータベースよろず勉強会 #3 発表資料)YugabyteDBの実行計画を眺める(NewSQL/分散SQLデータベースよろず勉強会 #3 発表資料)
YugabyteDBの実行計画を眺める(NewSQL/分散SQLデータベースよろず勉強会 #3 発表資料)
 
Prosym2012
Prosym2012Prosym2012
Prosym2012
 
関東第2回r勉強会
関東第2回r勉強会関東第2回r勉強会
関東第2回r勉強会
 
Linux 対応だけじゃない!! sql server 2017 こんな機能が追加されています。
Linux 対応だけじゃない!! sql server 2017 こんな機能が追加されています。Linux 対応だけじゃない!! sql server 2017 こんな機能が追加されています。
Linux 対応だけじゃない!! sql server 2017 こんな機能が追加されています。
 
Sansan様 登壇資料
Sansan様 登壇資料Sansan様 登壇資料
Sansan様 登壇資料
 
R intro
R introR intro
R intro
 
Reactive Extensionsで非同期処理を簡単に
Reactive Extensionsで非同期処理を簡単にReactive Extensionsで非同期処理を簡単に
Reactive Extensionsで非同期処理を簡単に
 
Vector
VectorVector
Vector
 
Boost tour 1_40_0
Boost tour 1_40_0Boost tour 1_40_0
Boost tour 1_40_0
 
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
 
サービス開発における フロントエンド・ドメイン駆動設計の実践
サービス開発における フロントエンド・ドメイン駆動設計の実践サービス開発における フロントエンド・ドメイン駆動設計の実践
サービス開発における フロントエンド・ドメイン駆動設計の実践
 

Qt × Reactive Extensions