SlideShare a Scribd company logo
1 of 94
Download to read offline
2013/07/13
規格書で読むC++11のスレッド
@hotwatermorning
1
発表者自己紹介
✤ @hotwatermorning
✤ DTMer
✤ C++ポケットリファレンス書きました!(共著)
✤ Amazonのなか見検索に対応!
2
http://www.amazon.co.jp/C-%E3%83%9D
%E3%82%B1%E3%83%83%E3%83%88%E3%83%AA
%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9-
%E9%AB%98%E6%A9%8B-%E6%99%B6/dp/4774157155
本日のセッションを始める前に
✤ 今日のセッションはC++の規格と絡むので、手元
に規格書があると便利です。
✤ 本日は規格書の代わりに、N3337を使用しま
す。
✤ ※PDF,割とサイズが大きいので注意
3
C++のスレッド
4
Free Lunch Is Over
5
✤ タダ飯の時代は終わった
✤ 2005年
マイクロソフトの Software Architect である
Herb Sutterの言葉
✤ CPUコアのクロック数向上が頭打ちとなり、時
を待てば自ずとソフトウェアの性能が上がるとい
う時代の終わり
✤ →並行プログラミングが重要に
C++のスレッド
✤ 2011年に策定された新規格(通称:C++11)
から、C++にマルチスレッドサポートが
導入された。
✤ これによって、ポータブルなコードで
マルチスレッドアプリケーションをかけるように
なった。
6
#include	 <iostream>
#include	 <thread>
#include	 <vector>
#include	 <functional>
int	 main()	 {
	 	 	 	 std::vector<int>	 data	 =	 GetSomeData();
	 	 	 	 int	 sum;
	 	 	 	 std::thread	 th(
	 	 	 	 	 	 	 	 [](std::vector<int>	 const	 &data_,	 int	 &sum_)	 {
	 	 	 	 	 	 	 	 	 	 	 	 sum_	 =	 0;
	 	 	 	 	 	 	 	 	 	 	 	 for(auto	 n	 :	 data_)	 {	 sum_	 +=	 n;	 }
	 	 	 	 	 	 	 	 },
	 	 	 	 	 	 	 	 std::cref(data),	 std::ref(sum)	 );
	 	 	 	 th.join();
	 	 	 	 std::cout	 <<	 "sum	 of	 data	 is	 :	 "	 <<	 sum	 <<	 std::endl;
}
C++のスレッド
7
C++03との違い
8
C++03までのスレッド
9
✤ 規格で、マルチスレッドをサポートしたメモリモ
デルや実行スレッドが定義されていなかった。
✤ そのため、これまでC++でマルチスレッド処理を
するためには、各プロセッサーのメモリモデルや
各処理系のスレッドの定義に依存したコードを書
く必要があった。
C++11からのスレッド
10
✤ 規格で、マルチスレッドをサポートしたメモリモ
デルや実行スレッドが定義された。
✤ マルチスレッドための言語機能やライブラリも導
入された。
✤ 標準機能のポータブルなコードでマルチスレッド
が実現できるようになった。
✤ スレッドライブラリも、最新のC++の知見をふん
だんに使用しているので、洗練されている。
ライブラリ
11
✤ thread
✤ mutex/lock
✤ future/promise
✤ async/packaged_task
✤ condition_variable
✤ call_once
✤ atomic
言語機能
12
✤ static変数の初期化
✤ thread_local変数のサポート
✤ スレッドを超えた例外の伝播(std::exception_ptr)
✤ などなど
本日やる内容
13
本日やる内容
14
✤ thread
✤ mutex/lock
✤ future/promise
✤ condition_variable
本日やる内容
15
✤ thread
✤ mutex/lock
✤ future/promise
✤ condition_variable
thread
✤ スレッドを扱うクラス ( 30.3.1)
✤ threadクラスは新たな実行スレッドを作成したり、その
スレッドの終了を待機したり、その他スレッドの状態を問
い合せる操作のメカニズムを提供します。
✤ スレッドの作成やスレッドハンドルの管理を行う
✤ そのためプログラマが常に明示的にスレッドの作成や
ハンドルの管理を意識する必要がない
✤ Not Copyable / Movable
16
スレッドの作成
✤ threadクラスのコンストラクタで、第一引数に関
数や関数オブジェクトを渡し、第二引数以降にそ
の関数に適用させたい引数を渡す( 30.3.1.2/3)
( 20.8.2/1)
17
#include	 <iostream>
#include	 <thread>
void	 foo(){
	 	 	 	 std::cout	 <<	 "Hello"	 <<	 std::endl;
}
int	 main()	 {
	 	 	 	 //	 別スレッドでfoo関数を起動
	 	 	 	 std::thread	 th(foo);
	 	 	 	 //	 スレッドの終了を待機
	 	 	 	 th.join();
}
スレッドの作成
18
template	 <class	 F,	 class	 ...Args>
explicit	 thread(F&&	 f,	 Args&&...	 args);
//	 というコンストラクタについて、
INVOKE	 (
	  DECAY_COPY(
	 	 	 	 	  std::forward<F>(f)
	 	 	 	 ),
	 	 	 	 DECAY_COPY(
	 	 	 	 	  std::forward<Args>(args)
	 	 	 	 )...
)
//	 が有効であるような関数や引数を渡せる
コンストラクタの定義
19
DECAY_COPY()
✤ 引数に渡されたオブジェクトをコピーして受け渡
す操作を表す。( 30.2.6)
✤ ただし、rvalueなオブジェクトはそのままムーブ
されたり、配列は先頭要素へのポインタにするな
どの変換が行われる。
✤ 詳しくは
http://d.hatena.ne.jp/yohhoy/20120306/p1
20
INVOKE()
✤ 関数やメンバ関数へのポインタや関数オブジェク
ト(Functor)やラムダ式など、なんらか呼び出し
可能なものを第1引数に取り、続く引数を適用し
て呼び出す操作を表す。( 20.8.2)
✤ https://sites.google.com/site/cpprefjp/reference/functional/invoke
✤ http://twitter.com/Cryolite/status/216814363221303296
21
//	 INVOKEが表す仮想的な呼び出し操作は
INVOKE(f,	 t1,	 t2,	 ...,	 tN);
//	 実際には以下から適切なものが呼び出される
(t1.*f)(t2,	 ...,	 tN);
((*t1).*f)(t2,	 ...,	 tN);
f(t1,	 t2,	 ...,	 tN);
INVOKE()
22
struct	 Foo	 {


