More Related Content Similar to Boost9 session Similar to Boost9 session (20) Boost9 session10. Boost.Thread v2
1.50.0 から v1 は提供されず v2 に完全移行(予定)
C++11 compliance が中心
Move semantics が Boost.Move ベースになる
Boost.DateTime ベースの this_thread::sleep に加え
Boost.Chrono ベースの this_thread::sleep_(for|until)
11. Boost.Thread v3
1.55.0 から v3 へ移行予定
1.50.0 から 1.54.0 は v3 への移行期間
#define BOOST_THREAD_VERSION 3
マクロで互換性等を細かく設定できる
e.g. #define BOOST_THREAD_DONT_PROVIDE_FUTURE
ifdef → boost::unique_future
else → boost::future
18. ctx::fcontext_t orig, fc;
void f(intptr_t)
{
std::cout << "in context" << std::endl;
ctx::jump_fcontext(&fc, &orig, 0);
}
int main()
{
const size_t ctxsize = ctx::default_stacksize();
ctx::stack_allocator alloc;
fc.fc_stack.base = alloc.allocate(ctxsize);
fc.fc_stack.limit = static_cast<char *>(fc.fc_stack.base) - ctxsize;
ctx::make_fcontext(&fc, f);
std::cout << "pre jump" << std::endl;
ctx::jump_fcontext(&orig, &fc, 0);
std::cout << "post jump" << std::endl;
alloc.deallocate(fc.fc_stack.base, ctxsize);
}
19. ちょっとした注意
TLS は使ってはいけない
多分 SEGV とかそういう話だと思う
スタックのデアロケートを自動化しようとコンテキスト
内で開放してはいけない
Deallocate が戻ると SEGV
コンテキスト内ではスコープを意識して使わないと dtor
が呼ばれないコードになってしまう
エントリーポイントをそのまま出ると exit が呼ばれる
25. 例えばコールバックベースだと
function<void()> callback_timer; int state = 0;
callback_timer = timer_handler; void timer_handler()
{
while ((event = peek_event()) != FINISH) switch (state)
{ {
switch (event) case 0:
{ 呼ばれる毎に共有 ... process step 0 ...
... snip ... できる形でどこかに break;
state case 1:
case TIMER: を保持しないといけな ... process step 1 ...
callback_timer(); い break;
break; case 2:
... process step 2 ...
... snip ... break;
} }
} timer_handler を state = (state + 1) % 3;
複数登録できる }
ようにするには ...
26. 例えばコールバックベースだと
vector<function<void()>> timer_callbacks; void timer_handler(shared_ptr<int> ps)
… snip... {
timer_callbacks.push_back( switch (*ps)
bind(timer_handler, {
make_shared<int>(0)); case 0:
… snip... ... process step 0 ...
while ((event = peek_event()) != FINISH) break;
{ case 1:
switch (event) shared_ptr 等で固有 ... process step 1 ...
{ の break;
状態を持ち回る必要
... snip ... が case 2:
case TIMER: ... process step 2 ...
for (auto &c : timer_callbacks) c(); break;
break; }
... snip ... *ps = (*ps + 1) % 3;
} }
}
27. ユーザースレッドを導入すると
fcontext_t fctx;
// s tack とか make_f context とか
void timer_handler(fcontext_t *ctx)
vector<fcontext_t> timer_callbacks; {
… snip... while (true)
timer_callbacks.push_back(move(fctx)); {
... process step 0 …
while ((event = peek_event()) != FINISH) ctx = jump_fcontext(ctx, &fo, 0);
{ 固有の状態はコンテキス
switch (event) ト ... process step 1 …
{ 自身が持ってるので ctx = jump_fcontext(ctx, &fo, 0);
コンテキストの管理だけ
... snip ... 行えば良い
case TIMER: ... process step 2 …
for (auto &ctx : timer_callbacks) ctx = jump_fcontext(ctx, &fo, 0);
jump_fcontext(&fo, &ctx, &ctx); }
break; }
... snip ...
シングルスレッドの処
} 理の
} 流れと同じように書け
る
29. 高級な実装
正直 Boost.Context は抽象化されてるとはいえ常用するに
は低級すぎる
現在 Oliver が Boost.Context をベースとした
Boost.Coroutine を提案して Formal Review 待ち
http://ok73.ok.funpic.de/boost/libs/coroutine/doc/html/index.html
GSoC2006 で Eric Niebler が書いた Boost.Coroutine と基本インター
フェースは同じ
30. ctx::fcontext_t orig, fc;
void f(intptr_t)
{
Boost.Context
std::cout << "in context (pre jump)" << std::endl;
ctx::jump_fcontext(&fc, &orig, 0);
std::cout << "in context (post jump)" << std::endl;
ctx::jump_fcontext(&fc, &orig, 0);
}
int main()
{
最後に jump を忘れてはいけないし、
const size_t ctxsize = ctx::default_stacksize();
トップレベルの dtor は呼ばれない
ctx::stack_allocator alloc;
fc.fc_stack.base = alloc.allocate(ctxsize);
fc.fc_stack.limit = static_cast<char *>(fc.fc_stack.base) - ctxsize;
ctx::make_fcontext(&fc, f);
std::cout << "pre jump" << std::endl;
ctx::jump_fcontext(&orig, &fc, 0);
std::cout << "now yield" << std::endl;
ctx::jump_fcontext(&orig, &fc, 0);
std::cout << "post jump" << std::endl;
alloc.deallocate(fc.fc_stack.base, ctxsize);
}
31. Boost.Coroutine
typedef coro::coroutine<void()> coro_t;
void f(coro_t::self &self)
{
std::cout << "in coroutine (pre yield)" << std::endl;
self.yeild();
std::cout << "in coroutine (post yield)" << std::endl;
}
int main()
{ 最後に yield を呼ぶ必要はないし dtor も呼ばれ
coro_t c(f); る
std::cout << "pre jump" << std::endl;
c();
std::cout << “now yield” << std::endl;
c();
std::cout << "post jump" << std::endl;
}
33. C++ 標準委員会での動き
Study Group 1
並行と並列に関する Study Group
n3328 Resumable Functions
言語仕様としてユーザースレッドを導入する提案
resumable と await の 2 つの contextual keywords
n3356 C++ Mutable Threads
Mutable Threads の提案
n3361 C++ Language Constructs for Parallel Programming
Intel® CilkTM Plus の紹介 ( 提案は次の meeting らしい
34. C++ 標準委員会での動き
n3378 A preliminary proposal for work executors
Worker を投げると適当にスケジューリングして裏で実行する
executer の提案
Worker の戻り値は投げた時に返ってくる future で取得
しかしこれらが実際に入るのは早くとも C++2x 頃なのでは