ロック数の管理
DLLサーバではLockServer()、class object、coclassの利用数を数えることで、
COMサーバが解放可能であるかチェックしていました。
EXEサーバでは、他のプロセスによってclass objectが作成されるたびにLockServer()されるようですので、
LockServer()、coclassの利用数を数えることでCOMサーバが解放可能であるかをチェックできます。
なお、class objectはCOMシステムに登録した時点でAddRef()されるため、
class objectの利用数は、COMサーバが解放可能であるかを知るためには利用できないようです。
DLLサーバを実装する場合と同様に、EXEサーバでも
グローバル変数を用意してロック数を数えることは可能です。
この場合、DLLと異なる点は、ロック数がゼロになった時点で、
EXEサーバはサーバプロセス自身を終了させることになります。
具体的には、CoSuspendClassObjects()させてからロック数がゼロのままであることを確認のうえ、
CoRevokeClassObject()などの終了処理を行うことになります。
しかし、ロック数を増減させたり、ロック数がゼロになった時点でCoSuspendClassObjects()を呼び出す部分は、
実装を間違えると不具合の原因になります。
そこでEXEサーバのロック数管理については、COMシステムが以下の管理用関数を提供してくれています。
これらの関数はプロセスに関連づけられたロック数を操作するため、DLLサーバから呼び出してはいけません。
CoAddRefServerProcess() | EXEサーバのロック数を1増やす。 |
CoReleaseServerProcess() | EXEサーバのロック数を1減らし、ロック数が0になった場合はCoSuspendClassObjects()を呼び出す。また、減らした後のロック数を返す。 |
ロック数管理関数を用いた例
これらの管理用関数を使うと、EXEサーバのロック数は次の2つの関数で管理できます。
この例では、EXEサーバのロック数が0になった場合には、PostQuitMessage()を利用してメッセージキューを終了させています。
void LockServerProcess()
{
CoAddRefServerProcess();
}
void UnlockServerProcess()
{
if ( CoReleaseServerProcess() == 0 ) {
PostQuitMessage(0);
}
}
これらの関数をclass objectのLockServer()、およびcoclassの作成と解放時に呼び出すことで、
EXEサーバの利用状態を管理できます。
class objectのLockServer()は、例えば次のようになります。
HRESULT STDMETHODCALLTYPE CIchigo2Factory::LockServer( BOOL fLock )
{
if ( fLock ) {
LockServerProcess();
} else {
UnlockServerProcess();
}
return S_OK;
}
また、coclassのコンストラクタとデストラクタは、例えば次のようになります。
CIchigo2::CIchigo2() : m_nRef(1)
{
LockServerProcess();
}
CIchigo2::~CIchigo2()
{
UnlockServerProcess();
}
関連ページ
COM/ActiveXの解説ページ 目次
前の項目: コマンドラインの解析
次の項目: class objectの登録