 //	 operator()をもつクラス
	 	 	 	 //	 →	 関数オブジェクト(別名:ファンクタ)
	 	 	 	 void	 operator()	 (std::string	 msg)	 const	 {
	 	 	 	 	 	 	 	 std::cout	 <<	 "Hello	 "	 <<	 msg	 <<	 std::endl;
	 	 	 	 }
};
Foo	 foo;
std::string	 msg	 =	 "World!";
foo("World");	 //	 Hello	 World!
//関数のように呼び出せる
INVOKE()
23
int	 main()	 {
	 	 	 	 std::string	 msg	 =	 "World!";
	 	 	 	 Foo	 foo;
	 	 	 	 //	 関数のように呼び出せるものは
	 	 	 	 //	 スレッドに渡せる
	 	 	 	 std::thread	 th(foo,	 msg);	 //	 Hello	 World!
	 	 	 	 //スレッドの終了を待機
	 	 	 	 th.join();
}
INVOKE()
24
スレッドに参照を渡す
✤ スレッドの引数にオブジェクトの参照を渡そうと
すると、DECAY_COPY()によって、コンパイル
エラーとなる。
✤ 参照型はコピーもムーブもできないため
✤ そのため、DECAY_COPY()に渡す前に参照を
std::ref()やstd::cref()で包んで渡すようにする。
✤ http://d.hatena.ne.jp/yohhoy/20120306/p1
25
#include	 <thread>
#include	 <iostream>
#include	 <functional>
void	 add(int	 a,	 int	 b,	 int	 &c)	 {
	 	 	 	 c	 =	 a	 +	 b;
}
int	 main()	 {
	 	 	 	 int	 result;
	 	 	 	 std::thread	 th1(add,	 1,	 2,	 std::ref(result));
	 	 	 	 th1.join();
	 	 	 	 std::cout	 <<	 result	 <<	 std::endl;
}
スレッドに参照を渡す
26
thread
✤ スレッドを扱うクラス ( 30.3.1)
✤ threadクラスは新たな実行スレッドを作成したり、その
スレッドの終了を待機したり、その他スレッドの状態を問
い合せる操作のメカニズムを提供します。
✤ スレッドの作成やスレッドハンドルの管理を行う
✤ そのためプログラマが常に明示的にスレッドの作成や
ハンドルの管理を意識する必要がない
✤ Not Copyable / Movable
27
Copyable Type
✤ CopyConstructible要件 と
CopyAssignable要件 を満たす型 ( 17.6.3.1)
✤ データをコピーして、オブジェクト間で同じ状態
を実現できる
✤ (Copyable自体はC++規格に定義された用語で
はないが、上の2つの性質をまとめてCopyable
という)
28
//	 CopyConstructible
T	 u	 =	 v;
T(v);
	 
//	 CopyAssignable
u	 =	 v;
Copyable Type
29
Movable Type
✤ MoveConstructible要件 と
MoveAssignable要件 を満たす型 ( 17.6.3.1)
✤ データ(の所有権)を移動して、オブジェクト間
でデータを受け渡せる
✤ (Movable自体はC++規格に定義された用語で
はないが、上の2つの性質をまとめてMovableと
いう)
30
//	 MoveConstructible
T	 u	 =	 SomeFunctionReturnsT();
T(SomeFunctionReturnsT());
	 
//	 MoveAssignable
u	 =	 SomeFunctionReturnsT();
Movable Type
31
//	 MoveConstructible
T	 u	 =	 std::move(t1);
T(std::move(t2));
	 
