Out of Memory

ごめん、忘れてた。

目次

Blog 利用状況

ニュース

2008年7月1日
Microsoft MVP for Developer Tools - Visual C++ を再受賞しました。
2008年2月某日
MVPアワードがVisual C++に変更になりました。
2007年10月23日
blogタイトルを変更しました。
2007年7月1日
Microsoft MVP for Windows - SDKを受賞しました!
2007年6月20日
スキル「ニュース欄ハック」を覚えた!
2006年12月14日
記念すべき初エントリ
2006年12月3日
わんくま同盟に加盟しました。

カレンダー

中の人

aetos

顔写真

埼玉を馬鹿にする奴は俺が許さん。

基本的に知ったかぶり。興味を持った技術に手を出して、ちょっと齧りはするものの、それを応用して何か形にするまでは及ばずに飽きて放り出す人。

Microsoft MVP for Windows SDK July 2007 - February 2008, Microsoft MVP for Visual C++ February 2008 - June 2009
Microsoft MVP for Windows SDK
July 2007 - February 2008
Microsoft MVP for Visual C++
February 2008 - June 2009

アクセサリ

あわせて読みたい

e-Words

アフィリエイト

記事カテゴリ

書庫

日記カテゴリ

COMとスレッドセーフ

MTAとかは当たり前にスレッドセーフなので置いといて。

DllGetClassObjectとDllCanUnloadNowとか、クラスファクトリもスレッドセーフにしなきゃならないですよね?

投稿日時 : 2007年12月21日 14:35

Feedback

# re: COMとスレッドセーフ 2007/12/21 18:52 シャノン

クラスファクトリは、STAクラスのファクトリなら考えなくていいかもしれない。

# re: COMとスレッドセーフ 2007/12/21 22:58 Atata!!

プロセス内にSTAスレッドは複数存在できるので、基本的にインプロセスサーバDLLのすべてのエクスポート関数とクラスファクトリはスレッドセーフでなければなりません。
と Effective COM かどこかに書いてた気がします。

# re: COMとスレッドセーフ 2007/12/21 23:43 シャノン

うぃ。

で、DllCanUnloadNowがスレッドセーフでなければならないということは、モジュールロックカウンタは排他制御しなければならんというわけで。

STDAPI DllCanUnloadNow()
{
 if( moduleCount == 0 )
 {
  //※
  return S_OK;
 }

 return S_FALSE;
}

※のタイミングで新しいインスタンスが作られることは阻止しなければならないと思うんですが、そこまで書いてるサンプルコードはまず見ない。

あと、クラスファクトリオブジェクトが属するアパートメントは何なんだろう? と思うわけなんですが、試してみた結果、DllGetClassObject や IClassFactory::CreateInstance は、その引数に渡される CLSID を持つクラスのスレッドコンテキストで呼ばれるみたいだと。
DllGetClassObject が、呼ばれる都度、新しいクラスファクトリオブジェクトを作って返す場合、かつ、そのクラスファクトリオブジェクトが STA オブジェクトしか作らない場合、クラスファクトリのメソッドが呼ばれるスレッドは固定? これは試してみないといかんな。

ちなみに、DllGetClassObject が、呼ばれる都度、新しいクラスファクトリオブジェクトを作る場合、クラスファクトリはスレッドセーフを考慮しなくてよい、と解説されてるものも目にしますが、嘘ですね。
あと、DLL のエクスポート関数は常にプロセスのプライマリSTAで実行されるという記述も見かけますが、嘘ですね。

# re: COMとスレッドセーフ 2007/12/22 0:26 Atata!!

> DllGetClassObject が、呼ばれる都度、新しいクラスファクトリオブジェクトを作って返す場合、かつ、そのクラスファクトリオブジェクトが STA オブジェクトしか作らない場合、クラスファクトリのメソッドが呼ばれるスレッドは固定? これは試してみないといかんな。

固定がどこを指してるのかは分かりませんが、呼び出し元のアパートメントに依存するのではないでしょーか。


> あと、DLL のエクスポート関数は常にプロセスのプライマリSTAで実行されるという記述も見かけますが、嘘ですね。

コンポーネントのThreadingModelが設定されていない場合、CoFreeUnusedLibraries(Ex)を直接呼び出さなければ、この動作で正しいはずです。
CoFreeUnusedLibraries(Ex)を直接呼び出した場合、DllCanUnloadNowは呼び出したスレッドのコンテキストで実行されます。

この場合でも、プライマリSTAスレッド以外のCoUninitialize呼び出しによるDllCanUnloadNowの呼び出しは発生しないではないかと思っています。
(この動作は未検証)

タイトル  
名前  
Url
コメント