トップ回答者
「InterlockedDecrementやInterlockedIncrement→比較」について

質問
-
InterlockedIncrementなどは、戻り値の評価も含んでアトミックであることが保証されるのでしょうか?(そうでないと参照カウント操作について以下の形は不完全な気がするのですが)
struct AAA {
ULONG i;
void AddRef(){
InterlockedIncrement(&i);
}
void Release(){
if ( InterlockedDecrement(&i) == 0 ) delete this;
}
};便宜上
InterLokedDecrement→--
InterlockedIncrement→++
と書きます。
コンストラクタ・iの値とか仮想関数にすべきとか呼び出し規約は__stdcallの方がいいのでは?戻り値は・・・?とか細かいところは本題でないので省略するとして、--(&i) == 0がアトミックでない場合、以下の手順になった場合限定ですがやばい気がします。
1.スレッド1がRelease関数に入り、--。
2.--終了後 ==0の比較の前にスレッド2がAddRef関数を呼び出す。
3.==0との比較が成立し、ここで++(&i)の前にdelete thisまで行われれば++が呼ばれたときにthis->iに対するアクセス違反
4.++後にdelete this の場合、AddRefした側が今後このクラスを使用しようとするとアクセス違反
となるような気がするのですが、実際はこうはならないのでしょうか?
回答
-
Interlocked だけでいえば起きえます。
ただし、実際にはそういったシビアな状況になることはないと予想されます。たとえば、Release で 0 になる状況で、後から、あるいは同時に AddRef することは誰かが何か間違えています。
間違えている可能性としては、自分の分以外の参照カウントを減らそうとしている、あるいは参照カウントを増やさずに使っているということです。
(AddRef を実行しようとする人は参照を保持しているはずなので、 1 以上のはずだし、それを Release しようとするのは「AddRef したいのになぜか先に Release する」か、「自分の知らない誰かが勝手に Release する」か、「自分が参照カウント増やし忘れてた」かでしょう)- 編集済み AzuleanMVP, Moderator 2013年7月6日 11:01 少し加筆
- 回答としてマーク mr.setup 2013年7月6日 11:14
すべての返信
-
Interlocked だけでいえば起きえます。
ただし、実際にはそういったシビアな状況になることはないと予想されます。たとえば、Release で 0 になる状況で、後から、あるいは同時に AddRef することは誰かが何か間違えています。
間違えている可能性としては、自分の分以外の参照カウントを減らそうとしている、あるいは参照カウントを増やさずに使っているということです。
(AddRef を実行しようとする人は参照を保持しているはずなので、 1 以上のはずだし、それを Release しようとするのは「AddRef したいのになぜか先に Release する」か、「自分の知らない誰かが勝手に Release する」か、「自分が参照カウント増やし忘れてた」かでしょう)- 編集済み AzuleanMVP, Moderator 2013年7月6日 11:01 少し加筆
- 回答としてマーク mr.setup 2013年7月6日 11:14
-