//	 MoveAssignable
u	 =	 std::move(t3);
Movable Type
32
#include	 <cassert>
#include	 <thread>
#include	 <iostream>
void	 foo(int	 a,	 int	 b)	 {	 std::cout	 <<	 a	 <<	 ",	 "	 <<	 b	 <<	 std::endl;	 }
int	 main()	 {
	 	 	 	 std::thread	 th1(foo,	 1,	 2);
	 	 	 	 //	 コンパイルエラー
	 	 	 	 std::thread	 th2	 =	 th1;
	 	 	 	 //	 ムーブなら問題ない
	 	 	 	 std::thread	 th3	 =	 std::move(th1);
	 	 	 	 
	 	 	 	 //	 ムーブ元のth1はスレッドを手放している。
	 	 	 	 assert(th1.get_id()	 ==	 std::thread().get_id());
	 	 	 	 th3.join();
}
スレッドの受け渡し
33
thread
✤ threadクラスのデストラクタと、スレッド管理
の問題
34
デストラクタとjoin/detach
35
✤ thread::join()はスレッドの終了を待機し、
threadオブジェクトを初期化する関数
✤ thread::detach()はスレッドの管理を手放し、
threadオブジェクトを初期化する関数
デストラクタとjoin/detach
36
✤ なんらかのスレッドを管理しているthreadオブ
ジェクトが、join()もdetach()も呼び出さずにデ
ストラクトされると、std::terminate()を呼び出
して、プログラムが強制終了する。
✤ デストラクタで自動的にjoin()やdetach()を呼び出すこと
にすると、プログラマの意図しないjoin()やdetach()の
呼び出しが発生し、予期しないバグを引き起こす可能性が
あるため。
✤ http://d.hatena.ne.jp/yohhoy/20120209/p1
✤ http://d.hatena.ne.jp/yohhoy/20120211/p1
✤ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2802.html
void	 worker(SomeParam	 p)
{
	  doSomething();
}
void	 foo(SomeParam	 p)
{
	  std::thread	 th(worker,	 p);
	 	 	 	 
	 	 	 	 //	 このまま関数を抜ける
	 	 	 	 //	 →std::terminate()で強制終了
}
デストラクタとjoin/detach
37
デストラクタとjoin/detach
38
✤ このままでは、あまりに活用しにくいように思わ
れるが、そもそもthreadクラスはC++で
スレッドを扱うための最もプリミティブな機能な
ので、このようになっている。
デストラクタとjoin/detach
39
✤ マルチスレッドや非同期処理のより高級な仕組み
としてstd::asyncやstd::future/std::promiseな
どが用意されている。
✤ ただしマルチスレッドプログラミングに便利な機
能が充分に っているとは言えない。
✤ なのでそういうのが必要な場合はTBBや
Microsoft PPLなどを使ったほうがいいかも?
✤ http://corensic.wordpress.com/2011/10/10/async-tasks-in-c11-not-quite-
there-yet/
✤ http://d.hatena.ne.jp/yohhoy/20120417/p1
デストラクタとjoin/detach
40
✤ 明示的にjoin()/detach()しなければプログラムが
強制終了する挙動は、そのままでは例外機構との
相性が悪い。
✤ RAIIイディオムを用いて、自動でjoinを行う方法
などが以下に紹介されている。
✤ http://akrzemi1.wordpress.com/2012/11/14/not-using-stdthread/
✤ http://www.boost.org/doc/html/thread/ScopedThreads.html
本日やる内容
41
✤ thread
✤ mutex/lock
✤ future/promise
✤ condition_variable
Mutex/Lock
42
✤ 排他処理を実現する仕組み
Mutexクラス
43
✤ スレッド間で排他的に所有されるリソースを表す
クラス ( 30.4)
✤ ミューテックスオブジェクトは、データ競合に対する
保護を容易にし、execution agents間での安全なデー
タ同期を可能にします。
Mutexクラス
44
✤ 標準で定義されているMutexクラスは以下の4つ
✤ std::mutex
✤ std::recursive_mutex
✤ std::timed_mutex
✤ std::recursive_timed_mutex
std::mutex
45
✤ 再帰的ロック不可なミューテックス ( 30.4.1.2.1)
✤ Lockable
std::recursive_mutex
46
✤ 再帰的ロック可能なミューテックス ( 30.4.1.2.2)
✤ Lockable
✤ Window APIのMutexやCritical Sectionの挙動
と同じ
Lockable Type
47
✤ 排他処理のために、標準規格のスレッドライブラ
リから使用されるオブジェクトに必要とされる要
件を満たす型 ( 30.2.5.3)
✤ 以下の3つのメンバ関数を持つなど
✤ m.lock()
✤ m.try_lock()
✤ m.unlock()
SomeLockableType	 m;
//	 所有権を取得
m.lock();
//	 所有権の取得を試行
m.try_lock();
//	 所有権を手放す
m.unlock();
Lockable Type
48
std::timed_mutex
49
✤ 再帰的ロック不可な
時間制限機能付きミューテックス
✤ ロック処理を制限時間まで試行する
✤ TimedLockable
std::recursive_timed_mutex
50
✤ 再帰的ロック可能な
時間制限機能付きミューテックス
✤ ロック処理を制限時間まで試行する
✤ TimedLockable
TimedLockable Type
51
✤ 排他処理のために、標準規格のスレッドライブラ
リから使用されるオブジェクトに必要とされる要
件を満たす型 ( 30.2.5.3)
✤ LockableTypeの性質に加え、以下のメンバ関数
を持つなど
✤ m.try_lock_for()
✤ m.try_lock_until()
#include	 <chrono>
SomeTimedLockableType	 m;
//	 指定時間だけ所有権の取得を試行
m.try_lock_for(
	  std::chrono::seconds(3)
	 	 	 	 );
//	 指定時刻まで所有権の取得を試行
m.try_lock_until(
	  std::chrono::steady_clock()::now()	 +
	 	 	 	 std::chrono::seconds(3)
	  );
