プログラミング言語C++のトランザクショナルメモリ(TM; Transactional Memory)拡張に関するざっくりまとめメモ。
2013-10-05追記:本記事の内容はN3718にてアップデートされている。→id:yohhoy:20131005
本記事の内容は、2012年4月現在の最新ドラフト仕様 “Draft Specification of Transactional Language Constructs for C++, Version 1.1”(→id:yohhoy:20120413)に基づく。
超要約:Isolation と Atomicity を保証し、かつ Composable なトランザクション機能を提供する。
概要
C++トランザクショナルメモリ拡張が提供する機能の概要は下記の通り。
新キーワードと属性
C++トランザクショナルメモリ拡張の仕様では、3つのキーワードと5つの属性が新たに導入される*1。
// 新キーワード __transaction_relaxed __transaction_atomic __transaction_cancel // 属性(コメントはアノテート対象) outer // atomicトランザクション, キャンセル文 transaction_callable // 関数, クラス transaction_safe // 関数, クラス transaction_unsafe // 関数, クラス transaction_may_cancel_outer // 関数
relaxedトランザクション
relaxedトランザクションの指定はキーワード__transaction_relaxed
を用いる。
// 複合文 __transaction_relaxed { //... } // 関数 void f() __transaction_relaxed { //... } // 式 T v = __transaction_relaxed (/*...*/);
relaxedトランザクション内から呼び出される関数はtransaction_callable
属性でアノテートできる(しなくてもよい)。relaxedトランザクション実装のパフォーマンス向上を目的としており、関数アノテートはプログラムの意味には影響しない。
[[transaction_callable]] void h();
__transaction_relaxed { h(); }
atomicトランザクション
atomicトランザクションの指定はキーワード__transaction_atomic
を用いる。
// 複合文 __transaction_atomic { //... } // 関数 void f() __transaction_atomic { //... } // 式 T v = __transaction_atomic (/*...*/);
他トランザクションの入れ子とされない最外トランザクションであることを強制するには、atomicトランザクションに対してouter
属性でアノテートする。
void f0() { __transaction_atomic { /*...*/ } } void f1() { __transaction_atomic [[outer]] { /*...*/ } } __transaction_atomic { f0(); } // OK: well-formed __transaction_atomic { f1(); } // NG: ill-formed
関数が安全である/安全でないと指定するには、関数に対してtransaction_safe
/transaction_unsafe
属性でアノテートする。
int x, y, z; // 組み込み型 [[transaction_safe]] int f0(); // 安全な関数 [[transaction_unsafe]] int f1(); // 安全でない関数 __transaction_atomic { ++x; // OK: well-formed y = f0(); // OK: well-formed z = f1(); // NG: ill-formed }
クラスに対してアノテートした場合は、同クラスの全メンバ関数に対して個々にアノテートしたのと等価。さらにメンバ関数をアノテートして属性を上書きすることも出来る。
class C [[transaction_safe]] { void mf1(); // transaction_safe virtual void mf2(); // transaction_safe [[transaction_unsafe]] void mf3(); // transaction_unsafe };
キャンセル文
キャンセル文はキーワード__transaction_cancel
を用いる。
__transaction_atomic { //... if (/*...*/) __transanction_cancel; // cancel文 //... if (/*...*/) __transaction_cancel throw 42; // cancel-and-thorw文 }
最外トランザクションをキャンセルするには、キャンセル文に対してouter
属性でアノテートする。
__transaction_atomic [[outer]] { // トランザクションT1 // 処理1 __transaction_atomic { // トランザクションT2 // 処理2 if (/*...*/) __transaction_cancel; // T2(処理2)をキャンセル if (/*...*/) __transaction_cancel [[outer]]; // T1(処理1,処理2)をキャンセル } }
関数中で__transaction_cancel [[outer]]
を行う可能性があることを表明するには、関数に対してtransaction_may_cancel_outer
属性でアノテートする。
[[transaction_may_cancel_outer]] void f() { //... if (/*...*/) __transaction_cancel [[outer]]; } __transaction_atomic [[outer]] { //... __transaction_atomic { f(); } }
outer
アノテートされないキャンセル文は、必ずatomicトランザクションのレキシカル・スコープ内に無ければならない。outer
アノテートされたキャンセル文は、outer
アノテートされたatomicトランザクションのレキシカル・スコープ内、またはtransaction_may_cancel_outer
アノテートされた関数内のいずれかに無ければならない。
関連URL