この記事ではスレッド安全性分析、完全な研究のために、関連リンクを参照してください。
クランスレッドセーフな分析ツールは、C ++言語、潜在的な競争を警告するために使用されるコードを拡張したものです。また、コンパイル時に静的解析、パフォーマンスの低下を実行時ではありません。このツールはまだ開発段階にあるが、本番環境での展開のために十分成熟していても。
これは、マルチスレッドプログラミングのための型システムと同様に動作します。例えば、変数がfoo
分析ツールが書き込みロックに対応する変数が保護されていない場合、警告を促すメッセージが表示されます検出された場合、複数のスレッドによってアクセスされてもよいです。
基本コンセプト
打ち鳴らすスレッドセーフな分析ツールcapabilities
の資源を保護します。リソースは、ここでデータのメンバーを指すか、または基礎となるリソース関数またはメソッドへのアクセスを提供します。それが唯一の呼び出し元のスレッドが持っていることを確認しcapability
、対応するリソースにアクセスするために。
もしmu
代表mutex
スレッドの実行、mu.Lock()
その代わった後には、へのアクセス取得するためにmu
保護されたリソースをcapability
、それが呼び出したときに、mu.unLock()
その代わってリリース後capability
。スレッドはしているcapability
、それは破壊されない、それだけで解放することができますコピーされていないcapability
他のスレッドを得るためには、capability
。
使用
スレッドセーフな分析ツールは、依存関係プロパティを宣言するために、アノテーションを使用して、これらのプロパティは、クラス、メソッド、データメンバに追加のノートの上にあります。公式には、マクロ(の使用をお勧めmutex.h理解し、プロパティより読みやすいノートを作るために)。
操作方法は非常に簡単で、実行
clang -c -Wthread-safety example.cpp
変数のコメントに適し
GUARDED_BY:プロパティ宣言の前に、スレッド変数に読み取りと書き込み、変数の操作は、スレッドセーフであることを保証するために、対応するロックを取得してください。
PT_GUARDED_BY:スマートポインタとポインタに使用されGUARDED_BYなど、ポインタ自体は、バインディングはありませんが、データ保護属性ポイントに適用されます。
Mutex mu;
int *p1 GUARDED_BY(mu);
int *p2 PT_GUARDED_BY(mu);
unique_ptr<int> p3 PT_GUARDED_BY(mu);
void test() {
p1 = 0; // Warning!
*p2 = 42; // Warning!
p2 = new int; // OK.
*p3 = 42; // Warning!
p3.reset(new int); // OK.
}
機能に適用される注意事項
この関数を呼び出す前に、呼び出し元のスレッドを示し、あなたが最初のミューロックを取得する必要があります(MU)が必要です。呼び出し元の関数を呼び出す前に、すでにミューロック、追加のロックなしで共有変数への内部の修正を有しているものとします。
REQUIRES_SHARED()、および類似必要ですが、唯一の共有への読み取りアクセスを必要とします。
Mutex mu1, mu2;
int a GUARDED_BY(mu1);
int b GUARDED_BY(mu2);
void foo() REQUIRES(mu1, mu2) {
a = 0;
b = 0;
}
void test() {
mu1.Lock();
foo(); // Warning! Requires mu2.
mu1.Unlock();
}
- ACQUIRE()文は、関数がそれを解放する必要はありません終了するまでロックを取得するために内部関数を呼び出しました。呼び出し側は、この関数を呼び出す前に、ロックを保持することはできません。
- RELEASE()関数は、関数が終了する前にロックを解除するためのイニシアチブをとるだろう、入り口でロックを保持することなく、発信者を呼び出し、ロック文を放出する能力を持っています。
Mutex mu;
MyClass myObject GUARDED_BY(mu);
void lockAndInit() ACQUIRE(mu) {
mu.Lock();
myObject.init();
}
void cleanupAndUnlock() RELEASE(mu) {
myObject.cleanup();
} // Warning! Need to unlock mu.
void test() {
lockAndInit();
myObject.doSomething();
cleanupAndUnlock();
myObject.doSomething(); // Warning, mu is not locked.
}
引数がACQUIREまたはRELEASEに渡されていない場合は、参照が、これは、解析ツールは、内部関数の実装をチェックしないものとします。ロックの内側に隠された、共通の抽象インタフェースの実装の詳細。
- EXCLUDES(...)呼び出し側が指定した保持することはできません宣言
capabilities
アノテーションはときに、同じ機能リエントラント、非リエントラントロックのため、デッドロックを防ぐために使用され、あなたがデッドロックを起こし、二回ロックを取得します。
Mutex mu;
int a GUARDED_BY(mu);
void clear() EXCLUDES(mu) {
mu.Lock();
a = 0;
mu.Unlock();
}
void reset() {
mu.Lock();
clear(); // Warning! Caller cannot hold 'mu'.
mu.Unlock();
}
- NO_THREAD_SAFETY_ANALYSISは:プロパティは、.cppファイルを置くために使用される文の一部ではありません、スレッドの安全性の検査を閉じます。
クラスに適用される注意事項
能力(
):このクラスの例は、指定として使用することができ capaility
、文字列パラメータを示すために使用されcapaility
、警告が出力された場合、種。SCOPED_CAPABILITY:RAIIスタイルのためのリソース管理クラスを示しました。