Lockable Type
52
Lockクラス
53
✤ Lockableなオブジェクトを管理するRAIIクラス
( 30.4.2)
✤ lock とはLockableなオブジェクトの参照を保持し、ス
コープを抜けるなどのデストラクト時には、その
Lockableなオブジェクトをunlockするようなオブジェク
トです。
execution agentはlockableオブジェクト(のロック)の
所有権を、例外安全のマナーに則って管理するための助け
として、この"lock"を使用できます。
Lockクラス
54
✤ それ自身は、排他処理のための直接的な機能は持
たずに、参照として保持するMutexクラスを管理
するだけ。
Lockクラス
55
✤ 標準規格で定義されているLockクラス
✤ std::lock_guard<Mutex>
✤ std::unique_lock<Mutex>
std::lock_guard<Mutex>
56
✤ ミューテックスのシンプルな管理機構を実現する
クラステンプレート
✤ テンプレート引数Mutexは、BasicLockableでな
ければならない
BasicLockable Type
57
✤ 排他処理のために、標準規格のスレッドライブラ
リから使用されるオブジェクトに必要とされる要
件を満たす型 ( 30.2.5.3)
✤ 以下の2つのメンバ関数を持つなど
✤ m.lock()
✤ m.unlock()
✤ 前述のLockable Typeは、BasicLockable Type
の性質を含んでいる
SomeBasicLockableType	 m;
//	 所有権を取得
m.lock();
//	 所有権を手放す
m.unlock();
BasicLockable Type
58
struct	 Worker	 {	 
	  //...
	 	 	 	 void	 process()	 {
	 	 	 	 	 	 	 	 for(int	 i	 =	 0;	 i	 <	 100;	 ++i)	 {
	 	 	 	 	 	 	 	 	 	 	 	 //このスコープ内だけ排他処理する
	 	 	 	 	 	 	 	 	 	 	 	 std::lock_guard<std::mutex>	 lock(mutex_);
	 	 	 	 	 	 	 	 	 	 	 	 
	 	 	 	 	 	 	 	 	  	 	 data_	 =	 doSomething(data_);
	 	 	 	 	 	 	 	 }
	 	 	 	 }
private:
	  std::mutex	 	 mutex_;
	 	 	 	 int	 	  	  	 	 	 	 data_;
	 	 	 	 //	 ...
};
std::lock_guard<Mutex>
59
Lockクラス
60
✤ 標準規格で定義されているLockクラス
✤ std::lock_guard<Mutex>
✤ std::unique_lock<Mutex>
std::unique_lock<Mutex>
61
✤ lock_guardよりも高級な処理ができるクラス
✤ Mutexオブジェクトの再割当て、ムーブ、try_lock_*によ
るロックの試行
Lockクラス
62
✤ Lockクラスによって、プログラマが明示的に
lock()/unlock()を対応付けて管理する必要がなく
なる。
✤ RAIIというイディオムによって、例外安全性も高
まる。
✤ http://d.hatena.ne.jp/heisseswasser/20130508/1367988794
本日やる内容
63
✤ thread
✤ mutex/lock
✤ future/promise
✤ condition_variable
future/promise
64
✤ 並行プログラミングのPromise/Futureパターン
を実現する。
✤ あるスレッドから、同じあるいは異なるスレッド
で走る関数の結果を受け取るためのコンポーネン
ト。マルチスレッドプログラミングのためだけで
はなく、シングルスレッドプログラムでも、非同
期処理に役立つ。( 30.6.1)
future/promise
65
✤ std::promiseクラスとstd::futureクラスの対応す
るオブジェクト同士は、一つのshared stateを
共有する。( 30.6.4)
✤ データを作る側はpromiseに値を設定し、データ
を受け取る側ではfutureから値を取得する
void	 sum_async(	 std::vector<int>	 const	 &data,
	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 std::promise<int>	 promise)	 {
	 	 	 	 int	 sum	 =	 0;
	 	 	 	 for(auto	 n	 :	 data)	 {	 sum	 +=	 n;	 }
	 	 	 	 promise.set_value(sum);	 	 //	 promiseにデータをセットし
}
int	 main()	 {
	 	 	 	 std::vector<int>	 data	 =	 {	 1,	 2,	 3	 };
	 	 	 	 std::promise<int>	 p;
	 	 	 	 std::future<int>	 f	 =	 p.get_future();
	 	 	 	 std::thread	 th(
sum_async,	 std::cref(data),	 std::move(p));
	 	 	 	 th.detach();
	 	 	 	 std::cout	 <<	 f.get()	 <<	 std::endl;	 //	 futureで受け取る
}
future/promise
66
std::promise<R>
67
✤ set_value(R const &)
✤ 非同期処理の結果として値を設定
✤ この形式の他に、Rの型によって異なるシグネチャのものが存在する。
✤ set_exception(std::exception_ptr)
✤ 非同期処理の結果として例外を設定
std::future<R>
68
✤ get()
✤ 非同期処理の結果を取得する
✤ この形式の他に、Rの型によって戻り値やシグネチャが異なるものが存在する。
✤ promiseで例外が設定された場合は、get()の呼び出し
で、もとの例外が再送出される
✤ wait()
✤ 非同期処理の結果がpromiseに設定されるまで処理をブ
ロックする(値/例外はまだ取得しない)
void	 sum_async(	 std::vector<int>	 const	 &data,
	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 std::promise<int>	 promise)	 {
	 	 	 	 if(data.empty())	 {
	 	 	 	 	 	 	 	 std::exception_ptr	 pe	 =
	 	 	 	 	 	 	 	 	 	 	 	 std::make_exception_ptr(
	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 UnexpectedDataLengthError()	 );
    //	 エラーを表すときは、promiseに例外をセットする
	 	 	 	 	 	 	 	 promise.set_exception(pe);
	 	 	 	 }	 else	 {
	 	 	 	 	 	 	 	 int	 sum	 =	 0;
	 	 	 	 	 	 	 	 for(auto	 n	 :	 data)	 {	 sum	 +=	 n;	 }
	 	 	 	 	 	 	 	 promise.set_value(sum);
	 	 	 	 }
}
例外の受け渡し(セット側)
69
int	 main()	 {
	 	 	 	 std::vector<int>	 data	 =	 {};
	 	 	 	 std::promise<int>	 p;
	 	 	 	 std::future<int>	 f	 =	 p.get_future();
	 	 	 	 std::thread	 th(
	 	 	 	 	 	 	 	 sum_async,	 std::cref(data),	 std::move(p));
	 	 	 	 th.detach();
	 	 	 	 try	 {
	 	 	 	 	 	 	 	 std::cout	 <<	 f.get()	 <<	 std::endl;


 //	 futureのget()で例外が再送出される
	 	 	 	 }	 catch(UnexpectedDataLengthError	 &e)	 {
	 	 	 	 	 	 	 	 std::cout	 <<	 e.what()	 <<	 std::endl;
	 	 	 	 }
}
例外の受け渡し(取得側)
70
本日やる内容
71
✤ thread
✤ mutex/lock
✤ future/promise
✤ condition_variable
condition_variable
72
✤ 条件変数という、スレッド間で同期をとる仕組み
( 30.5/1)
✤ 条件変数は、ある条件が満たされた事によって他のス
レッドから通知を受けたり、システム時間が設定時刻に到
達するまでスレッドをブロックするのに使用される同期プ
リミティブを提供します。
条件変数の動作原理
73
✤ あるスレッドでミューテックスにロックをかけ、
条件変数にミューテックスを渡す。
✤ 条件変数はミューテックスのロックを解放し、処
理をブロック、スレッドは待機状態になる。
✤ 別のスレッドから待機状態のスレッドに起動通知
を送る
✤ 条件変数はロックを再取得し、待機状態のスレッ
ドを再開させる
std::condition_variable	 cond;
std::mutex	 mutex;
bool	 data_ready;
void	 process_data();
void	 wait_for_data_to_process()	 {
	 	 	 	 std::unique_lock<std::mutex>	 lock(mut);
	 	 	 	 
	 	 	 	 //	 データが準備できるまで待機する。
	 	 	 	 while(!data_ready)	 {
	 	 	 	 	 	 	 	 cond.wait(lock);
	 	 	 	 }
	 	 	 	 process_data();
}
condition_variable
74
void	 retrieve_data();
void	 prepare_data();
void	 prepare_data_for_processing()	 {
	 	 	 	 retrieve_data();
	 	 	 	 prepare_data();
	 	 	 	 {
	 	 	 	 	 	 	 	 boost::lock_guard<boost::mutex>	 lock(mut);
	 	 	 	 	 	 	 	 data_ready=true;
	 	 	 	 }
	 	 	 	 //	 データが準備できたら待機状態のスレッドを起こす
	 	 	 	 cond.notify_one();
}
condition_variable
75
ミューテックスの型
76
✤ std::condition_variableではミューテックスに
std::unique_lock<std::mutex>を使用する。
✤ std::condition_variable_anyでは、排他処理
に、std::unique_lock<std::mutex>以外の別のク
ラスを使用できる。
hwm.task
77
ここまでの機能
78
✤ thread
✤ mutex/lock
✤ future/promise
✤ condition_variable
✤ これらを使って、タスクライブラリっぽいものを
作ってみる。
hwm.task
79
✤ Github :
https://github.com/hotwatermorning/hwm.task.git
hwm.task
80
✤ Github :
https://github.com/hotwatermorning/hwm.task.git
✤ git cloneして持ってきて、
SConstructに指定している
Boostのパスなどを適宜書き換えて、
$> scons
するとサンプルコードがビルドできる。
(※scons必要)
✤ gcc 4.8で動作確認済み。
hwm.task
81
✤ 概要
✤ いくつかスレッドを起動させ、タスクキューにタスクが追
加されると、どれかのスレッドがそれを処理する。
✤ 起動するスレッドの数はキューの初期化時に設定できる
✤ タスクはINVOKE()のように呼び出せるものであればなん
でもいい。
✤ タスクキューへのタスクの追加はスレッドセーフ
✤ タスクキューから自動でタスクが取り出され実行され、そ
の実行結果は、std::futureを通じて非同期に取得できる。
hwm.task
82
✤ task_queue.hpp
✤ タスクキュー本体。タスクを管理し、適宜どれかのスレッ
ドで取り出して実行する
hwm.task
83
✤ locked_queue.hpp
✤ タスクキューの実装に使用している、コンテナ。
✤ Producer/Consumerパターンを使用したマルチスレッド
セーフなキュー
hwm.task
84
✤ task_base.hpp/task_impl.hpp
✤ タスクを表すクラス。
✤ run()メンバ関数によって実行される。
✤ 実際の処理を行う部分はType Erasureというイディオム
によって、baseクラスに隠 される。
//!	 タスクキューで扱うタスクを表すベースクラス
namespace	 hwm	 {
namespace	 detail	 {	 namespace	 ns_task	 {
struct	 task_base
{
	 	 	 	 virtual	 ~task_base()	 {}
	 	 	 	 virtual	 void	 run()	 =	 0;
};
}}}
task_base
85
//!	 タスクの実体クラス
//!	 Boost.Preprocessorを用いて、10引数を取るタスクまでをサポート
template<class	 F	 BOOST_PP_ENUM_TRAILING(11,	 HWM_TASK_template_parameters,	 unused)>
struct	 task_impl;
#define	 BOOST_PP_LOCAL_MACRO(iteration_value)	 
	 	 	 	 template<class	 F	 BOOST_PP_ENUM_TRAILING(iteration_value,	 HWM_TASK_template_parameters_specialized,	 unused)>
	 	 	 	 struct	 task_impl<F	 BOOST_PP_ENUM_TRAILING_PARAMS(iteration_value,	 Arg)	 /*BOOST_PP_ENUM_TRAILING(BOOST_PP_SUB(10,	 
iteration_value),	 HWM_TASK_default_params,	 unused)	 */>
	 	 	 	 	 	 	 	 :	 	 task_base	 
	 	 	 	 {
	 	 	 	 	 	 	 	 typedef	 typename	 function_result_type<F	 BOOST_PP_ENUM_TRAILING_PARAMS(iteration_value,	 Arg)>::type	 result_type;	 	 	 	 	 	 	 	 
typedef	 std::promise<result_type>	 promise_type;
	 	 	 	 	 	 	 	 task_impl(promise_type	 &&	 promise,	 F	 &&	 f	 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(iteration_value,	 Arg,	 &&arg))
	 	 	 	 	 	 	 	 	 	 	 	 :	 	 	 promise_(boost::move(promise))
	 	 	 	 	 	 	 	 	 	 	 	 ,	 	 	 f_(std::forward<F>(f))
	 	 	 	 	 	 	 	 	 	 	 	 BOOST_PP_ENUM_TRAILING(iteration_value,	 HWM_TASK_initialize_member_variables,	 unused)
	 	 	 	 	 	 	 	 {}
	 	 	 	 private:
	 	 	 	 	 	 	 	 task_impl(task_impl	 const	 &)	 =	 delete;
	 	 	 	 	 	 	 	 task_impl	 &	 	 operator=(task_impl	 const	 &)	 =	 delete;
	 	 	 	 	 	 	 	 promise_type	 	 	 	 promise_;
	 	 	 	 	 	 	 	 F	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 f_;
	 	 	 	 	 	 	 	 BOOST_PP_REPEAT(iteration_value,	 HWM_TASK_define_member_variables,	 unused)
	 	 	 	 	 	 	 	 virtual
	 	 	 	 	 	 	 	 void	 	 	 	 run()	 override	 final
	 	 	 	 	 	 	 	 {
	 	 	 	 	 	 	 	 	 	 	 	 try	 {
	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 promise_.set_value(f_(BOOST_PP_ENUM(iteration_value,	 HWM_TASK_apply_member_variables,	 unused)));
	 	 	 	 	 	 	 	 	 	 	 	 }	 catch(...)	 {
	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 promise_.set_exception(std::current_exception());
	 	 	 	 	 	 	 	 	 	 	 	 }
	 	 	 	 	 	 	 	 }
	 	 	 	 };
	 	 	 	 /**/
task_impl
86
//!	 タスクの実体クラス
//!	 Boost.Preprocessorを用いて、10引数を取るタスクまでをサポート
template<class	 F>
struct	 task_impl	 {
	 	 	 	 task_imp(std::promise<F()の戻り値>	 &&promise,	 F	 &&f)
	 	 	 	 	 	 	 	 :	 promise_(std::move(promise))
	 	 	 	 	 	 	 	 ,	 f_(std::forward<F>(f))
	 	 	 	 {}
	 	 	 	 
	 	 	 	 std::promise<F()の戻り値>	 promise_;
	 	 	 	 F	 f_;
	 	 	 	 
	 	 	 	 void	 	 	 	 run()	 override	 final	 {
	 	 	 	 	 	 	 	 try	 {
	 	 	 	 	 	 	 	 	 	 	 	 promise_.set_value(f_());
	 	 	 	 	 	 	 	 }	 catch(...)	 {
	 	 	 	 	 	 	 	 	 	 	 	 promise_.set_exception(std::current_exception());
	 	 	 	 	 	 	 	 }
	 	 	 	 }
};
task_impl
87
//!	 タスクの実体クラス
//!	 Boost.Preprocessorを用いて、10引数を取るタスクまでをサポート
template<class	 F,	 class	 Arg0>
struct	 task_impl	 {
	 	 	 	 task_imp(std::promise<F()の戻り値>	 &&promise,	 F	 &&f,	 Arg0	 &&arg0)
	 	 	 	 	 	 	 	 :	 promise_(std::move(promise))
	 	 	 	 	 	 	 	 ,	 f_(std::forward<F>(f))
	 	 	 	 	 	 	 	 ,	 arg0_(arg0)
	 	 	 	 {}
	 	 	 	 
	 	 	 	 std::promise<F()の戻り値>	 promise_;
	 	 	 	 F	 f_;
	 	 	 	 Arg0	 arg0_;
	 	 	 	 
	 	 	 	 void	 	 	 	 run()	 override	 final	 {
	 	 	 	 	 	 	 	 try	 {
	 	 	 	 	 	 	 	 	 	 	 	 promise_.set_value(f_(std::forward<Arg0>(arg0_)));
	 	 	 	 	 	 	 	 }	 catch(...)	 {
	 	 	 	 	 	 	 	 	 	 	 	 promise_.set_exception(std::current_exception());
	 	 	 	 	 	 	 	 }
	 	 	 	 }
};
task_impl
88
example
89
namespace	 hwm	 {
struct	 task_queue	 {


 //	 タスクをキューに追加する
	  template<class	 F,	 class...	 Args>


 

 	 	 std::future<F(Args)の戻り値の型>
	  >
	  enqueue_sync(F	 f,	 Args...	 args);
	 	 	 	 
	 	 	 	 //...
};
}
タスクの追加
90
hwm::task_queue	 tq(スレッド数);
std::future<int>	 f	 =
	  tq.enqueue_sync(
	 	 	 	 	  [](int	 x1,	 int	 x2)	 ->	 int	 {
	 	 	 	 	 	 	 	 	  std::cout	 <<	 (x1	 +	 x2)	 <<	 std::endl;
	  	  	  return	 x1	 +	 x2;
	 	 	 	 	 	 	 	 },
	 	 	 	 	 	 	 	 10,	 20
	 	 	 	 );
	 	 	 	 
//	 タスクキューによって自動的に非同期に実行される	 
タスクの追加
91
//	 タスクキューに積まれた処理の結果は、
//	 タスク追加時に返されたfutureオブジェクトを使用して
//	 取得する
std::cout
	 	 	 	 <<	 "calculated	 value	 :	 "	 <<	 f.get()
	 	 	 	 <<	 std::end;
実行結果の取得
92
まとめ
✤ C++11から、言語規格でスレッドがサポートさ
れました。
✤ スレッドを扱うためのライブラリも言語に追加さ
れました。
✤ これでマルチスレッドライブラリ/アプリケー
ションを書くのが容易になります。
93
まとめ
✤並行プログラミングを極めて
タダ飯の時代を!
94

More Related Content

What's hot

C/C++プログラマのための開発ツール
C/C++プログラマのための開発ツールC/C++プログラマのための開発ツール
C/C++プログラマのための開発ツールMITSUNARI Shigeo
 
Pythonによる黒魔術入門
Pythonによる黒魔術入門Pythonによる黒魔術入門
Pythonによる黒魔術入門大樹 小倉
 
C++の話(本当にあった怖い話)
C++の話(本当にあった怖い話)C++の話(本当にあった怖い話)
C++の話(本当にあった怖い話)Yuki Tamura
 
Constexpr 中3女子テクニック
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニックGenya Murakami
 
プログラムを高速化する話Ⅱ 〜GPGPU編〜
プログラムを高速化する話Ⅱ 〜GPGPU編〜プログラムを高速化する話Ⅱ 〜GPGPU編〜
プログラムを高速化する話Ⅱ 〜GPGPU編〜京大 マイコンクラブ
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するYoshifumi Kawai
 
クロージャデザインパターン
クロージャデザインパターンクロージャデザインパターン
クロージャデザインパターンMoriharu Ohzu
 
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜Preferred Networks
 
こわくない Git
こわくない Gitこわくない Git
こわくない GitKota Saito
 
いまさら聞けないarmを使ったNEONの基礎と活用事例
いまさら聞けないarmを使ったNEONの基礎と活用事例いまさら聞けないarmを使ったNEONの基礎と活用事例
いまさら聞けないarmを使ったNEONの基礎と活用事例Fixstars Corporation
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪Takuto Wada
 
shared_ptrとゲームプログラミングでのメモリ管理
shared_ptrとゲームプログラミングでのメモリ管理shared_ptrとゲームプログラミングでのメモリ管理
shared_ptrとゲームプログラミングでのメモリ管理DADA246
 
いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門Fixstars Corporation
 
async/await のしくみ
async/await のしくみasync/await のしくみ
async/await のしくみ信之 岩永
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexprGenya Murakami
 
ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門Fixstars Corporation
 

What's hot (20)

C/C++プログラマのための開発ツール
C/C++プログラマのための開発ツールC/C++プログラマのための開発ツール
C/C++プログラマのための開発ツール
 
Pythonによる黒魔術入門
Pythonによる黒魔術入門Pythonによる黒魔術入門
Pythonによる黒魔術入門
 
C++の話(本当にあった怖い話)
C++の話(本当にあった怖い話)C++の話(本当にあった怖い話)
C++の話(本当にあった怖い話)
 
Constexpr 中3女子テクニック
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニック
 
Docker Compose 徹底解説
Docker Compose 徹底解説Docker Compose 徹底解説
Docker Compose 徹底解説
 
プログラムを高速化する話Ⅱ 〜GPGPU編〜
プログラムを高速化する話Ⅱ 〜GPGPU編〜プログラムを高速化する話Ⅱ 〜GPGPU編〜
プログラムを高速化する話Ⅱ 〜GPGPU編〜
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
 
プログラムを高速化する話
プログラムを高速化する話プログラムを高速化する話
プログラムを高速化する話
 
クロージャデザインパターン
クロージャデザインパターンクロージャデザインパターン
クロージャデザインパターン
 
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
 
こわくない Git
こわくない Gitこわくない Git
こわくない Git
 
いまさら聞けないarmを使ったNEONの基礎と活用事例
いまさら聞けないarmを使ったNEONの基礎と活用事例いまさら聞けないarmを使ったNEONの基礎と活用事例
いまさら聞けないarmを使ったNEONの基礎と活用事例
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪
 
C++の黒魔術
C++の黒魔術C++の黒魔術
C++の黒魔術
 
shared_ptrとゲームプログラミングでのメモリ管理
shared_ptrとゲームプログラミングでのメモリ管理shared_ptrとゲームプログラミングでのメモリ管理
shared_ptrとゲームプログラミングでのメモリ管理
 
llvm入門
llvm入門llvm入門
llvm入門
 
いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門
 
async/await のしくみ
async/await のしくみasync/await のしくみ
async/await のしくみ
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexpr
 
ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門
 

Similar to 規格書で読むC++11のスレッド

Flutterを体験してみませんか
Flutterを体験してみませんかFlutterを体験してみませんか
Flutterを体験してみませんかcch-robo
 
エキ Py 読書会02 2章後半
エキ Py 読書会02 2章後半エキ Py 読書会02 2章後半
エキ Py 読書会02 2章後半Tetsuya Morimoto
 
Programming camp 2008, Codereading
Programming camp 2008, CodereadingProgramming camp 2008, Codereading
Programming camp 2008, CodereadingHiro Yoshioka
 
Apache Torqueについて
Apache TorqueについてApache Torqueについて
Apache Torqueについてtako pons
 
関ジャバ JavaOne Tokyo 2012報告会
関ジャバ JavaOne Tokyo 2012報告会関ジャバ JavaOne Tokyo 2012報告会
関ジャバ JavaOne Tokyo 2012報告会Koichi Sakata
 
HandlerSocket plugin for MySQL
HandlerSocket plugin for MySQLHandlerSocket plugin for MySQL
HandlerSocket plugin for MySQLakirahiguchi
 
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~normalian
 
エキ Py 読書会02 2010/9/7
エキ Py 読書会02 2010/9/7エキ Py 読書会02 2010/9/7
エキ Py 読書会02 2010/9/7Tetsuya Morimoto
 
PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!Shohei Okada
 
【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門 【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門 sandai
 
Boost.Flyweight
Boost.FlyweightBoost.Flyweight
Boost.Flyweightgintenlabo
 
DTrace for biginners part(2)
DTrace for biginners part(2)DTrace for biginners part(2)
DTrace for biginners part(2)Shoji Haraguchi
 
Uart受信設計2013
Uart受信設計2013Uart受信設計2013
Uart受信設計2013Kiyoshi Ogawa
 
Vim の話
Vim の話Vim の話
Vim の話cohama
 
C#coding guideline その2_20130325
C#coding guideline その2_20130325C#coding guideline その2_20130325
C#coding guideline その2_20130325Yoshihisa Ozaki
 

Similar to 規格書で読むC++11のスレッド (20)

Flutterを体験してみませんか
Flutterを体験してみませんかFlutterを体験してみませんか
Flutterを体験してみませんか
 
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
 
エキ Py 読書会02 2章後半
エキ Py 読書会02 2章後半エキ Py 読書会02 2章後半
エキ Py 読書会02 2章後半
 
Objc lambda
Objc lambdaObjc lambda
Objc lambda
 
Programming camp 2008, Codereading
Programming camp 2008, CodereadingProgramming camp 2008, Codereading
Programming camp 2008, Codereading
 
Apache Torqueについて
Apache TorqueについてApache Torqueについて
Apache Torqueについて
 
関ジャバ JavaOne Tokyo 2012報告会
関ジャバ JavaOne Tokyo 2012報告会関ジャバ JavaOne Tokyo 2012報告会
関ジャバ JavaOne Tokyo 2012報告会
 
HandlerSocket plugin for MySQL
HandlerSocket plugin for MySQLHandlerSocket plugin for MySQL
HandlerSocket plugin for MySQL
 
Prosym2012
Prosym2012Prosym2012
Prosym2012
 
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
 
What is template
What is templateWhat is template
What is template
 
エキ Py 読書会02 2010/9/7
エキ Py 読書会02 2010/9/7エキ Py 読書会02 2010/9/7
エキ Py 読書会02 2010/9/7
 
PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!
 
【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門 【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門
 
Java class design
Java class designJava class design
Java class design
 
Boost.Flyweight
Boost.FlyweightBoost.Flyweight
Boost.Flyweight
 
DTrace for biginners part(2)
DTrace for biginners part(2)DTrace for biginners part(2)
DTrace for biginners part(2)
 
Uart受信設計2013
Uart受信設計2013Uart受信設計2013
Uart受信設計2013
 
Vim の話
Vim の話Vim の話
Vim の話
 
C#coding guideline その2_20130325
C#coding guideline その2_20130325C#coding guideline その2_20130325
C#coding guideline その2_20130325
 

More from Kohsuke Yuasa

オーディオ用レベルメータを作ってみよう
オーディオ用レベルメータを作ってみようオーディオ用レベルメータを作ってみよう
オーディオ用レベルメータを作ってみようKohsuke Yuasa
 
Juceで作るオーディオアプリケーション
Juceで作るオーディオアプリケーションJuceで作るオーディオアプリケーション
Juceで作るオーディオアプリケーションKohsuke Yuasa
 
イマドキC++erのモテカワリソース管理術
イマドキC++erのモテカワリソース管理術イマドキC++erのモテカワリソース管理術
イマドキC++erのモテカワリソース管理術Kohsuke Yuasa
 
最近のC++ @ Sapporo.cpp #5
最近のC++ @ Sapporo.cpp #5最近のC++ @ Sapporo.cpp #5
最近のC++ @ Sapporo.cpp #5Kohsuke Yuasa
 
C++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプC++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプKohsuke Yuasa
 
Introduction to boost test
Introduction to boost testIntroduction to boost test
Introduction to boost testKohsuke Yuasa
 
Sapporocpp#2 exception-primer
Sapporocpp#2 exception-primerSapporocpp#2 exception-primer
Sapporocpp#2 exception-primerKohsuke Yuasa
 

More from Kohsuke Yuasa (10)

オーディオ用レベルメータを作ってみよう
オーディオ用レベルメータを作ってみようオーディオ用レベルメータを作ってみよう
オーディオ用レベルメータを作ってみよう
 
Juceで作るオーディオアプリケーション
Juceで作るオーディオアプリケーションJuceで作るオーディオアプリケーション
Juceで作るオーディオアプリケーション
 
イマドキC++erのモテカワリソース管理術
イマドキC++erのモテカワリソース管理術イマドキC++erのモテカワリソース管理術
イマドキC++erのモテカワリソース管理術
 
最近のC++ @ Sapporo.cpp #5
最近のC++ @ Sapporo.cpp #5最近のC++ @ Sapporo.cpp #5
最近のC++ @ Sapporo.cpp #5
 
C++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプC++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプ
 
Introduction to boost test
Introduction to boost testIntroduction to boost test
Introduction to boost test
 
C++ template-primer
C++ template-primerC++ template-primer
C++ template-primer
 
Read egg oven
Read egg ovenRead egg oven
Read egg oven
 
Study3 boost
Study3 boostStudy3 boost
Study3 boost
 
Sapporocpp#2 exception-primer
Sapporocpp#2 exception-primerSapporocpp#2 exception-primer
Sapporocpp#2 exception-primer
 

Recently uploaded

プレイマットのパターン生成支援ツールの評価
プレイマットのパターン生成支援ツールの評価プレイマットのパターン生成支援ツールの評価
プレイマットのパターン生成支援ツールの評価sugiuralab
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000Shota Ito
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxAtomu Hidaka
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directoryosamut
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
プレイマットのパターン生成支援ツール
プレイマットのパターン生成支援ツールプレイマットのパターン生成支援ツール
プレイマットのパターン生成支援ツールsugiuralab
 

Recently uploaded (7)

プレイマットのパターン生成支援ツールの評価
プレイマットのパターン生成支援ツールの評価プレイマットのパターン生成支援ツールの評価
プレイマットのパターン生成支援ツールの評価
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
 
プレイマットのパターン生成支援ツール
プレイマットのパターン生成支援ツールプレイマットのパターン生成支援ツール
プレイマットのパターン生成支援ツール
 

規格書で読むC++11のスレッド